diff --git a/stdiet-admin/src/main/java/com/stdiet/web/controller/custom/SysRecipesController.java b/stdiet-admin/src/main/java/com/stdiet/web/controller/custom/SysRecipesController.java index e27b04217..9aeb2de2a 100644 --- a/stdiet-admin/src/main/java/com/stdiet/web/controller/custom/SysRecipesController.java +++ b/stdiet-admin/src/main/java/com/stdiet/web/controller/custom/SysRecipesController.java @@ -10,6 +10,8 @@ import com.stdiet.custom.service.ISysRecipesService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import java.util.List; + @RestController @RequestMapping("/custom/recipes") public class SysRecipesController extends BaseController { @@ -39,6 +41,11 @@ public class SysRecipesController extends BaseController { } } + @PostMapping(value = "/menu/replace") + public AjaxResult replaceMenu(@RequestBody List<SysRecipesDailyDishes> dishes) { + return AjaxResult.success(sysRecipesService.replaceDishes(dishes)); + } + /** * 修改食谱菜品 * diff --git a/stdiet-custom/src/main/java/com/stdiet/custom/mapper/SysRecipesMapper.java b/stdiet-custom/src/main/java/com/stdiet/custom/mapper/SysRecipesMapper.java index da961cc3e..5f184f629 100644 --- a/stdiet-custom/src/main/java/com/stdiet/custom/mapper/SysRecipesMapper.java +++ b/stdiet-custom/src/main/java/com/stdiet/custom/mapper/SysRecipesMapper.java @@ -26,5 +26,7 @@ public interface SysRecipesMapper { public int deleteDishes(Long id); + public int deleteMenu(Long id); + public List<SysRecipesDailyDishes> selectDishesByMenuId(Long id); } diff --git a/stdiet-custom/src/main/java/com/stdiet/custom/service/ISysRecipesService.java b/stdiet-custom/src/main/java/com/stdiet/custom/service/ISysRecipesService.java index 54b7805a2..1d30b460b 100644 --- a/stdiet-custom/src/main/java/com/stdiet/custom/service/ISysRecipesService.java +++ b/stdiet-custom/src/main/java/com/stdiet/custom/service/ISysRecipesService.java @@ -4,6 +4,7 @@ import com.stdiet.custom.domain.SysRecipes; import com.stdiet.custom.domain.SysRecipesDaily; import com.stdiet.custom.domain.SysRecipesDailyDishes; +import java.sql.Array; import java.util.List; public interface ISysRecipesService { @@ -20,4 +21,6 @@ public interface ISysRecipesService { public int deleteDishes(Long id); + public Long[] replaceDishes(List<SysRecipesDailyDishes> sysRecipesDailyDishes); + } diff --git a/stdiet-custom/src/main/java/com/stdiet/custom/service/impl/SysRecipesServiceImpl.java b/stdiet-custom/src/main/java/com/stdiet/custom/service/impl/SysRecipesServiceImpl.java index e18f40614..8186a3c73 100644 --- a/stdiet-custom/src/main/java/com/stdiet/custom/service/impl/SysRecipesServiceImpl.java +++ b/stdiet-custom/src/main/java/com/stdiet/custom/service/impl/SysRecipesServiceImpl.java @@ -1,6 +1,5 @@ package com.stdiet.custom.service.impl; -import com.stdiet.common.utils.StringUtils; import com.stdiet.custom.domain.SysRecipes; import com.stdiet.custom.domain.SysRecipesDaily; import com.stdiet.custom.domain.SysRecipesDailyDishes; @@ -62,6 +61,7 @@ public class SysRecipesServiceImpl implements ISysRecipesService { return rows; } + @Override public List<SysRecipes> selectSysRecipesByRecipesId(Long id) { return sysRecipesMapper.selectSysRecipesByRecipesId(id); @@ -86,4 +86,20 @@ public class SysRecipesServiceImpl implements ISysRecipesService { public int deleteDishes(Long id) { return sysRecipesMapper.deleteDishes(id); } + + @Override + public Long[] replaceDishes(List<SysRecipesDailyDishes> sysRecipesDailyDishes) { + // 删除原有 + sysRecipesMapper.deleteMenu(sysRecipesDailyDishes.get(0).getMenuId()); + // 插入新的 + int row = sysRecipesMapper.bashAddDishes(sysRecipesDailyDishes); + if (row > 0) { + Long[] ids = new Long[sysRecipesDailyDishes.size()]; + for (int i = 0; i < sysRecipesDailyDishes.size(); i++) { + ids[i] = sysRecipesDailyDishes.get(i).getId(); + } + return ids; + } + return null; + } } diff --git a/stdiet-custom/src/main/resources/mapper/custom/SysRecipesMapper.xml b/stdiet-custom/src/main/resources/mapper/custom/SysRecipesMapper.xml index 9edc9c56b..72e771e3c 100644 --- a/stdiet-custom/src/main/resources/mapper/custom/SysRecipesMapper.xml +++ b/stdiet-custom/src/main/resources/mapper/custom/SysRecipesMapper.xml @@ -116,6 +116,11 @@ delete from sys_customer_menu_dishes where id = #{id} </delete> + <!-- 删除整天食谱 --> + <delete id="deleteMenu" parameterType="Long"> + delete from sys_customer_menu_dishes where menu_id = #{id} + </delete> + <!-- 查询已有食谱天数--> <select id="getNumDayByCusId" parameterType="Long" resultType="Integer"> select count(*) from sys_customer_daily_menu where cus_id = #{id} @@ -141,7 +146,7 @@ </insert> <!-- 新增菜单对应菜品--> - <insert id="bashAddDishes" > + <insert id="bashAddDishes" useGeneratedKeys="true" keyProperty="id"> insert into sys_customer_menu_dishes (menu_id, type, dishes_id, remark, detail) values <foreach collection="list" separator="," item="item" index="index"> (#{item.menuId}, #{item.type}, #{item.dishesId}, #{item.remark}, #{item.detail, jdbcType=OTHER, typeHandler=com.stdiet.custom.typehandler.ArrayJsonHandler}) diff --git a/stdiet-ui/src/api/custom/recipes.js b/stdiet-ui/src/api/custom/recipes.js index f8ecdbd6c..3842cc8d1 100644 --- a/stdiet-ui/src/api/custom/recipes.js +++ b/stdiet-ui/src/api/custom/recipes.js @@ -37,3 +37,11 @@ export function deleteDishesApi(id) { method: "delete" }); } + +export function replaceMenuApi(data) { + return request({ + url: "/custom/recipes/menu/replace", + method: "post", + data + }); +} diff --git a/stdiet-ui/src/components/HealthyView/RemarkCom/index.vue b/stdiet-ui/src/components/HealthyView/RemarkCom/index.vue index 74081b18f..7f10eba8e 100644 --- a/stdiet-ui/src/components/HealthyView/RemarkCom/index.vue +++ b/stdiet-ui/src/components/HealthyView/RemarkCom/index.vue @@ -45,7 +45,7 @@ export default { }, watch: { value(val) { - console.log(val); + // console.log(val); this.nData = val; }, nData(val) { diff --git a/stdiet-ui/src/components/OrderDrawer/index.vue b/stdiet-ui/src/components/OrderDrawer/index.vue index 3ba615c2b..4aa7d8682 100644 --- a/stdiet-ui/src/components/OrderDrawer/index.vue +++ b/stdiet-ui/src/components/OrderDrawer/index.vue @@ -182,7 +182,7 @@ export default { } if (idx === res.rows.length - 1) { arr.forEach((obj) => { - console.log({ obj }); + // console.log({ obj }); if (obj.children) { obj.amount = obj.children.reduce( (a, c) => a + (c.afterSaleCommissOrder === 0 ? c.amount : 0), @@ -193,7 +193,7 @@ export default { } return arr; }, []); - console.log(this.orderList); + // console.log(this.orderList); this.loading = false; }); }, diff --git a/stdiet-ui/src/components/PhysicalSignsRemark/index.vue b/stdiet-ui/src/components/PhysicalSignsRemark/index.vue index ab3b89249..b4aaf2c93 100644 --- a/stdiet-ui/src/components/PhysicalSignsRemark/index.vue +++ b/stdiet-ui/src/components/PhysicalSignsRemark/index.vue @@ -52,7 +52,7 @@ export default { }, methods: { showDialog(data, healthy, type) { - console.log(healthy) + // console.log(healthy) this.data = data; this.type = type; this.title = "修改" + `「${data.name}」` + "备注"; diff --git a/stdiet-ui/src/components/RecipesPlanDrawer/index.vue b/stdiet-ui/src/components/RecipesPlanDrawer/index.vue index 69dac7d95..cc8976eb9 100644 --- a/stdiet-ui/src/components/RecipesPlanDrawer/index.vue +++ b/stdiet-ui/src/components/RecipesPlanDrawer/index.vue @@ -75,7 +75,7 @@ {{ `${scope.row.startDate} 至 ${scope.row.endDate}` }} </template> </el-table-column> - <el-table-column label="发送" align="center"> + <el-table-column label="发送" align="center" width="80"> <template slot-scope="scope"> <el-switch v-model="!!scope.row.sendFlag" diff --git a/stdiet-ui/src/store/modules/recipes.js b/stdiet-ui/src/store/modules/recipes.js index abf69b5c3..9a5f10ae1 100644 --- a/stdiet-ui/src/store/modules/recipes.js +++ b/stdiet-ui/src/store/modules/recipes.js @@ -5,12 +5,15 @@ import { updateDishesDetailApi, addDishesApi, deleteDishesApi, - addRecipesApi + addRecipesApi, + replaceMenuApi } from "@/api/custom/recipes"; import { getDishesMenuTypes } from "@/api/custom/dishes"; import { getRecipesTemplateDetail } from "@/api/custom/recipesTemplate"; import { getRecipesPlan, updateRecipesPlan } from "@/api/custom/recipesPlan"; import { getDicts } from "@/api/system/dict/data"; +import { addShortCut } from "@/utils/shortCutUtils"; +import { messageTypes } from "@/utils"; const oriState = { cusId: undefined, @@ -31,8 +34,10 @@ const oriState = { endNum: 0, reviewStatus: 0, templateInfo: undefined, - copyData: undefined, - canCopyMenuTypes: [], + // + // copyData: undefined, + // canCopyMenuTypes: [], + // fontSize: parseInt(localStorage.getItem("fontSize")) || 12, dishBigClassOptions: [], dishSmallClassOptions: [], @@ -40,7 +45,9 @@ const oriState = { leftShow: false, notRecIgds: [], avoidFoodIds: [], - igdTypeOptions: [] + igdTypeOptions: [], + // + curShortCutObj: {} }; const mutations = { @@ -113,6 +120,9 @@ const mutations = { setNotRecIgds(state, payload) { state.notRecIgds = payload.data; }, + setCurShortCutObj(state, payload) { + state.curShortCutObj = payload.data; + }, setDate(state, payload) { state.startDate = payload.startDate; state.endDate = payload.endDate; @@ -461,6 +471,45 @@ const actions = { commit("deleteSomeDayDishes", payload); } }, + async replaceMenu({ commit, state }, payload) { + const rData = JSON.parse(JSON.stringify(state.recipesData)); + if (state.recipesId) { + const tarData = { + ...payload.data, + dishes: payload.data.dishes.map(obj => ({ + ...obj, + id: -1 + })) + }; + const menuData = payload.data.dishes.map(dObj => ({ + menuId: payload.data.id, + dishesId: dObj.dishesId, + type: dObj.type, + remark: dObj.remark, + detail: dObj.igdList.map(igd => ({ + id: igd.id, + weight: igd.weight, + cus_unit: igd.cusUnit, + cus_weight: igd.cusWeight + })) + })); + const result = await replaceMenuApi(menuData); + if (result.code === 200) { + result.data.forEach((id, idx) => { + tarData.dishes[idx].id = id; + }); + rData[payload.num] = tarData; + commit("updateStateData", { + recipesData: rData + }); + } + } else { + rData[payload.num] = payload.data; + commit("updateStateData", { + recipesData: rData + }); + } + }, async deleteMenu({ commit }, payload) {}, async setCopyData({ commit, state }, payload) { return new Promise(async (res, rej) => { @@ -470,16 +519,29 @@ const actions = { if (tarDishes) { const response = await getDishesMenuTypes(tarDishes.dishesId); if (response.code === 200) { - commit("updateStateData", { - copyData: tarDishes, - canCopyMenuTypes: response.data.type.split(",") + // commit("updateStateData", { + // copyData: tarDishes, + // canCopyMenuTypes: type + // }); + addShortCut({ + id: new Date().getTime(), + name: tarDishes.name, + type: response.data.type.split(",").sort(), + data: tarDishes + }).then(() => { + window.postMessage( + { + type: messageTypes.UPDATE_SHORTCUT + }, + "*" + ); }); - res("复制成功"); + res("添加成功"); } else { - rej("复制失败"); + rej("添加失败"); } } else { - rej("复制失败"); + rej("添加失败"); } }); } diff --git a/stdiet-ui/src/utils/index.js b/stdiet-ui/src/utils/index.js index 918580f7b..beb444f36 100644 --- a/stdiet-ui/src/utils/index.js +++ b/stdiet-ui/src/utils/index.js @@ -1,18 +1,25 @@ -import { parseTime } from './ruoyi' +import { parseTime } from "./ruoyi"; /** * 表格时间格式化 */ export function formatDate(cellValue) { if (cellValue == null || cellValue == "") return ""; - var date = new Date(cellValue) - var year = date.getFullYear() - var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1 - var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate() - var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours() - var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes() - var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds() - return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds + var date = new Date(cellValue); + var year = date.getFullYear(); + var month = + date.getMonth() + 1 < 10 + ? "0" + (date.getMonth() + 1) + : date.getMonth() + 1; + var day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate(); + var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours(); + var minutes = + date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes(); + var seconds = + date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds(); + return ( + year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds + ); } /** @@ -21,40 +28,40 @@ export function formatDate(cellValue) { * @returns {string} */ export function formatTime(time, option) { - if (('' + time).length === 10) { - time = parseInt(time) * 1000 + if (("" + time).length === 10) { + time = parseInt(time) * 1000; } else { - time = +time + time = +time; } - const d = new Date(time) - const now = Date.now() + const d = new Date(time); + const now = Date.now(); - const diff = (now - d) / 1000 + const diff = (now - d) / 1000; if (diff < 30) { - return '刚刚' + return "刚刚"; } else if (diff < 3600) { // less 1 hour - return Math.ceil(diff / 60) + '分钟前' + return Math.ceil(diff / 60) + "分钟前"; } else if (diff < 3600 * 24) { - return Math.ceil(diff / 3600) + '小时前' + return Math.ceil(diff / 3600) + "小时前"; } else if (diff < 3600 * 24 * 2) { - return '1天前' + return "1天前"; } if (option) { - return parseTime(time, option) + return parseTime(time, option); } else { return ( d.getMonth() + 1 + - '月' + + "月" + d.getDate() + - '日' + + "日" + d.getHours() + - '时' + + "时" + d.getMinutes() + - '分' - ) + "分" + ); } } @@ -63,18 +70,18 @@ export function formatTime(time, option) { * @returns {Object} */ export function getQueryObject(url) { - url = url == null ? window.location.href : url - const search = url.substring(url.lastIndexOf('?') + 1) - const obj = {} - const reg = /([^?&=]+)=([^?&=]*)/g + url = url == null ? window.location.href : url; + const search = url.substring(url.lastIndexOf("?") + 1); + const obj = {}; + const reg = /([^?&=]+)=([^?&=]*)/g; search.replace(reg, (rs, $1, $2) => { - const name = decodeURIComponent($1) - let val = decodeURIComponent($2) - val = String(val) - obj[name] = val - return rs - }) - return obj + const name = decodeURIComponent($1); + let val = decodeURIComponent($2); + val = String(val); + obj[name] = val; + return rs; + }); + return obj; } /** @@ -83,14 +90,14 @@ export function getQueryObject(url) { */ export function byteLength(str) { // returns the byte length of an utf8 string - let s = str.length + let s = str.length; for (var i = str.length - 1; i >= 0; i--) { - const code = str.charCodeAt(i) - if (code > 0x7f && code <= 0x7ff) s++ - else if (code > 0x7ff && code <= 0xffff) s += 2 - if (code >= 0xDC00 && code <= 0xDFFF) i-- + const code = str.charCodeAt(i); + if (code > 0x7f && code <= 0x7ff) s++; + else if (code > 0x7ff && code <= 0xffff) s += 2; + if (code >= 0xdc00 && code <= 0xdfff) i--; } - return s + return s; } /** @@ -98,13 +105,13 @@ export function byteLength(str) { * @returns {Array} */ export function cleanArray(actual) { - const newArray = [] + const newArray = []; for (let i = 0; i < actual.length; i++) { if (actual[i]) { - newArray.push(actual[i]) + newArray.push(actual[i]); } } - return newArray + return newArray; } /** @@ -112,13 +119,13 @@ export function cleanArray(actual) { * @returns {Array} */ export function param(json) { - if (!json) return '' + if (!json) return ""; return cleanArray( Object.keys(json).map(key => { - if (json[key] === undefined) return '' - return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]) + if (json[key] === undefined) return ""; + return encodeURIComponent(key) + "=" + encodeURIComponent(json[key]); }) - ).join('&') + ).join("&"); } /** @@ -126,21 +133,21 @@ export function param(json) { * @returns {Object} */ export function param2Obj(url) { - const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') + const search = decodeURIComponent(url.split("?")[1]).replace(/\+/g, " "); if (!search) { - return {} + return {}; } - const obj = {} - const searchArr = search.split('&') + const obj = {}; + const searchArr = search.split("&"); searchArr.forEach(v => { - const index = v.indexOf('=') + const index = v.indexOf("="); if (index !== -1) { - const name = v.substring(0, index) - const val = v.substring(index + 1, v.length) - obj[name] = val + const name = v.substring(0, index); + const val = v.substring(index + 1, v.length); + obj[name] = val; } - }) - return obj + }); + return obj; } /** @@ -148,9 +155,9 @@ export function param2Obj(url) { * @returns {string} */ export function html2Text(val) { - const div = document.createElement('div') - div.innerHTML = val - return div.textContent || div.innerText + const div = document.createElement("div"); + div.innerHTML = val; + return div.textContent || div.innerText; } /** @@ -160,21 +167,21 @@ export function html2Text(val) { * @returns {Object} */ export function objectMerge(target, source) { - if (typeof target !== 'object') { - target = {} + if (typeof target !== "object") { + target = {}; } if (Array.isArray(source)) { - return source.slice() + return source.slice(); } Object.keys(source).forEach(property => { - const sourceProperty = source[property] - if (typeof sourceProperty === 'object') { - target[property] = objectMerge(target[property], sourceProperty) + const sourceProperty = source[property]; + if (typeof sourceProperty === "object") { + target[property] = objectMerge(target[property], sourceProperty); } else { - target[property] = sourceProperty + target[property] = sourceProperty; } - }) - return target + }); + return target; } /** @@ -183,18 +190,18 @@ export function objectMerge(target, source) { */ export function toggleClass(element, className) { if (!element || !className) { - return + return; } - let classString = element.className - const nameIndex = classString.indexOf(className) + let classString = element.className; + const nameIndex = classString.indexOf(className); if (nameIndex === -1) { - classString += '' + className + classString += "" + className; } else { classString = classString.substr(0, nameIndex) + - classString.substr(nameIndex + className.length) + classString.substr(nameIndex + className.length); } - element.className = classString + element.className = classString; } /** @@ -202,10 +209,10 @@ export function toggleClass(element, className) { * @returns {Date} */ export function getTime(type) { - if (type === 'start') { - return new Date().getTime() - 3600 * 1000 * 24 * 90 + if (type === "start") { + return new Date().getTime() - 3600 * 1000 * 24 * 90; } else { - return new Date(new Date().toDateString()) + return new Date(new Date().toDateString()); } } @@ -216,38 +223,38 @@ export function getTime(type) { * @return {*} */ export function debounce(func, wait, immediate) { - let timeout, args, context, timestamp, result + let timeout, args, context, timestamp, result; const later = function() { // 据上一次触发时间间隔 - const last = +new Date() - timestamp + const last = +new Date() - timestamp; // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait if (last < wait && last > 0) { - timeout = setTimeout(later, wait - last) + timeout = setTimeout(later, wait - last); } else { - timeout = null + timeout = null; // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用 if (!immediate) { - result = func.apply(context, args) - if (!timeout) context = args = null + result = func.apply(context, args); + if (!timeout) context = args = null; } } - } + }; return function(...args) { - context = this - timestamp = +new Date() - const callNow = immediate && !timeout + context = this; + timestamp = +new Date(); + const callNow = immediate && !timeout; // 如果延时不存在,重新设定延时 - if (!timeout) timeout = setTimeout(later, wait) + if (!timeout) timeout = setTimeout(later, wait); if (callNow) { - result = func.apply(context, args) - context = args = null + result = func.apply(context, args); + context = args = null; } - return result - } + return result; + }; } /** @@ -258,18 +265,18 @@ export function debounce(func, wait, immediate) { * @returns {Object} */ export function deepClone(source) { - if (!source && typeof source !== 'object') { - throw new Error('error arguments', 'deepClone') + if (!source && typeof source !== "object") { + throw new Error("error arguments", "deepClone"); } - const targetObj = source.constructor === Array ? [] : {} + const targetObj = source.constructor === Array ? [] : {}; Object.keys(source).forEach(keys => { - if (source[keys] && typeof source[keys] === 'object') { - targetObj[keys] = deepClone(source[keys]) + if (source[keys] && typeof source[keys] === "object") { + targetObj[keys] = deepClone(source[keys]); } else { - targetObj[keys] = source[keys] + targetObj[keys] = source[keys]; } - }) - return targetObj + }); + return targetObj; } /** @@ -277,16 +284,16 @@ export function deepClone(source) { * @returns {Array} */ export function uniqueArr(arr) { - return Array.from(new Set(arr)) + return Array.from(new Set(arr)); } /** * @returns {string} */ export function createUniqueString() { - const timestamp = +new Date() + '' - const randomNum = parseInt((1 + Math.random()) * 65536) + '' - return (+(randomNum + timestamp)).toString(32) + const timestamp = +new Date() + ""; + const randomNum = parseInt((1 + Math.random()) * 65536) + ""; + return (+(randomNum + timestamp)).toString(32); } /** @@ -296,7 +303,7 @@ export function createUniqueString() { * @returns {boolean} */ export function hasClass(ele, cls) { - return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) + return !!ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)")); } /** @@ -305,7 +312,7 @@ export function hasClass(ele, cls) { * @param {string} cls */ export function addClass(ele, cls) { - if (!hasClass(ele, cls)) ele.className += ' ' + cls + if (!hasClass(ele, cls)) ele.className += " " + cls; } /** @@ -315,76 +322,78 @@ export function addClass(ele, cls) { */ export function removeClass(ele, cls) { if (hasClass(ele, cls)) { - const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)') - ele.className = ele.className.replace(reg, ' ') + const reg = new RegExp("(\\s|^)" + cls + "(\\s|$)"); + ele.className = ele.className.replace(reg, " "); } } export function makeMap(str, expectsLowerCase) { - const map = Object.create(null) - const list = str.split(',') + const map = Object.create(null); + const list = str.split(","); for (let i = 0; i < list.length; i++) { - map[list[i]] = true + map[list[i]] = true; } - return expectsLowerCase - ? val => map[val.toLowerCase()] - : val => map[val] + return expectsLowerCase ? val => map[val.toLowerCase()] : val => map[val]; } - -export const exportDefault = 'export default ' + +export const exportDefault = "export default "; export const beautifierConf = { html: { - indent_size: '2', - indent_char: ' ', - max_preserve_newlines: '-1', + indent_size: "2", + indent_char: " ", + max_preserve_newlines: "-1", preserve_newlines: false, keep_array_indentation: false, break_chained_methods: false, - indent_scripts: 'separate', - brace_style: 'end-expand', + indent_scripts: "separate", + brace_style: "end-expand", space_before_conditional: true, unescape_strings: false, jslint_happy: false, end_with_newline: true, - wrap_line_length: '110', + wrap_line_length: "110", indent_inner_html: true, comma_first: false, e4x: true, indent_empty_lines: true }, js: { - indent_size: '2', - indent_char: ' ', - max_preserve_newlines: '-1', + indent_size: "2", + indent_char: " ", + max_preserve_newlines: "-1", preserve_newlines: false, keep_array_indentation: false, break_chained_methods: false, - indent_scripts: 'normal', - brace_style: 'end-expand', + indent_scripts: "normal", + brace_style: "end-expand", space_before_conditional: true, unescape_strings: false, jslint_happy: true, end_with_newline: true, - wrap_line_length: '110', + wrap_line_length: "110", indent_inner_html: true, comma_first: false, e4x: true, indent_empty_lines: true } -} +}; // 首字母大小 export function titleCase(str) { - return str.replace(/( |^)[a-z]/g, L => L.toUpperCase()) + return str.replace(/( |^)[a-z]/g, L => L.toUpperCase()); } // 下划转驼峰 export function camelCase(str) { - return str.replace(/-[a-z]/g, str1 => str1.substr(-1).toUpperCase()) + return str.replace(/-[a-z]/g, str1 => str1.substr(-1).toUpperCase()); } export function isNumberStr(str) { - return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str) + return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str); } - + +export const messageTypes = { + UPDATE_SHORTCUT: "updateShortCut", + UPDATE_CURRENT_SHORTCUT: "updateCurrentShortCut" +}; diff --git a/stdiet-ui/src/utils/shortCutUtils.js b/stdiet-ui/src/utils/shortCutUtils.js new file mode 100644 index 000000000..53fe07159 --- /dev/null +++ b/stdiet-ui/src/utils/shortCutUtils.js @@ -0,0 +1,52 @@ +export function getShortCut() { + return new Promise((res, rej) => { + try { + const data = JSON.parse(localStorage.getItem("shortCut") || "[]"); + res(data); + } catch (error) { + rej(error); + } + }); +} + +export async function addShortCut(data) { + const shortCutList = await getShortCut(); + return new Promise((res, rej) => { + try { + shortCutList.splice(0, 0, data); + localStorage.setItem("shortCut", JSON.stringify(shortCutList)); + res(); + } catch (error) { + rej(error); + } + }); +} + +export async function removeShortCut(id) { + const shortCutList = await getShortCut(); + return new Promise((res, rej) => { + try { + const newShortCutList = shortCutList.filter(obj => obj.id !== id); + localStorage.setItem("shortCut", JSON.stringify(newShortCutList)); + res(); + } catch (error) { + rej(error); + } + }); +} + +export async function editShortCut(data) { + const shortCutList = await getShortCut(); + return new Promise((res, rej) => { + try { + const tarObj = shortCutList.find(obj => obj.id === data.id); + Object.keys(data).forEach(key => { + tarObj[key] = data[key]; + }); + localStorage.setItem("shortCut", JSON.stringify(shortCutList)); + res(); + } catch (error) { + rej(error); + } + }); +} diff --git a/stdiet-ui/src/views/custom/recipesBuild/InfoView/ShortCutCom/index.vue b/stdiet-ui/src/views/custom/recipesBuild/InfoView/ShortCutCom/index.vue new file mode 100644 index 000000000..60485a3da --- /dev/null +++ b/stdiet-ui/src/views/custom/recipesBuild/InfoView/ShortCutCom/index.vue @@ -0,0 +1,191 @@ +<template> + <div class="short_cut_com_wrapper"> + <div class="header"> + <el-button icon="el-icon-refresh" size="mini" @click="getList" circle /> + </div> + <el-table + :data="dataList" + ref="shortCutTable" + highlight-current-row + @current-change="handleOnCurrentChange" + height="800" + > + <el-table-column prop="name" label="对象" align="center"> + <template slot-scope="scope"> + <el-popover + placement="left" + width="200" + trigger="click" + title="修改对象名称" + @hide="handleOnHide" + > + <el-input + v-model="scope.row.name" + @change="(val) => handleOnNameChange(val, scope.row)" + /> + <span slot="reference" style="cursor: pointer"> + {{ scope.row.name }} + </span> + </el-popover> + </template> + </el-table-column> + <el-table-column prop="type" label="可用类型" align="center"> + <template slot-scope="scope"> + <AutoHideInfo :data="translateType(scope.row.type)" :line="10" /> + </template> + </el-table-column> + <el-table-column prop="priview" label="预览" align="center"> + <template slot-scope="scope"> + <el-popover + placement="left" + trigger="click" + :title="`「${scope.row.name}」预览`" + > + <!-- 菜谱预览 --> + <RecipesCom + v-if="scope.row.type.includes('0')" + :data="scope.row.data" + :numDay="scope.row.data.numDay" + preview + /> + <!-- 菜品预览 --> + <el-table border :data="scope.row.data.igdList" v-else size="mini"> + <el-table-column align="center" label="食材" prop="name" /> + <el-table-column align="center" label="分量估算"> + <template slot-scope="scope"> + <span>{{ + `${cusWeightDict[scope.row.cusWeight]}${ + cusUnitDict[scope.row.cusUnit] + }` + }}</span> + </template> + </el-table-column> + <el-table-column align="center" label="重量(g)" prop="weight" /> + </el-table> + <el-button type="text" size="mini" slot="reference">预览</el-button> + </el-popover> + </template> + </el-table-column> + <el-table-column label="操作" :width="60" align="center"> + <template slot-scope="scope"> + <el-button type="text" size="mini" @click="handleOnDelete(scope.row)"> + 删除 + </el-button> + </template> + </el-table-column> + </el-table> + </div> +</template> +<script> +import { + getShortCut, + removeShortCut, + editShortCut, +} from "@/utils/shortCutUtils"; +import AutoHideInfo from "@/components/AutoHideInfo"; +import { createNamespacedHelpers } from "vuex"; +import RecipesCom from "../../RecipesView/RecipesCom"; +const { mapState, mapMutations, mapGetters } = createNamespacedHelpers( + "recipes" +); +import { messageTypes } from "@/utils"; +export default { + name: "ShortCutCom", + components: { + AutoHideInfo, + RecipesCom, + }, + data() { + return { + dataList: [], + modifingId: 0, + }; + }, + created() { + this.getList(); + }, + mounted() { + window.addEventListener("storage", this.storageListener); + window.addEventListener("message", this.messageListener); + }, + beforeDestroy() { + window.removeEventListener("storage", this.storageListener); + window.removeEventListener("message", this.messageListener); + }, + computed: { + names() { + return this.dataList.map((obj) => obj.name); + }, + ...mapState(["curShortCutObj"]), + ...mapGetters(["cusUnitDict", "cusWeightDict"]), + }, + methods: { + storageListener(e) { + const { key } = e; + if (key === "shortCut") { + this.getList(); + } + }, + messageListener(e) { + const { data } = e; + if (data.type === messageTypes.UPDATE_SHORTCUT) { + this.getList(); + } + }, + getList() { + getShortCut().then((data) => { + this.dataList = data; + // console.log(this.dataList); + }); + }, + handleOnDelete(data) { + removeShortCut(data.id).then((res) => { + this.getList(); + }); + }, + handleOnCurrentChange(data) { + this.setCurShortCutObj({ data }); + }, + handleOnNameChange(val, data) { + this.modifingId = data.id; + }, + handleOnHide() { + if (this.modifingId) { + const tarObj = this.dataList.find((obj) => obj.id === this.modifingId); + editShortCut({ + id: this.modifingId, + name: tarObj.name, + }); + } + }, + translateType(type) { + return type.map((t) => { + if (t === "0") { + return "整天"; + } else if (t === "1") { + return "早餐"; + } else if (t === "2") { + return "早加餐"; + } else if (t === "3") { + return "午餐"; + } else if (t === "4") { + return "午加餐"; + } else if (t === "5") { + return "晚餐"; + } else if (t === "6") { + return "晚加餐"; + } + }); + }, + ...mapMutations(["setCurShortCutObj"]), + }, +}; +</script> +<style lang="scss" scoped> +.short_cut_com_wrapper { + .header { + text-align: right; + padding-bottom: 8px; + } +} +</style> diff --git a/stdiet-ui/src/views/custom/recipesBuild/InfoView/index.vue b/stdiet-ui/src/views/custom/recipesBuild/InfoView/index.vue index 52f59eec1..27bbb1bd3 100644 --- a/stdiet-ui/src/views/custom/recipesBuild/InfoView/index.vue +++ b/stdiet-ui/src/views/custom/recipesBuild/InfoView/index.vue @@ -27,7 +27,7 @@ </div> </el-tab-pane> <el-tab-pane label="快捷列表" name="3"> - + <ShortCutCom /> </el-tab-pane> </el-tabs> </div> @@ -40,6 +40,7 @@ import HealthyView from "@/components/HealthyView"; import BodySignView from "@/components/BodySignView"; import WeaklyAnalyzeCom from "./WeaklyAnalyzeCom"; import DailyAnalyzeCom from "./DailyAnalyzeCom"; +import ShortCutCom from "./ShortCutCom"; export default { name: "InfoView", data() { @@ -52,6 +53,7 @@ export default { TemplateInfoView, WeaklyAnalyzeCom, DailyAnalyzeCom, + ShortCutCom, }, computed: { max() { diff --git a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/EditableText/index.vue b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/EditableText/index.vue index 5d72163cb..b8789887c 100644 --- a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/EditableText/index.vue +++ b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/EditableText/index.vue @@ -21,10 +21,10 @@ export default { editing: false, }; }, - props: ["value"], + props: ["value", "disabled"], methods: { handleOnClick(e) { - if (!this.editing) { + if (!this.editing && !this.disabled) { this.editing = true; this.$nextTick(() => { this.$refs["inputRef"].focus(); diff --git a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/EditableUnit/index.vue b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/EditableUnit/index.vue index a72998e82..359072686 100644 --- a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/EditableUnit/index.vue +++ b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/EditableUnit/index.vue @@ -40,7 +40,7 @@ import { createNamespacedHelpers } from "vuex"; const { mapState, mapGetters } = createNamespacedHelpers("recipes"); export default { name: "EditableUnit", - props: ["weight", "unit"], + props: ["weight", "unit", "disabled"], mounted() { window.addEventListener("click", this.handleOnWindowClick); }, @@ -56,7 +56,7 @@ export default { }, methods: { handleOnClick(e) { - if (!this.editing) { + if (!this.editing && !this.disabled) { setTimeout(() => { this.editing = true; }, 0); diff --git a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/index.vue b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/index.vue index db4af82eb..5a7fb7b82 100644 --- a/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/index.vue +++ b/stdiet-ui/src/views/custom/recipesBuild/RecipesView/RecipesCom/index.vue @@ -9,33 +9,80 @@ size="mini" header-row-class-name="recipes_header" :cell-class-name="cellClassName" - :style="`outline: ${currentDay === num ? '1px solid #d53950' : 'none'}`" + :style="`outline: ${ + currentDay === num && !preview ? '1px solid #d53950' : 'none' + }`" > <el-table-column prop="type" :width="80" align="center"> <template slot="header"> - <div class="pointer_style" @click="handleOnResetCurrentDay"> - {{ `第${numDay}天` }} - </div> - </template> - <template slot-scope="scope"> <el-popover - placement="top" + placement="right" + :open-delay="200" trigger="hover" - :title="typeFormatter(scope.row)" + :title="`第${numDay}天`" + :disabled="preview" > <div> <el-button size="mini" type="primary" - @click="handleOnMenuTypeClick(scope.row)" - >添加 + icon="el-icon-position" + @click="handleOnMenuCopyClick" + > + 添加快捷 </el-button> <el-button size="mini" type="primary" - @click="handleOnPaste(scope.row.type)" - v-if="canCopyMenuTypes.includes(scope.row.type)" - >粘贴</el-button + icon="el-icon-refresh" + v-if="shouldPasteShow('0')" + @click="handleOnMenuPasteClick" + >快捷替换</el-button + > + <div v-else-if="curShortCutObj.type" style="margin-top: 8px"> + <el-button + icon="el-icon-right" + size="mini" + type="primary" + v-for="item in curShortCutObj.type" + :key="item" + @click="handleOnShortCutMenuAdd(item)" + >{{ menuTypeDict[item] }}</el-button + > + </div> + </div> + <div + class="pointer_style" + @click="handleOnResetCurrentDay" + slot="reference" + > + {{ `第${numDay}天` }} + </div> + </el-popover> + </template> + <template slot-scope="scope"> + <el-popover + placement="top" + trigger="hover" + :open-delay="200" + :title="typeFormatter(scope.row)" + :disabled="preview" + > + <div> + <el-button + size="mini" + type="primary" + icon="el-icon-plus" + @click="handleOnMenuTypeClick(scope.row)" + >添加菜品 + </el-button> + <el-button + size="mini" + type="primary" + icon="el-icon-position" + @click="handleOnShortCutMenuAdd(scope.row.type)" + v-if="shouldPasteShow(scope.row.type)" + >快捷添加</el-button > </div> <div @@ -52,7 +99,13 @@ <div class="pointer_style" @click="handleOnAdd">菜品</div> </template> <template slot-scope="scope"> - <el-popover placement="right" trigger="hover" :title="scope.row.name"> + <el-popover + placement="right" + :open-delay="200" + trigger="hover" + :title="scope.row.name" + :disabled="preview" + > <div> <div style="margin-bottom: 8px"> <el-button @@ -62,7 +115,7 @@ class="fun_button" @click="handleOnReplace(scope.row)" > - 替换 + 替换菜品 </el-button> <el-button type="danger" @@ -71,18 +124,18 @@ class="fun_button" @click="handleOnDelete(scope.row)" > - 删除 + 删除菜品 </el-button> </div> - <div> + <div style="margin-bottom: 8px"> <el-button type="primary" size="mini" - icon="el-icon-document-copy" + icon="el-icon-position" class="fun_button" @click="handleOnCopy(scope.row)" > - 复制 + 添加快捷 </el-button> <el-button type="primary" @@ -94,6 +147,18 @@ 修改餐类 </el-button> </div> + <div> + <el-button + type="primary" + size="mini" + icon="el-icon-refresh" + class="fun_button" + v-if="shouldPasteShow(scope.row.type)" + @click="handleOnShortCutReplace(scope.row)" + > + 快捷替换 + </el-button> + </div> </div> <div class="pointer_style" slot="reference"> {{ scope.row.name }} @@ -115,8 +180,10 @@ <el-popover v-else placement="right" + :open-delay="200" trigger="hover" :title="scope.row.igdName" + :disabled="preview" > <el-button type="danger" @@ -137,6 +204,7 @@ <EditableUnit :weight="scope.row.cusWeight" :unit="scope.row.cusUnit" + :disabled="preview" @onChange="(val) => handleOnCustomUnitChange(scope.row, val)" /> </template> @@ -145,6 +213,7 @@ <template slot-scope="scope"> <EditableText :value="scope.row.weight" + :disabled="preview" @onChange="(val) => handleOnWeightChange(scope.row, val)" /> </template> @@ -154,6 +223,7 @@ prop="proteinRatio" :width="60" align="center" + v-if="!preview" > <template slot="header"> <div class="pointer_style"> @@ -167,6 +237,7 @@ prop="fatRatio" :width="60" align="center" + v-if="!preview" > <template slot="header"> <div class="pointer_style"> @@ -180,6 +251,7 @@ prop="carbonRatio" :width="60" align="center" + v-if="!preview" > <template slot="header"> <div class="pointer_style"> @@ -194,6 +266,7 @@ :width="60" align="center" :formatter="nutriFormatter" + v-if="!preview" > <template slot="header"> <div class="pointer_style"> @@ -208,6 +281,7 @@ :width="60" align="center" :formatter="nutriFormatter" + v-if="!preview" > <template slot="header"> <div class="pointer_style"> @@ -222,6 +296,7 @@ :width="60" align="center" :formatter="nutriFormatter" + v-if="!preview" > <template slot="header"> <div class="pointer_style"> @@ -230,8 +305,8 @@ </div> </template> </el-table-column> - <el-table-column label="做法" prop="methods" /> - <el-table-column label="备注" prop="remark"> + <el-table-column label="做法" prop="methods" v-if="!preview" /> + <el-table-column label="备注" prop="remark" v-if="!preview"> <template slot-scope="scope"> <div v-if="!scope.row.remark" @@ -276,13 +351,15 @@ import DishesSettingDialog from "./DishesSettingDialog"; import VueScrollTo from "vue-scrollto"; import RemarkDialog from "./RemarkDialog"; import { processMenuData } from "./utils"; +import { addShortCut } from "@/utils/shortCutUtils"; +import { messageTypes } from "@/utils"; export default { name: "RecipesCom", props: { data: { type: Object, - default: [], + default: {}, required: true, }, name: { @@ -297,6 +374,10 @@ export default { type: Number, default: 0, }, + preview: { + type: Boolean, + default: false, + }, }, components: { EditableText, @@ -309,7 +390,16 @@ export default { // console.log(this.data); }, data() { - return {}; + return { + menuTypeDict: { + 1: "早餐", + 2: "早加餐", + 3: "午餐", + 4: "午加餐", + 5: "晚餐", + 6: "晚加餐", + }, + }; }, computed: { notIds() { @@ -327,15 +417,70 @@ export default { ...mapGetters(["typeDict"]), ...mapState([ "currentDay", - "copyData", + // "copyData", "fontSize", - "canCopyMenuTypes", + // "canCopyMenuTypes", "recipesId", "notRecIgds", "avoidFoodIds", + "curShortCutObj", + "healthyData", + "templateInfo", ]), }, methods: { + handleOnShortCutReplace(data) { + this.updateDishes({ + num: this.num, + data: { + ...this.curShortCutObj.data, + type: data.type, + id: data.id, + }, + actionType: "replace", + }).catch((err) => { + this.$message.error(err); + }); + }, + handleOnShortCutMenuAdd(type) { + const data = { + ...JSON.parse(JSON.stringify(this.curShortCutObj.data)), + type, + }; + if (!this.recipesId) { + // 未生成食谱时拷贝 + data.id = new Date().getTime(); + } + this.addDishes({ + num: this.num, + data, + }).catch((err) => { + this.$message.error(err); + }); + }, + handleOnMenuPasteClick() { + if (!this.curShortCutObj || !this.curShortCutObj.data.dishes) { + this.$message.error("快捷对象错误"); + return; + } + const { id } = this.data; + this.replaceMenu({ + num: this.num, + data: { + numDay: this.numDay, + id, + dishes: this.curShortCutObj.data.dishes.map((obj) => ({ + ...obj, + id: id + obj.id, + })), + }, + }); + }, + shouldPasteShow(type) { + return ( + this.curShortCutObj.type && this.curShortCutObj.type.includes(type) + ); + }, cellClassName({ row, column, rowIndex, columnIndex }) { // console.log({ row, column, rowIndex, columnIndex }); if (!columnIndex) { @@ -349,6 +494,9 @@ export default { } }, handleParentClick(e) { + if (this.preview) { + return; + } // 校验某天 this.setCurrentDay({ currentDay: this.num }); }, @@ -370,6 +518,9 @@ export default { return ((row.weight / 100) * row[col.property]).toFixed(1); }, handleOnResetCurrentDay(e) { + if (this.preview) { + return; + } e.stopPropagation(); // 取消高亮 this.resetCurrentDay({ currentDay: this.num }); @@ -379,6 +530,9 @@ export default { }, handleOnAdd() { // console.log(this.num); + if (this.preview) { + return; + } this.$refs.drawerRef.showDrawer({}); }, handleOnReplace(data) { @@ -398,25 +552,25 @@ export default { this.$message.error(err); }); }, - handleOnPaste(type) { - // console.log(this.copyData); - if (this.copyData) { - const data = { - ...JSON.parse(JSON.stringify(this.copyData)), - type, - }; - if (!this.recipesId) { - // 未生成食谱时拷贝 - data.id = new Date().getTime(); - } - this.addDishes({ - num: this.num, - data, - }).catch((err) => { - this.$message.error(err); - }); - } - }, + // handleOnPaste(type) { + // // console.log(this.copyData); + // if (this.copyData) { + // const data = { + // ...JSON.parse(JSON.stringify(this.copyData)), + // type, + // }; + // if (!this.recipesId) { + // // 未生成食谱时拷贝 + // data.id = new Date().getTime(); + // } + // this.addDishes({ + // num: this.num, + // data, + // }).catch((err) => { + // this.$message.error(err); + // }); + // } + // }, handleOnWeightChange(data, weight) { // console.log({ data, weight }); this.updateDishes({ @@ -507,12 +661,38 @@ export default { this.$message.error(err); }); }, + handleOnMenuCopyClick() { + // console.log({ + // numDay: this.numDay, + // data: this.data, + // healthyData: this.healthyData, + // templateInfo: this.templateInfo, + // }); + const name = `${ + this.healthyData ? this.healthyData.name : this.templateInfo.name + }-第${this.numDay}天`; + addShortCut({ + name, + id: new Date().getTime(), + type: ["0"], + data: this.data, + }).then(() => { + this.$message.success("添加成功"); + window.postMessage( + { + type: messageTypes.UPDATE_SHORTCUT, + }, + "*" + ); + }); + }, ...mapActions([ "updateDishes", "addDishes", "deleteDishes", "replaceDishes", "setCopyData", + "replaceMenu", ]), ...mapMutations(["setCurrentDay", "resetCurrentDay"]), },