项目文档

master
段学强 1 year ago
parent 3f8e97ca7f
commit d0ef903add

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

@ -0,0 +1,37 @@
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/

@ -0,0 +1,28 @@
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.17-SNAPSHOT'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
maven { url 'https://repo.spring.io/snapshot' }
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}

@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

@ -0,0 +1,248 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

@ -0,0 +1,92 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

@ -0,0 +1,6 @@
{
"name": "dxq-rjgcks",
"lockfileVersion": 2,
"requires": true,
"packages": {}
}

@ -0,0 +1,8 @@
pluginManagement {
repositories {
maven { url 'https://repo.spring.io/milestone' }
maven { url 'https://repo.spring.io/snapshot' }
gradlePluginPortal()
}
}
rootProject.name = 'demo'

@ -0,0 +1,13 @@
package com.dxq;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DxqRjgcksApplication {
public static void main(String[] args) {
SpringApplication.run(DxqRjgcksApplication.class, args);
}
}

@ -0,0 +1,13 @@
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

@ -0,0 +1,18 @@
server:
port:9999
spring:
datasource:
username: root
password: 123456
url:jdbc: mysql:///xdb
redis:
port: 6379
host: localhost
logging:
level:
com.example: debug

@ -0,0 +1,13 @@
package com.dxq;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DxqRjgcksApplicationTests {
@Test
void contextLoads() {
}
}

@ -0,0 +1,13 @@
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests {
@Test
void contextLoads() {
}
}

@ -0,0 +1,14 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

@ -0,0 +1,5 @@
# just a flag
ENV = 'development'
# base api
VUE_APP_BASE_API = '/dev-api'

@ -0,0 +1,6 @@
# just a flag
ENV = 'production'
# base api
VUE_APP_BASE_API = '/prod-api'

@ -0,0 +1,8 @@
NODE_ENV = production
# just a flag
ENV = 'staging'
# base api
VUE_APP_BASE_API = '/stage-api'

@ -0,0 +1,4 @@
build/*.js
src/assets
public
dist

@ -0,0 +1,198 @@
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint',
sourceType: 'module'
},
env: {
browser: true,
node: true,
es6: true,
},
extends: ['plugin:vue/recommended', 'eslint:recommended'],
// add your custom rules here
//it is base on https://github.com/vuejs/eslint-config-vue
rules: {
"vue/max-attributes-per-line": [2, {
"singleline": 10,
"multiline": {
"max": 1,
"allowFirstLine": false
}
}],
"vue/singleline-html-element-content-newline": "off",
"vue/multiline-html-element-content-newline":"off",
"vue/name-property-casing": ["error", "PascalCase"],
"vue/no-v-html": "off",
'accessor-pairs': 2,
'arrow-spacing': [2, {
'before': true,
'after': true
}],
'block-spacing': [2, 'always'],
'brace-style': [2, '1tbs', {
'allowSingleLine': true
}],
'camelcase': [0, {
'properties': 'always'
}],
'comma-dangle': [2, 'never'],
'comma-spacing': [2, {
'before': false,
'after': true
}],
'comma-style': [2, 'last'],
'constructor-super': 2,
'curly': [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
'eqeqeq': ["error", "always", {"null": "ignore"}],
'generator-star-spacing': [2, {
'before': true,
'after': true
}],
'handle-callback-err': [2, '^(err|error)$'],
'indent': [2, 2, {
'SwitchCase': 1
}],
'jsx-quotes': [2, 'prefer-single'],
'key-spacing': [2, {
'beforeColon': false,
'afterColon': true
}],
'keyword-spacing': [2, {
'before': true,
'after': true
}],
'new-cap': [2, {
'newIsCap': true,
'capIsNew': false
}],
'new-parens': 2,
'no-array-constructor': 2,
'no-caller': 2,
'no-console': 'off',
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 0,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [2, {
'allowLoop': false,
'allowSwitch': false
}],
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [2, {
'max': 1
}],
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef': 2,
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [2, {
'defaultAssignment': false
}],
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [2, {
'vars': 'all',
'args': 'none'
}],
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [2, {
'initialized': 'never'
}],
'operator-linebreak': [2, 'after', {
'overrides': {
'?': 'before',
':': 'before'
}
}],
'padded-blocks': [2, 'never'],
'quotes': [2, 'single', {
'avoidEscape': true,
'allowTemplateLiterals': true
}],
'semi': [2, 'never'],
'semi-spacing': [2, {
'before': false,
'after': true
}],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': [2, 'never'],
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [2, {
'words': true,
'nonwords': false
}],
'spaced-comment': [2, 'always', {
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
}],
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
'yoda': [2, 'never'],
'prefer-const': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'object-curly-spacing': [2, 'always', {
objectsInObjects: false
}],
'array-bracket-spacing': [2, 'never']
}
}

@ -0,0 +1,16 @@
.DS_Store
node_modules/
dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
package-lock.json
tests/**/coverage/
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln

@ -0,0 +1,5 @@
language: node_js
node_js: 10
script: npm run test
notifications:
email: false

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017-present PanJiaChen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,111 @@
# vue-admin-template
> 这是一个极简的 vue admin 管理后台。它只包含了 Element UI & axios & iconfont & permission control & lint这些搭建后台必要的东西。
[线上地址](http://panjiachen.github.io/vue-admin-template)
[国内访问](https://panjiachen.gitee.io/vue-admin-template)
目前版本为 `v4.0+` 基于 `vue-cli` 进行构建,若你想使用旧版本,可以切换分支到[tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0),它不依赖 `vue-cli`
<p align="center">
<b>SPONSORED BY</b>
</p>
<p align="center">
<a href="https://finclip.com?from=vue_element" title="FinClip" target="_blank">
<img height="200px" src="https://gitee.com/panjiachen/gitee-cdn/raw/master/vue%E8%B5%9E%E5%8A%A9.png" title="FinClip">
</a>
</p>
## Extra
如果你想要根据用户角色来动态生成侧边栏和 router你可以使用该分支[permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control)
## 相关项目
- [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
- [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
- [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template)
- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
写了一个系列的教程配套文章,如何从零构建后一个完整的后台项目:
- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
- [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35)
- [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板,专门针对本项目的文章,算作是一篇文档)](https://juejin.im/post/595b4d776fb9a06bbe7dba56)
- [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836)
## Build Setup
```bash
# 克隆项目
git clone https://github.com/PanJiaChen/vue-admin-template.git
# 进入项目目录
cd vue-admin-template
# 安装依赖
npm install
# 建议不要直接使用 cnpm 安装以来,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
npm install --registry=https://registry.npm.taobao.org
# 启动服务
npm run dev
```
浏览器访问 [http://localhost:9528](http://localhost:9528)
## 发布
```bash
# 构建测试环境
npm run build:stage
# 构建生产环境
npm run build:prod
```
## 其它
```bash
# 预览发布环境效果
npm run preview
# 预览发布环境效果 + 静态资源分析
npm run preview -- --report
# 代码格式检查
npm run lint
# 代码格式检查并自动修复
npm run lint -- --fix
```
更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
## 购买贴纸
你也可以通过 购买[官方授权的贴纸](https://smallsticker.com/product/vue-element-admin) 的方式来支持 vue-element-admin - 每售出一张贴纸,我们将获得 2 元的捐赠。
## Demo
![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif)
## Browsers support
Modern browsers and Internet Explorer 10+.
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| --------- | --------- | --------- | --------- |
| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
## License
[MIT](https://github.com/PanJiaChen/vue-admin-template/blob/master/LICENSE) license.
Copyright (c) 2017-present PanJiaChen

@ -0,0 +1,99 @@
# vue-admin-template
English | [简体中文](./README-zh.md)
> A minimal 中国民航大学营养菜谱生成系统 with Element UI & axios & iconfont & permission control & lint
**Live demo:** http://panjiachen.github.io/vue-admin-template
**The current version is `v4.0+` build on `vue-cli`. If you want to use the old version , you can switch branch to [tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0), it does not rely on `vue-cli`**
<p align="center">
<b>SPONSORED BY</b>
</p>
<p align="center">
<a href="https://finclip.com?from=vue_element" title="FinClip" target="_blank">
<img height="200px" src="https://gitee.com/panjiachen/gitee-cdn/raw/master/vue%E8%B5%9E%E5%8A%A9.png" title="FinClip">
</a>
</p>
## Build Setup
```bash
# clone the project
git clone https://github.com/PanJiaChen/vue-admin-template.git
# enter the project directory
cd vue-admin-template
# install dependency
npm install
# develop
npm run dev
```
This will automatically open http://localhost:9528
## Build
```bash
# build for test environment
npm run build:stage
# build for production environment
npm run build:prod
```
## Advanced
```bash
# preview the release environment effect
npm run preview
# preview the release environment effect + static resource analysis
npm run preview -- --report
# code format check
npm run lint
# code format check and auto fix
npm run lint -- --fix
```
Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) for more information
## Demo
![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif)
## Extra
If you want router permission && generate menu by user roles , you can use this branch [permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control)
For `typescript` version, you can use [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour))
## Related Project
- [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
- [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
- [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template)
- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
## Browsers support
Modern browsers and Internet Explorer 10+.
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| --------- | --------- | --------- | --------- |
| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
## License
[MIT](https://github.com/PanJiaChen/vue-admin-template/blob/master/LICENSE) license.
Copyright (c) 2017-present PanJiaChen

@ -0,0 +1,53 @@
const express = require('express');
const cors = require('cors');
const mysql = require('mysql2/promise'); // 使用mysql2库
const app = express();
app.use(cors());
app.use(express.json()); // Add this line to enable JSON parsing
const port = 3000;
// 创建MySQL数据库连接池
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'wql17623243339',
database: 'custom',
connectionLimit: 10, // 适当设置连接池大小
});
// 创建API端点来执行数据库查询
app.get('/api/data', async (req, res) => {
try {
// 从数据库中查询数据的示例
const [rows] = await pool.query('SELECT * FROM yonghu');
res.json(rows);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal server error' });
}
});
app.post('/api/data', async (req, res) => {
try {
const { idyonghu, feedback } = req.body;
console.log('Received data:', idyonghu, feedback);
const [result] = await pool.query('INSERT INTO yonghu (idyonghu, feedback) VALUES (?, ?)', [idyonghu, feedback]);
console.log('Insert result:', result);
res.json({ success: true, insertedId: result.insertId });
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal server error' });
}
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});

@ -0,0 +1,52 @@
const express = require('express');
const cors = require('cors');
const mysql = require('mysql2/promise'); // 使用mysql2库
const app = express();
app.use(cors());
app.use(express.json()); // Add this line to enable JSON parsing
const port = 3000;
// 创建MySQL数据库连接池
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'wql17623243339',
database: 'sys',
connectionLimit: 100, // 适当设置连接池大小
});
// 创建API端点来执行数据库查询
app.get('/api/data', async (req, res) => {
try {
// 从数据库中查询数据的示例
const [rows] = await pool.query('SELECT * FROM new_table');
res.json(rows);
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal server error' });
}
});
app.post('/api/data', async (req, res) => {
try {
const { idnew_table, new_tablecol, new_tablecol1, new_tablecol2, new_tablecol3, new_tablecol4, new_tablecol5, new_tablecol6, new_tablecol7, new_tablecol8, new_tablecol9 } = req.body;
console.log('Received data:', idnew_table, new_tablecol, new_tablecol1, new_tablecol2, new_tablecol3, new_tablecol4, new_tablecol5, new_tablecol6, new_tablecol7, new_tablecol8, new_tablecol9);
const [result] = await pool.query('INSERT INTO new_table ( idnew_table, new_tablecol, new_tablecol1, new_tablecol2, new_tablecol3, new_tablecol4, new_tablecol5, new_tablecol6, new_tablecol7, new_tablecol8, new_tablecol9) VALUES (?, ?,?, ?,?, ?,?, ?,?, ?,?)', [ idnew_table, new_tablecol, new_tablecol1, new_tablecol2, new_tablecol3, new_tablecol4, new_tablecol5, new_tablecol6, new_tablecol7, new_tablecol8, new_tablecol9]);
console.log('Insert result:', result);
res.json({ success: true, insertedId: result.insertId });
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal server error' });
}
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});

@ -0,0 +1,14 @@
module.exports = {
presets: [
// https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
'@vue/cli-plugin-babel/preset'
],
'env': {
'development': {
// babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
// This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
// https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html
'plugins': ['dynamic-import-node']
}
}
}

@ -0,0 +1,24 @@
module.exports = {
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
'jest-transform-stub',
'^.+\\.jsx?$': 'babel-jest'
},
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
snapshotSerializers: ['jest-serializer-vue'],
testMatch: [
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
],
collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
coverageDirectory: '<rootDir>/tests/unit/coverage',
// 'collectCoverage': true,
'coverageReporters': [
'lcov',
'text-summary'
],
testURL: 'http://localhost/'
}

@ -0,0 +1,9 @@
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
},
"exclude": ["node_modules", "dist"]
}

@ -0,0 +1,57 @@
const Mock = require('mockjs')
const { param2Obj } = require('./utils')
const user = require('./user')
const table = require('./table')
const mocks = [
...user,
...table
]
// for front mock
// please use it cautiously, it will redefine XMLHttpRequest,
// which will cause many of your third-party libraries to be invalidated(like progress event).
function mockXHR() {
// mock patch
// https://github.com/nuysoft/Mock/issues/300
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
Mock.XHR.prototype.send = function() {
if (this.custom.xhr) {
this.custom.xhr.withCredentials = this.withCredentials || false
if (this.responseType) {
this.custom.xhr.responseType = this.responseType
}
}
this.proxy_send(...arguments)
}
function XHR2ExpressReqWrap(respond) {
return function(options) {
let result = null
if (respond instanceof Function) {
const { body, type, url } = options
// https://expressjs.com/en/4x/api.html#req
result = respond({
method: type,
body: JSON.parse(body),
query: param2Obj(url)
})
} else {
result = respond
}
return Mock.mock(result)
}
}
for (const i of mocks) {
Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
}
}
module.exports = {
mocks,
mockXHR
}

@ -0,0 +1,81 @@
const chokidar = require('chokidar')
const bodyParser = require('body-parser')
const chalk = require('chalk')
const path = require('path')
const Mock = require('mockjs')
const mockDir = path.join(process.cwd(), 'mock')
function registerRoutes(app) {
let mockLastIndex
const { mocks } = require('./index.js')
const mocksForServer = mocks.map(route => {
return responseFake(route.url, route.type, route.response)
})
for (const mock of mocksForServer) {
app[mock.type](mock.url, mock.response)
mockLastIndex = app._router.stack.length
}
const mockRoutesLength = Object.keys(mocksForServer).length
return {
mockRoutesLength: mockRoutesLength,
mockStartIndex: mockLastIndex - mockRoutesLength
}
}
function unregisterRoutes() {
Object.keys(require.cache).forEach(i => {
if (i.includes(mockDir)) {
delete require.cache[require.resolve(i)]
}
})
}
// for mock server
const responseFake = (url, type, respond) => {
return {
url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`),
type: type || 'get',
response(req, res) {
console.log('request invoke:' + req.path)
res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
}
}
}
module.exports = app => {
// parse app.body
// https://expressjs.com/en/4x/api.html#req.body
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: true
}))
const mockRoutes = registerRoutes(app)
var mockRoutesLength = mockRoutes.mockRoutesLength
var mockStartIndex = mockRoutes.mockStartIndex
// watch files, hot reload mock server
chokidar.watch(mockDir, {
ignored: /mock-server/,
ignoreInitial: true
}).on('all', (event, path) => {
if (event === 'change' || event === 'add') {
try {
// remove mock routes stack
app._router.stack.splice(mockStartIndex, mockRoutesLength)
// clear routes cache
unregisterRoutes()
const mockRoutes = registerRoutes(app)
mockRoutesLength = mockRoutes.mockRoutesLength
mockStartIndex = mockRoutes.mockStartIndex
console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
} catch (error) {
console.log(chalk.redBright(error))
}
}
})
}

@ -0,0 +1,275 @@
const Mock = require('mockjs')
const data = Mock.mock({
'items|30': [{
id: '@id',
title: '@sentence(10, 20)',
'status|1': ['published', 'draft', 'deleted'],
author: 'name',
display_time: '@datetime',
pageviews: '@integer(300, 5000)'
}]
})
//从excel手动解析的部分数据excel转json在线网址 https://www.bejson.com/json/col2json/index.html
const dataAll =
[
{"menuId":1101,"menuName":"香辣鸡腿堡","price":9,"weight":160,"protein":17.2,"carb":60.6,"fat":14.5,"calories":441},
{"menuId":1102,"menuName":"岐山臊子面","price":9,"weight":160,"protein":12.8,"carb":72,"fat":14.7,"calories":470},
{"menuId":1103,"menuName":"鸡肉卷","price":9,"weight":160,"protein":18.9,"carb":37.9,"fat":21.9,"calories":422},
{"menuId":1104,"menuName":"七喜","price":12,"weight":450,"protein":0,"carb":34.6,"fat":0,"calories":135},
{"menuId":1105,"menuName":"可乐","price":10,"weight":450,"protein":0,"carb":50.4,"fat":0,"calories":198},
{"menuId":1106,"menuName":"美年达","price":14,"weight":450,"protein":0,"carb":43.2,"fat":0,"calories":171},
{"menuId":1107,"menuName":"炸鸡排","price":20.5,"weight":200,"protein":36.8,"carb":11.6,"fat":18.4,"calories":358},
{"menuId":1108,"menuName":"蜜汁鸡腿","price":16,"weight":130,"protein":22.1,"carb":12.5,"fat":14.4,"calories":267},
{"menuId":1109,"menuName":"奶香脆","price":10.5,"weight":200,"protein":21.2,"carb":114,"fat":29.6,"calories":806},
{"menuId":1110,"menuName":"糯糯小年糕","price":19,"weight":250,"protein":5.5,"carb":119.3,"fat":12.8,"calories":612},
{"menuId":1111,"menuName":"藤椒鸡条","price":17.5,"weight":200,"protein":21.8,"carb":13.4,"fat":16.4,"calories":288},
{"menuId":1112,"menuName":"锅巴土豆","price":11,"weight":200,"protein":5,"carb":32.3,"fat":20.6,"calories":334},
{"menuId":1113,"menuName":"爆浆芝士鸡排","price":14,"weight":315,"protein":37.5,"carb":40.6,"fat":51.7,"calories":774},
{"menuId":1114,"menuName":"现炸酥肉","price":12,"weight":185,"protein":18.4,"carb":17.5,"fat":53.4,"calories":623},
{"menuId":1115,"menuName":"黑椒鸡块","price":17.5,"weight":150,"protein":12.8,"carb":32.1,"fat":33.8,"calories":483},
{"menuId":1116,"menuName":"鸡米花","price":12.5,"weight":180,"protein":24.3,"carb":29.7,"fat":23.9,"calories":430},
{"menuId":1117,"menuName":"薯条","price":8,"weight":220,"protein":12.8,"carb":109.1,"fat":40.3,"calories":849},
{"menuId":1118,"menuName":"牛肉拉面","price":13.5,"weight":200,"protein":3.6,"carb":156.4,"fat":1.2,"calories":650},
{"menuId":1119,"menuName":"烤肠","price":15,"weight":150,"protein":20.4,"carb":13.8,"fat":33.5,"calories":436},
{"menuId":1120,"menuName":"猪肉肠","price":15,"weight":80,"protein":12.5,"carb":2.9,"fat":19.9,"calories":240},
{"menuId":1121,"menuName":"拉丝芝士棒","price":15,"weight":80,"protein":9,"carb":23,"fat":9.3,"calories":211},
{"menuId":1122,"menuName":"牛肉串","price":9.5,"weight":200,"protein":29,"carb":47.6,"fat":10.4,"calories":400},
{"menuId":1123,"menuName":"鱿鱼串","price":10,"weight":200,"protein":27.1,"carb":10.3,"fat":13.7,"calories":272},
{"menuId":1124,"menuName":"鸡肉串","price":9.5,"weight":200,"protein":38.6,"carb":2.6,"fat":18.8,"calories":334},
{"menuId":1125,"menuName":"鸭肉串","price":9.5,"weight":200,"protein":65,"carb":3.8,"fat":28.2,"calories":528},
{"menuId":1126,"menuName":"香辣鸡珍","price":9.5,"weight":200,"protein":51.4,"carb":0,"fat":26.2,"calories":440},
{"menuId":1127,"menuName":"香酥鸡柳","price":10,"weight":180,"protein":15.8,"carb":43.2,"fat":25.2,"calories":462},
{"menuId":1201,"menuName":"5个鲜肉包","price":15,"weight":80,"protein":6.4,"carb":32,"fat":3.4,"calories":183},
{"menuId":1202,"menuName":"4个虾仁三鲜包","price":12,"weight":90,"protein":7.2,"carb":10.8,"fat":11.8,"calories":177},
{"menuId":1203,"menuName":"4个西葫鸡蛋包","price":10,"weight":100,"protein":6.3,"carb":25.1,"fat":3.1,"calories":153},
{"menuId":1205,"menuName":"5个小葱鲜肉包","price":10,"weight":90,"protein":10.2,"carb":30.7,"fat":2.4,"calories":184},
{"menuId":1204,"menuName":"4个牛肉包","price":20,"weight":90,"protein":10.6,"carb":28.9,"fat":4.8,"calories":200},
// {"menuId":1206,"menuName":"香菇鲜肉包","price":1.8,"weight":90,"protein":6.4,"carb":30.5,"fat":5.5,"calories":196},
// {"menuId":1207,"menuName":"素三鲜包","price":1.5,"weight":90,"protein":6.6,"carb":33,"fat":11.2,"calories":258},
// {"menuId":1208,"menuName":"豆角鲜肉包","price":1.5,"weight":90,"protein":6.3,"carb":32.9,"fat":7.5,"calories":223},
// {"menuId":1209,"menuName":"芹菜鲜肉包","price":1.5,"weight":90,"protein":8.8,"carb":31,"fat":3.1,"calories":2.07},
// {"menuId":1210,"menuName":"鲜肉煎包","price":2,"weight":60,"protein":7.4,"carb":15.1,"fat":11.2,"calories":190},
// {"menuId":1211,"menuName":"豆沙包","price":1.5,"weight":80,"protein":7.5,"carb":54.1,"fat":0.9,"calories":253},
// {"menuId":1212,"menuName":"第一楼汤包","price":5,"weight":220,"protein":13.4,"carb":68.2,"fat":24,"calories":541},
// {"menuId":1213,"menuName":"素白菜包","price":1,"weight":80,"protein":5.1,"carb":20.7,"fat":1.4,"calories":115},
// {"menuId":1214,"menuName":"紫薯包","price":2.5,"weight":80,"protein":3.8,"carb":25.6,"fat":0.8,"calories":124},
// {"menuId":1215,"menuName":"紫薯馒头","price":0.9,"weight":60,"protein":8.1,"carb":35.4,"fat":2.2,"calories":193},
// {"menuId":1216,"menuName":"花卷","price":0.5,"weight":60,"protein":3.8,"carb":27.4,"fat":0.6,"calories":130},
// {"menuId":1217,"menuName":"白馒头","price":0.5,"weight":60,"protein":4.1,"carb":36.6,"fat":0.7,"calories":169},
// {"menuId":1218,"menuName":"白煮蛋","price":0.6,"weight":50,"protein":6,"carb":0.1,"fat":5.3,"calories":71},
// {"menuId":1219,"menuName":"豆腐脑","price":3,"weight":450,"protein":11.7,"carb":24.3,"fat":8.1,"calories":216},
// {"menuId":1220,"menuName":"五谷豆浆","price":1,"weight":500,"protein":15,"carb":6,"fat":8,"calories":155},
// {"menuId":1221,"menuName":"牛奶","price":3,"weight":500,"protein":15,"carb":25,"fat":19,"calories":330},
// {"menuId":1222,"menuName":"紫米露","price":3.5,"weight":500,"protein":4.5,"carb":80,"fat":4.8,"calories":380},
// {"menuId":1223,"menuName":"香芋露","price":3.5,"weight":500,"protein":4.5,"carb":80,"fat":4.8,"calories":380},
// {"menuId":1224,"menuName":"油条","price":1.5,"weight":50,"protein":3.5,"carb":25.5,"fat":8.8,"calories":195},
// {"menuId":1225,"menuName":"麻球","price":1.5,"weight":50,"protein":2.9,"carb":37,"fat":2.2,"calories":179},
// {"menuId":1226,"menuName":"烧麦","price":1.8,"weight":50,"protein":3.5,"carb":19.6,"fat":1.5,"calories":106},
// {"menuId":1227,"menuName":"水果玉米","price":3.5,"weight":400,"protein":12.4,"carb":70,"fat":10.4,"calories":420},
// {"menuId":1228,"menuName":"糯玉米","price":3.5,"weight":400,"protein":18.8,"carb":133.6,"fat":7.6,"calories":676},
// {"menuId":1229,"menuName":"地瓜","price":5,"weight":500,"protein":5.5,"carb":147.5,"fat":0.5,"calories":615},
// {"menuId":1230,"menuName":"甜甜圈","price":2,"weight":30,"protein":2,"carb":5.2,"fat":4.4,"calories":68},
// {"menuId":1231,"menuName":"卤鸡蛋","price":1.2,"weight":50,"protein":6.1,"carb":2.3,"fat":"4.0 ","calories":69},
// {"menuId":1232,"menuName":"荷包蛋","price":1.4,"weight":50,"protein":6.1,"carb":1.1,"fat":6.6,"calories":87},
// {"menuId":1233,"menuName":"脆皮大麻花","price":3.8,"weight":140,"protein":11.8,"carb":82,"fat":4.8,"calories":417},
// {"menuId":1234,"menuName":"脆皮淀粉肠","price":3,"weight":100,"protein":5,"carb":10.7,"fat":6,"calories":115},
// {"menuId":1235,"menuName":"黑椒肠","price":4,"weight":70,"protein":10.2,"carb":8.9,"fat":11.8,"calories":182},
// {"menuId":1236,"menuName":"玉米露汁","price":2.8,"weight":500,"protein":7.6,"carb":71.3,"fat":2.3,"calories":335},
// {"menuId":1237,"menuName":"铁板煎豆腐","price":7,"weight":400,"protein":25.4,"carb":13.5,"fat":28,"calories":404},
// {"menuId":1238,"menuName":"烤面筋","price":2.5,"weight":100,"protein":19.8,"carb":12.6,"fat":16.8,"calories":280},
// {"menuId":1239,"menuName":"发糕","price":2,"weight":70,"protein":5.3,"carb":36.1,"fat":0.7,"calories":170},
// {"menuId":1240,"menuName":"切糕","price":3,"weight":120,"protein":2.8,"carb":39,"fat":0.4,"calories":170},
// {"menuId":1241,"menuName":"香肠卷","price":2.5,"weight":110,"protein":9.1,"carb":41.4,"fat":6.6,"calories":260},
// {"menuId":1301,"menuName":"牛奶燕麦粥","price":2,"weight":450,"protein":2.6,"carb":7.2,"fat":3.6,"calories":71},
// {"menuId":1302,"menuName":"八宝粥","price":2,"weight":450,"protein":7.9,"carb":39.2,"fat":4.6,"calories":229},
// {"menuId":1303,"menuName":"金丝南瓜小米粥","price":2,"weight":450,"protein":3.6,"carb":29.4,"fat":1.1,"calories":139},
// {"menuId":1304,"menuName":"红糖银耳","price":1.5,"weight":450,"protein":0.6,"carb":8.4,"fat":0.2,"calories":36},
// {"menuId":1305,"menuName":"皮蛋瘦肉粥","price":2,"weight":450,"protein":21.6,"carb":59.6,"fat":11.9,"calories":427},
// {"menuId":1306,"menuName":"胡辣汤","price":3,"weight":450,"protein":13,"carb":11.6,"fat":7.4,"calories":162},
// {"menuId":1307,"menuName":"白米粥","price":0.5,"weight":450,"protein":3.1,"carb":35.5,"fat":2.7,"calories":175},
// {"menuId":1308,"menuName":"疙瘩汤","price":2,"weight":450,"protein":6,"carb":27.2,"fat":1.8,"calories":148},
// {"menuId":1309,"menuName":"银耳绿豆汤","price":2,"weight":450,"protein":8.7,"carb":32.9,"fat":0.3,"calories":166},
// {"menuId":1310,"menuName":"马拉糕","price":3,"weight":60,"protein":4.1,"carb":32.4,"fat":2.4,"calories":167},
// {"menuId":1311,"menuName":"蛋包肠","price":4,"weight":100,"protein":11.9,"carb":5.1,"fat":12.3,"calories":178},
// {"menuId":1312,"menuName":"白煮蛋","price":0.6,"weight":50,"protein":6,"carb":0.1,"fat":5.3,"calories":71},
// {"menuId":1313,"menuName":"麻球","price":1.5,"weight":30,"protein":1.8,"carb":22.2,"fat":1.3,"calories":107},
// {"menuId":1314,"menuName":"茶叶蛋","price":1.2,"weight":50,"protein":6.3,"carb":6.2,"fat":3.1,"calories":77},
{"menuId":1315,"menuName":"肉末粉丝煎饺","price":12,"weight":50,"protein":3.4,"carb":12.7,"fat":8.3,"calories":139},
{"menuId":1316,"menuName":"紫米球","price":12,"weight":120,"protein":1.8,"carb":35.8,"fat":2.6,"calories":174},
{"menuId":1317,"menuName":"三明治","price":8,"weight":135,"protein":14.4,"carb":24,"fat":18,"calories":314},
{"menuId":1318,"menuName":"赤豆元宵","price":8,"weight":210,"protein":6.9,"carb":63.6,"fat":1.5,"calories":294},
{"menuId":1319,"menuName":"桂花糯米糕","price":8,"weight":150,"protein":6.2,"carb":78.6,"fat":1.4,"calories":351},
{"menuId":1320,"menuName":"鸡蛋肉沫汉堡","price":8,"weight":150,"protein":20.2,"carb":45.5,"fat":17.2,"calories":416},
{"menuId":1321,"menuName":"火腿鸡蛋汉堡","price":7,"weight":150,"protein":15.6,"carb":39.1,"fat":21.5,"calories":411},
{"menuId":1322,"menuName":"葱油拌面","price":7,"weight":150,"protein":17.4,"carb":6.4,"fat":14.7,"calories":226},
{"menuId":1323,"menuName":"陕西油泼面","price":7,"weight":150,"protein":16.9,"carb":55.1,"fat":13.1,"calories":405},
{"menuId":1324,"menuName":"哈尔滨烤冷面","price":7,"weight":350,"protein":23,"carb":82.5,"fat":14.9,"calories":556},
// {"menuId":1401,"menuName":"杂粮煎饼","price":6,"weight":200,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1402,"menuName":"烤肠","price":2,"weight":20,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1403,"menuName":"辣条","price":3,"weight":50,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1404,"menuName":"火鸡面","price":3,"weight":60,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1405,"menuName":"里脊肉","price":3,"weight":25,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1406,"menuName":"纯肉肠","price":5,"weight":60,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1407,"menuName":"奥尔良鸡肉条","price":4,"weight":50,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1408,"menuName":"玉米肠","price":3.5,"weight":40,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1409,"menuName":"午餐肉","price":3,"weight":40,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1410,"menuName":"骨肉相连","price":3,"weight":30,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1411,"menuName":"培根","price":2,"weight":20,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1412,"menuName":"雪花鸡柳","price":3,"weight":50,"protein":0,"carb":0,"fat":0,"calories":0},
{"menuId":1501,"menuName":"清汤抄手","price":11,"weight":700,"protein":22,"carb":118,"fat":8.5,"calories":630},
{"menuId":1502,"menuName":"红油抄手","price":11.6,"weight":700,"protein":24.8,"carb":114.5,"fat":13.5,"calories":678},
{"menuId":1503,"menuName":"番茄抄手","price":12,"weight":700,"protein":21.6,"carb":118,"fat":7.6,"calories":623},
{"menuId":1504,"menuName":"鸡汤抄手","price":14,"weight":700,"protein":25.8,"carb":107,"fat":10.3,"calories":623},
{"menuId":1505,"menuName":"麻辣抄手","price":14,"weight":700,"protein":18.6,"carb":119.5,"fat":18.9,"calories":721},
{"menuId":1506,"menuName":"香菇菌汤抄手","price":9.8,"weight":700,"protein":17.5,"carb":110.9,"fat":13.5,"calories":630},
{"menuId":1507,"menuName":"金汤酸菜抄手","price":9.8,"weight":700,"protein":21.8,"carb":106.8,"fat":18.5,"calories":679},
// {"menuId":1508,"menuName":"鸡汤抄手面","price":9.8,"weight":950,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1509,"menuName":"番茄抄手面","price":9.8,"weight":950,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1510,"menuName":"麻辣抄手面","price":9.8,"weight":950,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1511,"menuName":"香菇菌汤抄手面","price":9.8,"weight":950,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1512,"menuName":"金汤酸菜抄手面","price":9.8,"weight":950,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1513,"menuName":"芹菜鸡蛋素水饺","price":7.6,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1514,"menuName":"胡萝卜鸡蛋素水饺","price":7.6,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1515,"menuName":"萝卜鲜肉水饺","price":8,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1516,"menuName":"茄子鲜肉水饺","price":8,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1517,"menuName":"肉三鲜水饺","price":8.6,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1518,"menuName":"大葱鲜肉水饺","price":9,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1519,"menuName":"玉米鲜肉水饺","price":9,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1520,"menuName":"茴香鲜肉水饺","price":9,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1521,"menuName":"菌菇鲜汤水饺","price":9,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1522,"menuName":"豆角鲜肉水饺","price":9,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1523,"menuName":"全家福鲜肉水饺","price":9,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1524,"menuName":"莲藕玉米鲜肉水饺","price":9.9,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1525,"menuName":"香芹蘑菇鲜肉水饺","price":9.9,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1526,"menuName":"新奥尔良鲜肉水饺","price":9.9,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1527,"menuName":"虾仁三鲜水饺","price":10.8,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1528,"menuName":"虾仁玉米鲜肉水饺","price":10.8,"weight":250,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1529,"menuName":"鲜肉小馄饨(小份)","price":6.6,"weight":320,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1530,"menuName":"鲜肉小馄饨(大份)","price":8.8,"weight":480,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1531,"menuName":"玉米鲜肉小馄饨(小份)","price":6.6,"weight":320,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1532,"menuName":"玉米鲜肉小馄饨(大份)","price":8.8,"weight":480,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1533,"menuName":"福清多方便面系列","price":3.5,"weight":180,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1534,"menuName":"康师傅方便面系列","price":4.5,"weight":180,"protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1801,"menuName":"飘香拌面","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1802,"menuName":"葱油拌面","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1803,"menuName":"高汤酸菜面","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1804,"menuName":"扁肉","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1805,"menuName":"蒸饺","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1806,"menuName":"罗汉肉炒饭","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1807,"menuName":"高汤青菜面","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1808,"menuName":"蛋炒饭","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1809,"menuName":"蛋炒面","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1810,"menuName":"蛋炒粉","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1811,"menuName":"蛋炒泡面","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1812,"menuName":"炒饼丝","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1813,"menuName":"泡菜炒饭","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1814,"menuName":"扬州炒饭","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1815,"menuName":"火腿炒饭","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1816,"menuName":"酸菜炒饭","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1817,"menuName":"老干妈炒饭","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1818,"menuName":"酸豆角炒饭","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1819,"menuName":"香菇肉丝炒饭","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1820,"menuName":"青椒肉丝炒饭","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1821,"menuName":"香菇肉丝面","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1822,"menuName":"榨菜肉丝面","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1823,"menuName":"老北京炸酱面","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1824,"menuName":"五香罗汉肉面","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1825,"menuName":"红烧罗汉肉面","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1826,"menuName":"香肠","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1827,"menuName":"豆干","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1828,"menuName":"鸡腿","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1829,"menuName":"卤蛋","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1901,"menuName":"黄焖鸡米饭套餐","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1902,"menuName":"黄焖鸡全家福套餐","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1903,"menuName":"黄焖全素套餐","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1904,"menuName":"铁锅炒鸡米饭套餐","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":1905,"menuName":"铁锅炒鸡全家福套餐","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2001,"menuName":"纯素饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2002,"menuName":"辣条饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2003,"menuName":"香辣土豆丝饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2004,"menuName":"玉米沙拉饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2005,"menuName":"芒果糯米饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2006,"menuName":"抹茶红豆饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2007,"menuName":"韩式泡菜饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2008,"menuName":"叉烧福袋饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2009,"menuName":"咸蛋黄饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2010,"menuName":"深海鳕鱼饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2011,"menuName":"鸡排饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2012,"menuName":"黑椒鸡柳饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2013,"menuName":"菠萝鸡柳饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2014,"menuName":"培根肉松饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2015,"menuName":"传统鸡蛋饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2016,"menuName":"油条甜饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2017,"menuName":"咖喱嫩鸡饭团","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2018,"menuName":"酸梅汤","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2019,"menuName":"金桔梨汤","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2020,"menuName":"芥菜梨汤","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2021,"menuName":"传统梨汤","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2022,"menuName":"菠萝梨汤","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2023,"menuName":"枇杷梨汤","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2024,"menuName":"蟹柳","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2025,"menuName":"辣条","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2026,"menuName":"蛋黄","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2027,"menuName":"芝士碎","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2028,"menuName":"烤肠","price":0,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2101,"menuName":"麻酱拌面","price":6,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2102,"menuName":"酸菜肉沫面","price":9,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2103,"menuName":"纯汤牛肉面","price":9,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2104,"menuName":"青菜面","price":6,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2105,"menuName":"葱油拌面","price":6.6,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2106,"menuName":"津味炸酱面","price":9.9,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2107,"menuName":"番茄鸡蛋面","price":7.7,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2108,"menuName":"尖椒鸡肉丝面","price":9.9,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2109,"menuName":"青菜鸡蛋面","price":7.8,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2110,"menuName":"榨菜猪肉丝面","price":9,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2111,"menuName":"蒜薹鸡肉丝面","price":9.9,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2112,"menuName":"武汉热干面","price":9.9,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2113,"menuName":"重庆担担面","price":8.8,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2114,"menuName":"椒麻鸡丝面","price":12,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2115,"menuName":"岐山臊子面","price":11,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2116,"menuName":"陕西油泼面","price":11,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2117,"menuName":"红烧排骨","price":8,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2118,"menuName":"香辣肥肠","price":8,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2119,"menuName":"熟牛肉","price":8,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2120,"menuName":"红烧牛肉","price":8,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2121,"menuName":"双椒肉酱","price":6,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2122,"menuName":"金汤鸭肉卷","price":6,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2123,"menuName":"香菇肉末","price":6,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2124,"menuName":"卤鸡腿","price":5,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2125,"menuName":"川味肉末","price":6,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2126,"menuName":"川味牛杂","price":7,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2127,"menuName":"卤蛋","price":1.2,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2128,"menuName":"丸子","price":2,"weight":"","protein":0,"carb":0,"fat":0,"calories":0},
// {"menuId":2129,"menuName":"豆干","price":2,"weight":"","protein":0,"carb":0,"fat":0,"calories":0}
]
module.exports = [
{
url: '/vue-admin-template/table/list',
type: 'get',
response: config => {
const items = data.items
return {
code: 20000,
data: {
total: items.length,
items: items
}
}
}
},
{
url: '/vue-admin-template/table/getEaWhat',
type: 'get',
response: config => {
// const items = data.items
return {
code: 20000,
data: {
list: dataAll,
}
}
}
}
]

@ -0,0 +1,86 @@
const tokens = {
admin: {
token: 'admin-token'
},
editor: {
token: 'editor-token'
}
}
const users = {
'admin-token': {
roles: ['admin'],
introduction: 'I am a super administrator',
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
name: 'Super Admin'
},
'editor-token': {
roles: ['editor'],
introduction: 'I am an editor',
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
name: 'Normal Editor'
}
}
module.exports = [
// user login
{
url: '/vue-admin-template/user/login',
type: 'post',
response: config => {
const { username } = config.body
console.log(username)
const token = tokens[username]
// mock error
if (!token) {
return {
code: 60204,
message: 'Account and password are incorrect.'
}
}
return {
code: 20000,
data: token
}
}
},
// get user info
{
url: '/vue-admin-template/user/info\.*',
type: 'get',
response: config => {
const { token } = config.query
const info = users[token]
// mock error
if (!info) {
return {
code: 50008,
message: 'Login failed, unable to get user details.'
}
}
return {
code: 20000,
data: info
}
}
},
// user logout
{
url: '/vue-admin-template/user/logout',
type: 'post',
response: _ => {
return {
code: 20000,
data: 'success'
}
}
}
]

@ -0,0 +1,25 @@
/**
* @param {string} url
* @returns {Object}
*/
function param2Obj(url) {
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
if (!search) {
return {}
}
const obj = {}
const searchArr = search.split('&')
searchArr.forEach(v => {
const index = v.indexOf('=')
if (index !== -1) {
const name = v.substring(0, index)
const val = v.substring(index + 1, v.length)
obj[name] = val
}
})
return obj
}
module.exports = {
param2Obj
}

@ -0,0 +1,67 @@
{
"name": "vue-admin-template",
"version": "4.4.0",
"description": "A 中国民航大学营养菜谱生成系统 with Element UI & axios & iconfont & permission control & lint",
"author": "Pan <panfree23@gmail.com>",
"scripts": {
"dev": "vue-cli-service serve",
"build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview",
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
"lint": "eslint --ext .js,.vue src",
"test:unit": "jest --clearCache && vue-cli-service test:unit",
"test:ci": "npm run lint && npm run test:unit"
},
"dependencies": {
"axios": "^0.18.1",
"body-parser": "^1.20.2",
"core-js": "3.6.5",
"cors": "^2.8.5",
"element-ui": "2.13.2",
"express": "^4.18.2",
"js-cookie": "2.2.0",
"mysql": "^2.18.1",
"mysql2": "^3.6.3",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"path-to-regexp": "2.4.0",
"vue": "2.6.10",
"vue-router": "3.0.6",
"vuex": "3.1.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "4.4.4",
"@vue/cli-plugin-eslint": "4.4.4",
"@vue/cli-plugin-unit-jest": "4.4.4",
"@vue/cli-service": "4.4.4",
"@vue/test-utils": "1.0.0-beta.29",
"autoprefixer": "9.5.1",
"babel-eslint": "10.1.0",
"babel-jest": "23.6.0",
"babel-plugin-dynamic-import-node": "2.3.3",
"chalk": "2.4.2",
"connect": "3.6.6",
"eslint": "6.7.2",
"eslint-plugin-vue": "6.2.2",
"html-webpack-plugin": "3.2.0",
"mockjs": "1.0.1-beta3",
"runjs": "4.3.2",
"sass": "1.26.8",
"sass-loader": "8.0.2",
"script-ext-html-webpack-plugin": "2.1.3",
"serve-static": "1.13.2",
"svg-sprite-loader": "4.1.3",
"svgo": "1.2.2",
"vue-template-compiler": "2.6.10"
},
"browserslist": [
"> 1%",
"last 2 versions"
],
"engines": {
"node": ">=8.9",
"npm": ">= 3.0.0"
},
"license": "MIT"
}

@ -0,0 +1,8 @@
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
'plugins': {
// to edit target browsers: use "browserslist" field in package.json
'autoprefixer': {}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= webpackConfig.name %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

@ -0,0 +1,11 @@
<template>
<div id="app">
<router-view />
</div>
</template>
<script>
export default {
name: 'App'
}
</script>

@ -0,0 +1,18 @@
import request from '@/utils/request'
export function getList(params) {
return request({
url: '/vue-admin-template/table/list',
method: 'get',
params
})
}
export function getEaWhat(params) {
return request({
url: '/vue-admin-template/table/getEaWhat',
method: 'get',
params
})
}

@ -0,0 +1,24 @@
import request from '@/utils/request'
export function login(data) {
return request({
url: '/vue-admin-template/user/login',
method: 'post',
data
})
}
export function getInfo(token) {
return request({
url: '/vue-admin-template/user/info',
method: 'get',
params: { token }
})
}
export function logout() {
return request({
url: '/vue-admin-template/user/logout',
method: 'post'
})
}

@ -0,0 +1,172 @@
//userApi.js
var models = require('../db')
var express = require('express')
var router = express.Router()
var mysql = require('mysql')
var $sql = require('../sqlMap')
// 连接数据库
var conn = mysql.createConnection(models.mysql)
conn.connect()
var jsonWrite = function (res, ret) {
if (typeof ret === 'undefined') {
res.json({
code: '1',
msg: '操作失败'
})
} else {
res.json(ret)
}
}
// 左侧导航
router.get('/addUser', (req, res) => {
var sql = $sql.leftList.search;
var params = req.body;
conn.query(sql, [params.loginname, params.password], function(err, result) {
if (err) {
console.log(err);
}
if (result) {
jsonWrite(res, result);
}
})
})
// 全部
router.get('/whole', (req, res) => {
var sql = $sql.whole.search;
var params = req.body;
conn.query(sql, [params.loginname, params.password], function(err, result) {
if (err) {
console.log(err);
}
if (result) {
jsonWrite(res, result);
}
})
})
// 其他
router.post('/project', (req, res) => {
var sql = $sql.project.search
var params = req.body
console.log(params)
console.log(sql);
conn.query(sql, [params.name], function (err, result) {
if (err) {
console.log(err)
}
if (result) {
jsonWrite(res, result)
}
})
})
// 根据某个项目查询系统详情信息
router.post('/system', (req, res) => {
var sql = $sql.system.search
var params = req.body
console.log(params)
console.log(sql);
conn.query(sql, [params.entryName], function (err, result) {
if (err) {
console.log(err)
}
if (result) {
jsonWrite(res, result)
}
})
})
// 根据某个项目查询系统列表信息
router.post('/systemlist', (req, res) => {
var sql = $sql.systemlist.search
var params = req.body
console.log(sql);
console.log(params)
conn.query(sql, [params.entryName], function (err, result) {
if (err) {
console.log(err)
}
if (result) {
jsonWrite(res, result)
}
})
})
// 根据项目名称查询系统入口
router.post('/detail', (req, res) => {
var sql = $sql.detail.search
var params = req.body
console.log(params)
console.log(sql);
conn.query(sql, [params.entryName], function (err, result) {
if (err) {
console.log(err)
}
if (result) {
jsonWrite(res, result)
}
})
})
// 根据ID查询所属领域
router.post('/businessType', (req, res) => {
var sql = $sql.businessType.search
var params = req.body
console.log(params)
console.log(sql);
conn.query(sql, [params.entryName], function (err, result) {
if (err) {
console.log(err)
}
if (result) {
jsonWrite(res, result)
}
})
})
// 各业务领域下查询
router.post('/getMessage', (req, res) => {
var sql = $sql.getMessage.search
var params = req.body
console.log(params)
console.log(sql);
conn.query(sql, [params.oneName,params.twoName,params.NAME], function (err, result) {
if (err) {
console.log(err)
}
if (result) {
jsonWrite(res, result)
}
})
})
// 全部情况下,根据项目或者系统名称查询项目
router.post('/wholeproject', (req, res) => {
var sql = $sql.wholeproject.search
var params = req.body
console.log(params)
conn.query(sql, [params.entryName,params.entryName], function (err, result) {
if (err) {
console.log(err)
}
if (result) {
jsonWrite(res, result)
}
})
})
module.exports = router

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

@ -0,0 +1,78 @@
<template>
<el-breadcrumb class="app-breadcrumb" separator="/">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
<span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<script>
import pathToRegexp from 'path-to-regexp'
export default {
data() {
return {
levelList: null
}
},
watch: {
$route() {
this.getBreadcrumb()
}
},
created() {
this.getBreadcrumb()
},
methods: {
getBreadcrumb() {
// only show routes with meta.title
let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
const first = matched[0]
if (!this.isDashboard(first)) {
matched = [{ path: '/dashboard', meta: { title: 'Dashboard' }}].concat(matched)
}
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
},
isDashboard(route) {
const name = route && route.name
if (!name) {
return false
}
return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
},
pathCompile(path) {
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
const { params } = this.$route
var toPath = pathToRegexp.compile(path)
return toPath(params)
},
handleLink(item) {
const { redirect, path } = item
if (redirect) {
this.$router.push(redirect)
return
}
this.$router.push(this.pathCompile(path))
}
}
}
</script>
<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
display: inline-block;
font-size: 14px;
line-height: 50px;
margin-left: 8px;
.no-redirect {
color: #97a8be;
cursor: text;
}
}
</style>

@ -0,0 +1,44 @@
<template>
<div style="padding: 0 15px;" @click="toggleClick">
<svg
:class="{'is-active':isActive}"
class="hamburger"
viewBox="0 0 1024 1024"
xmlns="http://www.w3.org/2000/svg"
width="64"
height="64"
>
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
</svg>
</div>
</template>
<script>
export default {
name: 'Hamburger',
props: {
isActive: {
type: Boolean,
default: false
}
},
methods: {
toggleClick() {
this.$emit('toggleClick')
}
}
}
</script>
<style scoped>
.hamburger {
display: inline-block;
vertical-align: middle;
width: 20px;
height: 20px;
}
.hamburger.is-active {
transform: rotate(180deg);
}
</style>

@ -0,0 +1,62 @@
<template>
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
import { isExternal } from '@/utils/validate'
export default {
name: 'SvgIcon',
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String,
default: ''
}
},
computed: {
isExternal() {
return isExternal(this.iconClass)
},
iconName() {
return `#icon-${this.iconClass}`
},
svgClass() {
if (this.className) {
return 'svg-icon ' + this.className
} else {
return 'svg-icon'
}
},
styleExternalIcon() {
return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
}
}
}
}
</script>
<style scoped>
.svg-icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover!important;
display: inline-block;
}
</style>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>dxs-rjgcks</artifactId>
<version>1.0-SNAPSHOT</version>
</project>

@ -0,0 +1,7 @@
package org.example;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}

@ -0,0 +1,9 @@
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg component
// register globally
Vue.component('svg-icon', SvgIcon)
const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req)

@ -0,0 +1 @@
<svg width="128" height="100" xmlns="http://www.w3.org/2000/svg"><path d="M27.429 63.638c0-2.508-.893-4.65-2.679-6.424-1.786-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.465 2.662-1.785 1.774-2.678 3.916-2.678 6.424 0 2.508.893 4.65 2.678 6.424 1.786 1.775 3.94 2.662 6.465 2.662 2.524 0 4.678-.887 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm13.714-31.801c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM71.714 65.98l7.215-27.116c.285-1.23.107-2.378-.536-3.443-.643-1.064-1.56-1.762-2.75-2.094-1.19-.33-2.333-.177-3.429.462-1.095.639-1.81 1.573-2.143 2.804l-7.214 27.116c-2.857.237-5.405 1.266-7.643 3.088-2.238 1.822-3.738 4.152-4.5 6.992-.952 3.644-.476 7.098 1.429 10.364 1.905 3.265 4.69 5.37 8.357 6.317 3.667.947 7.143.474 10.429-1.42 3.285-1.892 5.404-4.66 6.357-8.305.762-2.84.619-5.607-.429-8.305-1.047-2.697-2.762-4.85-5.143-6.46zm47.143-2.342c0-2.508-.893-4.65-2.678-6.424-1.786-1.775-3.94-2.662-6.465-2.662-2.524 0-4.678.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.786 1.775 3.94 2.662 6.464 2.662 2.524 0 4.679-.887 6.465-2.662 1.785-1.775 2.678-3.916 2.678-6.424zm-45.714-45.43c0-2.509-.893-4.65-2.679-6.425C68.68 10.01 66.524 9.122 64 9.122c-2.524 0-4.679.887-6.464 2.661-1.786 1.775-2.679 3.916-2.679 6.425 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm32 13.629c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM128 63.638c0 12.351-3.357 23.78-10.071 34.286-.905 1.372-2.19 2.058-3.858 2.058H13.93c-1.667 0-2.953-.686-3.858-2.058C3.357 87.465 0 76.037 0 63.638c0-8.613 1.69-16.847 5.071-24.703C8.452 31.08 13 24.312 18.714 18.634c5.715-5.68 12.524-10.199 20.429-13.559C47.048 1.715 55.333.035 64 .035c8.667 0 16.952 1.68 24.857 5.04 7.905 3.36 14.714 7.88 20.429 13.559 5.714 5.678 10.262 12.446 13.643 20.301 3.38 7.856 5.071 16.09 5.071 24.703z"/></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M96.258 57.462h31.421C124.794 27.323 100.426 2.956 70.287.07v31.422a32.856 32.856 0 0 1 25.971 25.97zm-38.796-25.97V.07C27.323 2.956 2.956 27.323.07 57.462h31.422a32.856 32.856 0 0 1 25.97-25.97zm12.825 64.766v31.421c30.46-2.885 54.507-27.253 57.713-57.712H96.579c-2.886 13.466-13.146 23.726-26.292 26.291zM31.492 70.287H.07c2.886 30.46 27.253 54.507 57.713 57.713V96.579c-13.466-2.886-23.726-13.146-26.291-26.292z"/></svg>

After

Width:  |  Height:  |  Size: 497 B

@ -0,0 +1 @@
<svg class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="128" height="128"><defs><style/></defs><path d="M512 128q69.675 0 135.51 21.163t115.498 54.997 93.483 74.837 73.685 82.006 51.67 74.837 32.17 54.827L1024 512q-2.347 4.992-6.315 13.483T998.87 560.17t-31.658 51.669-44.331 59.99-56.832 64.34-69.504 60.16-82.347 51.5-94.848 34.687T512 896q-69.675 0-135.51-21.163t-115.498-54.826-93.483-74.326-73.685-81.493-51.67-74.496-32.17-54.997L0 513.707q2.347-4.992 6.315-13.483t18.816-34.816 31.658-51.84 44.331-60.33 56.832-64.683 69.504-60.331 82.347-51.84 94.848-34.816T512 128.085zm0 85.333q-46.677 0-91.648 12.331t-81.152 31.83-70.656 47.146-59.648 54.485-48.853 57.686-37.675 52.821-26.325 43.99q12.33 21.674 26.325 43.52t37.675 52.351 48.853 57.003 59.648 53.845T339.2 767.02t81.152 31.488T512 810.667t91.648-12.331 81.152-31.659 70.656-46.848 59.648-54.186 48.853-57.344 37.675-52.651T927.957 512q-12.33-21.675-26.325-43.648t-37.675-52.65-48.853-57.345-59.648-54.186-70.656-46.848-81.152-31.659T512 213.334zm0 128q70.656 0 120.661 50.006T682.667 512 632.66 632.661 512 682.667 391.339 632.66 341.333 512t50.006-120.661T512 341.333zm0 85.334q-35.328 0-60.33 25.002T426.666 512t25.002 60.33T512 597.334t60.33-25.002T597.334 512t-25.002-60.33T512 426.666z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -0,0 +1 @@
<svg width="128" height="64" xmlns="http://www.w3.org/2000/svg"><path d="M127.072 7.994c1.37-2.208.914-5.152-.914-6.87-2.056-1.717-4.797-1.226-6.396.982-.229.245-25.586 32.382-55.74 32.382-29.24 0-55.74-32.382-55.968-32.627-1.6-1.963-4.57-2.208-6.397-.49C-.17 3.086-.399 6.275 1.2 8.238c.457.736 5.94 7.36 14.62 14.72L4.17 35.96c-1.828 1.963-1.6 5.152.228 6.87.457.98 1.6 1.471 2.742 1.471s2.284-.49 3.198-1.472l12.564-13.983c5.94 4.416 13.021 8.587 20.788 11.53l-4.797 17.418c-.685 2.699.686 5.397 3.198 6.133h1.37c2.057 0 3.884-1.472 4.341-3.68L52.6 42.83c3.655.736 7.538 1.227 11.422 1.227 3.883 0 7.767-.49 11.422-1.227l4.797 17.173c.457 2.208 2.513 3.68 4.34 3.68.457 0 .914 0 1.143-.246 2.513-.736 3.883-3.434 3.198-6.133l-4.797-17.172c7.767-2.944 14.848-7.114 20.788-11.53l12.336 13.738c.913.981 2.056 1.472 3.198 1.472s2.284-.49 3.198-1.472c1.828-1.963 1.828-4.906.228-6.87l-11.65-13.001c9.366-7.36 14.849-14.474 14.849-14.474z"/></svg>

After

Width:  |  Height:  |  Size: 944 B

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M84.068 23.784c-1.02 0-1.877-.32-2.572-.96a8.588 8.588 0 0 1-1.738-2.237 11.524 11.524 0 0 1-1.042-2.621c-.232-.895-.348-1.641-.348-2.238V0h.278c.834 0 1.622.085 2.363.256.742.17 1.645.575 2.711 1.214 1.066.64 2.363 1.535 3.892 2.686 1.53 1.15 3.453 2.664 5.77 4.54 2.502 2.045 4.494 3.771 5.977 5.178 1.483 1.406 2.618 2.6 3.406 3.58.787.98 1.274 1.812 1.46 2.494.185.682.277 1.278.277 1.79v2.046H84.068zM127.3 84.01c.278.682.464 1.535.556 2.558.093 1.023-.37 2.003-1.39 2.94-.463.427-.88.832-1.25 1.215-.372.384-.696.704-.974.96a6.69 6.69 0 0 1-.973.767l-11.816-10.741a44.331 44.331 0 0 0 1.877-1.535 31.028 31.028 0 0 1 1.737-1.406c1.112-.938 2.317-1.343 3.615-1.215 1.297.128 2.363.405 3.197.83.927.427 1.923 1.173 2.989 2.239 1.065 1.065 1.876 2.195 2.432 3.388zM78.23 95.902c2.038 0 3.752-.511 5.143-1.534l-26.969 25.83H18.037c-1.761 0-3.684-.47-5.77-1.407a24.549 24.549 0 0 1-5.838-3.709 21.373 21.373 0 0 1-4.518-5.306c-1.204-2.003-1.807-4.07-1.807-6.202V16.495c0-1.79.44-3.665 1.32-5.626A18.41 18.41 0 0 1 5.04 5.562a21.798 21.798 0 0 1 5.213-3.964C12.198.533 14.237 0 16.37 0h53.24v15.984c0 1.62.278 3.367.834 5.242a16.704 16.704 0 0 0 2.572 5.179c1.159 1.577 2.665 2.898 4.518 3.964 1.853 1.066 4.078 1.598 6.673 1.598h20.295v42.325L85.458 92.45c1.02-1.364 1.529-2.856 1.529-4.476 0-2.216-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1c-2.409 0-4.448.789-6.116 2.366-1.668 1.577-2.502 3.474-2.502 5.69 0 2.217.834 4.092 2.502 5.626 1.668 1.535 3.707 2.302 6.117 2.302h52.13zM26.1 47.951c-2.41 0-4.449.789-6.117 2.366-1.668 1.577-2.502 3.473-2.502 5.69 0 2.216.834 4.092 2.502 5.626 1.668 1.534 3.707 2.302 6.117 2.302h52.13c2.409 0 4.47-.768 6.185-2.302 1.715-1.534 2.572-3.41 2.572-5.626 0-2.217-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1zm52.407 64.063l1.807-1.663 3.476-3.196a479.75 479.75 0 0 0 4.587-4.284 500.757 500.757 0 0 1 5.004-4.667c3.985-3.666 8.48-7.758 13.485-12.276l11.677 10.741-13.485 12.404-5.004 4.603-4.587 4.22a179.46 179.46 0 0 0-3.267 3.068c-.88.853-1.367 1.322-1.46 1.407-.463.341-.973.703-1.529 1.087-.556.383-1.112.703-1.668.959-.556.256-1.413.575-2.572.959a83.5 83.5 0 0 1-3.545 1.087 72.2 72.2 0 0 1-3.475.895c-1.112.256-1.946.426-2.502.511-1.112.17-1.854.043-2.224-.383-.371-.426-.464-1.151-.278-2.174.092-.511.278-1.279.556-2.302.278-1.023.602-2.067.973-3.132l1.042-3.005c.325-.938.58-1.577.765-1.918a10.157 10.157 0 0 1 2.224-2.941z"/></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M115.625 127.937H.063V12.375h57.781v12.374H12.438v90.813h90.813V70.156h12.374z"/><path d="M116.426 2.821l8.753 8.753-56.734 56.734-8.753-8.745z"/><path d="M127.893 37.982h-12.375V12.375H88.706V0h39.187z"/></svg>

After

Width:  |  Height:  |  Size: 285 B

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M.002 9.2c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-5.043-3.58-9.132-7.997-9.132S.002 4.157.002 9.2zM31.997.066h95.981V18.33H31.997V.066zm0 45.669c0 5.044 3.58 9.132 7.998 9.132 4.417 0 7.997-4.088 7.997-9.132 0-3.263-1.524-6.278-3.998-7.91-2.475-1.63-5.524-1.63-7.998 0-2.475 1.632-4 4.647-4 7.91zM63.992 36.6h63.986v18.265H63.992V36.6zm-31.995 82.2c0 5.043 3.58 9.132 7.998 9.132 4.417 0 7.997-4.089 7.997-9.132 0-5.044-3.58-9.133-7.997-9.133s-7.998 4.089-7.998 9.133zm31.995-9.131h63.986v18.265H63.992V109.67zm0-27.404c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-3.263-1.524-6.277-3.998-7.909-2.475-1.631-5.524-1.631-7.998 0-2.475 1.632-4 4.646-4 7.91zm31.995-9.13h31.991V91.4H95.987V73.135z"/></svg>

After

Width:  |  Height:  |  Size: 821 B

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M108.8 44.322H89.6v-5.36c0-9.04-3.308-24.163-25.6-24.163-23.145 0-25.6 16.881-25.6 24.162v5.361H19.2v-5.36C19.2 15.281 36.798 0 64 0c27.202 0 44.8 15.281 44.8 38.961v5.361zm-32 39.356c0-5.44-5.763-9.832-12.8-9.832-7.037 0-12.8 4.392-12.8 9.832 0 3.682 2.567 6.808 6.407 8.477v11.205c0 2.718 2.875 4.962 6.4 4.962 3.524 0 6.4-2.244 6.4-4.962V92.155c3.833-1.669 6.393-4.795 6.393-8.477zM128 64v49.201c0 8.158-8.645 14.799-19.2 14.799H19.2C8.651 128 0 121.359 0 113.201V64c0-8.153 8.645-14.799 19.2-14.799h89.6c10.555 0 19.2 6.646 19.2 14.799z"/></svg>

After

Width:  |  Height:  |  Size: 623 B

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M.006.064h127.988v31.104H.006V.064zm0 38.016h38.396v41.472H.006V38.08zm0 48.384h38.396v41.472H.006V86.464zM44.802 38.08h38.396v41.472H44.802V38.08zm0 48.384h38.396v41.472H44.802V86.464zM89.598 38.08h38.396v41.472H89.598zm0 48.384h38.396v41.472H89.598z"/><path d="M.006.064h127.988v31.104H.006V.064zm0 38.016h38.396v41.472H.006V38.08zm0 48.384h38.396v41.472H.006V86.464zM44.802 38.08h38.396v41.472H44.802V38.08zm0 48.384h38.396v41.472H44.802V86.464zM89.598 38.08h38.396v41.472H89.598zm0 48.384h38.396v41.472H89.598z"/></svg>

After

Width:  |  Height:  |  Size: 597 B

@ -0,0 +1 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M126.713 90.023c.858.985 1.287 2.134 1.287 3.447v29.553c0 1.423-.429 2.6-1.287 3.53-.858.93-1.907 1.395-3.146 1.395H97.824c-1.145 0-2.146-.465-3.004-1.395-.858-.93-1.287-2.107-1.287-3.53V93.47c0-.875.19-1.696.572-2.462.382-.766.906-1.368 1.573-1.806a3.84 3.84 0 0 1 2.146-.657h9.725V69.007a3.84 3.84 0 0 0-.43-1.806 3.569 3.569 0 0 0-1.143-1.313 2.714 2.714 0 0 0-1.573-.492h-36.47v23.149h9.725c1.144 0 2.145.492 3.004 1.478.858.985 1.287 2.134 1.287 3.447v29.553c0 .876-.191 1.696-.573 2.463-.38.766-.905 1.368-1.573 1.806a3.84 3.84 0 0 1-2.145.656H51.915a3.84 3.84 0 0 1-2.145-.656c-.668-.438-1.216-1.04-1.645-1.806a4.96 4.96 0 0 1-.644-2.463V93.47c0-1.313.43-2.462 1.288-3.447.858-.986 1.907-1.478 3.146-1.478h9.582v-23.15h-37.9c-.953 0-1.74.356-2.359 1.068-.62.711-.93 1.56-.93 2.544v19.538h9.726c1.239 0 2.264.492 3.074 1.478.81.985 1.216 2.134 1.216 3.447v29.553c0 1.423-.405 2.6-1.216 3.53-.81.93-1.835 1.395-3.074 1.395H4.29c-.476 0-.93-.082-1.358-.246a4.1 4.1 0 0 1-1.144-.657 4.658 4.658 0 0 1-.93-1.067 5.186 5.186 0 0 1-.643-1.395 5.566 5.566 0 0 1-.215-1.56V93.47c0-.437.048-.875.143-1.313a3.95 3.95 0 0 1 .429-1.15c.19-.328.429-.656.715-.984.286-.329.572-.602.858-.821.286-.22.62-.383 1.001-.493.382-.11.763-.164 1.144-.164h9.726V61.619c0-.985.31-1.833.93-2.544.619-.712 1.358-1.068 2.216-1.068h44.335V39.62h-9.582c-1.24 0-2.288-.492-3.146-1.477a5.09 5.09 0 0 1-1.287-3.448V5.14c0-1.423.429-2.627 1.287-3.612.858-.985 1.907-1.477 3.146-1.477h25.743c.763 0 1.478.246 2.145.739a5.17 5.17 0 0 1 1.573 1.888c.382.766.573 1.587.573 2.462v29.553c0 1.313-.43 2.463-1.287 3.448-.859.985-1.86 1.477-3.004 1.477h-9.725v18.389h42.762c.954 0 1.74.355 2.36 1.067.62.711.93 1.56.93 2.545v26.925h9.582c1.239 0 2.288.492 3.146 1.478z"/></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -0,0 +1 @@
<svg width="130" height="130" xmlns="http://www.w3.org/2000/svg"><path d="M63.444 64.996c20.633 0 37.359-14.308 37.359-31.953 0-17.649-16.726-31.952-37.359-31.952-20.631 0-37.36 14.303-37.358 31.952 0 17.645 16.727 31.953 37.359 31.953zM80.57 75.65H49.434c-26.652 0-48.26 18.477-48.26 41.27v2.664c0 9.316 21.608 9.325 48.26 9.325H80.57c26.649 0 48.256-.344 48.256-9.325v-2.663c0-22.794-21.605-41.271-48.256-41.271z" stroke="#979797"/></svg>

After

Width:  |  Height:  |  Size: 440 B

@ -0,0 +1,22 @@
# replace default config
# multipass: true
# full: true
plugins:
# - name
#
# or:
# - name: false
# - name: true
#
# or:
# - name:
# param1: 1
# param2: 2
- removeAttrs:
attrs:
- 'fill'
- 'fill-rule'

@ -0,0 +1,40 @@
<template>
<section class="app-main">
<transition name="fade-transform" mode="out-in">
<router-view :key="key" />
</transition>
</section>
</template>
<script>
export default {
name: 'AppMain',
computed: {
key() {
return this.$route.path
}
}
}
</script>
<style scoped>
.app-main {
/*50 = navbar */
min-height: calc(100vh - 50px);
width: 100%;
position: relative;
overflow: hidden;
}
.fixed-header+.app-main {
padding-top: 50px;
}
</style>
<style lang="scss">
// fix css style bug in open el-dialog
.el-popup-parent--hidden {
.fixed-header {
padding-right: 15px;
}
}
</style>

@ -0,0 +1,136 @@
<template>
<!-- 这里是导航条组件 -->
<div class="navbar">
<hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
<breadcrumb class="breadcrumb-container" />
<div class="right-menu">
<el-dropdown class="avatar-container" trigger="click">
<div class="avatar-wrapper">
<img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar">
<i class="el-icon-caret-bottom" />
</div>
<el-dropdown-menu slot="dropdown" class="user-dropdown">
<!-- 下拉菜单 -->
<a target="_blank" href="https://www.cauc.edu.cn/zhv4/">
<el-dropdown-item>航大官网</el-dropdown-item>
</a>
<a target="_blank" href="https://www.cnsoc.org/">
<el-dropdown-item>营养知识</el-dropdown-item>
</a>
<el-dropdown-item divided @click.native="logout">
<span style="display:block;">退出登录</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import Breadcrumb from '@/components/Breadcrumb'
import Hamburger from '@/components/Hamburger'
export default {
components: {
Breadcrumb,
Hamburger
},
computed: {
...mapGetters([
'sidebar',
'avatar'
])
},
methods: {
toggleSideBar() {
this.$store.dispatch('app/toggleSideBar')
},
async logout() {
await this.$store.dispatch('user/logout')
this.$router.push(`/login?redirect=${this.$route.fullPath}`)
}
}
}
</script>
<style lang="scss" scoped>
.navbar {
height: 50px;
overflow: hidden;
position: relative;
background: #fff;
box-shadow: 0 1px 4px rgba(0,21,41,.08);
.hamburger-container {
line-height: 46px;
height: 100%;
float: left;
cursor: pointer;
transition: background .3s;
-webkit-tap-highlight-color:transparent;
&:hover {
background: rgba(0, 0, 0, .025)
}
}
.breadcrumb-container {
float: left;
}
.right-menu {
float: right;
height: 100%;
line-height: 50px;
&:focus {
outline: none;
}
.right-menu-item {
display: inline-block;
padding: 0 8px;
height: 100%;
font-size: 18px;
color: #5a5e66;
vertical-align: text-bottom;
&.hover-effect {
cursor: pointer;
transition: background .3s;
&:hover {
background: rgba(0, 0, 0, .025)
}
}
}
.avatar-container {
margin-right: 30px;
.avatar-wrapper {
margin-top: 5px;
position: relative;
.user-avatar {
cursor: pointer;
width: 40px;
height: 40px;
border-radius: 10px;
}
.el-icon-caret-bottom {
cursor: pointer;
position: absolute;
right: -20px;
top: 25px;
font-size: 12px;
}
}
}
}
}
</style>

@ -0,0 +1,26 @@
export default {
computed: {
device() {
return this.$store.state.app.device
}
},
mounted() {
// In order to fix the click on menu on the ios device will trigger the mouseleave bug
// https://github.com/PanJiaChen/vue-element-admin/issues/1135
this.fixBugIniOS()
},
methods: {
fixBugIniOS() {
const $subMenu = this.$refs.subMenu
if ($subMenu) {
const handleMouseleave = $subMenu.handleMouseleave
$subMenu.handleMouseleave = (e) => {
if (this.device === 'mobile') {
return
}
handleMouseleave(e)
}
}
}
}
}

@ -0,0 +1,41 @@
<script>
export default {
name: 'MenuItem',
functional: true,
props: {
icon: {
type: String,
default: ''
},
title: {
type: String,
default: ''
}
},
render(h, context) {
const { icon, title } = context.props
const vnodes = []
if (icon) {
if (icon.includes('el-icon')) {
vnodes.push(<i class={[icon, 'sub-el-icon']} />)
} else {
vnodes.push(<svg-icon icon-class={icon}/>)
}
}
if (title) {
vnodes.push(<span slot='title'>{(title)}</span>)
}
return vnodes
}
}
</script>
<style scoped>
.sub-el-icon {
color: currentColor;
width: 1em;
height: 1em;
}
</style>

@ -0,0 +1,43 @@
<template>
<component :is="type" v-bind="linkProps(to)">
<slot />
</component>
</template>
<script>
import { isExternal } from '@/utils/validate'
export default {
props: {
to: {
type: String,
required: true
}
},
computed: {
isExternal() {
return isExternal(this.to)
},
type() {
if (this.isExternal) {
return 'a'
}
return 'router-link'
}
},
methods: {
linkProps(to) {
if (this.isExternal) {
return {
href: to,
target: '_blank',
rel: 'noopener'
}
}
return {
to: to
}
}
}
}
</script>

@ -0,0 +1,82 @@
<template>
<div class="sidebar-logo-container" :class="{'collapse':collapse}">
<transition name="sidebarLogoFade">
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo">
<h1 v-else class="sidebar-title">{{ title }} </h1>
</router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo">
<h1 class="sidebar-title">{{ title }} </h1>
</router-link>
</transition>
</div>
</template>
<script>
export default {
name: 'SidebarLogo',
props: {
collapse: {
type: Boolean,
required: true
}
},
data() {
return {
title: '中国民航大学营养菜谱生成系统',
logo: 'https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png'
}
}
}
</script>
<style lang="scss" scoped>
.sidebarLogoFade-enter-active {
transition: opacity 1.5s;
}
.sidebarLogoFade-enter,
.sidebarLogoFade-leave-to {
opacity: 0;
}
.sidebar-logo-container {
position: relative;
width: 100%;
height: 50px;
line-height: 50px;
background: #2b2f3a;
text-align: center;
overflow: hidden;
& .sidebar-logo-link {
height: 100%;
width: 100%;
& .sidebar-logo {
width: 32px;
height: 32px;
vertical-align: middle;
margin-right: 12px;
}
& .sidebar-title {
display: inline-block;
margin: 0;
color: #fff;
font-weight: 600;
line-height: 50px;
font-size: 14px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
vertical-align: middle;
}
}
&.collapse {
.sidebar-logo {
margin-right: 0px;
}
}
}
</style>

@ -0,0 +1,95 @@
<template>
<div v-if="!item.hidden">
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
<item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" />
</el-menu-item>
</app-link>
</template>
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
<template slot="title">
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
</template>
<sidebar-item
v-for="child in item.children"
:key="child.path"
:is-nest="true"
:item="child"
:base-path="resolvePath(child.path)"
class="nest-menu"
/>
</el-submenu>
</div>
</template>
<script>
import path from 'path'
import { isExternal } from '@/utils/validate'
import Item from './Item'
import AppLink from './Link'
import FixiOSBug from './FixiOSBug'
export default {
name: 'SidebarItem',
components: { Item, AppLink },
mixins: [FixiOSBug],
props: {
// route object
item: {
type: Object,
required: true
},
isNest: {
type: Boolean,
default: false
},
basePath: {
type: String,
default: ''
}
},
data() {
// To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
// TODO: refactor with render function
this.onlyOneChild = null
return {}
},
methods: {
hasOneShowingChild(children = [], parent) {
const showingChildren = children.filter(item => {
if (item.hidden) {
return false
} else {
// Temp set(will be used if only has one showing child)
this.onlyOneChild = item
return true
}
})
// When there is only one child router, the child router is displayed by default
if (showingChildren.length === 1) {
return true
}
// Show parent if there are no child router to display
if (showingChildren.length === 0) {
this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
return true
}
return false
},
resolvePath(routePath) {
if (isExternal(routePath)) {
return routePath
}
if (isExternal(this.basePath)) {
return this.basePath
}
return path.resolve(this.basePath, routePath)
}
}
}
</script>

@ -0,0 +1,56 @@
<template>
<div :class="{'has-logo':showLogo}">
<logo v-if="showLogo" :collapse="isCollapse" />
<el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu
:default-active="activeMenu"
:collapse="isCollapse"
:background-color="variables.menuBg"
:text-color="variables.menuText"
:unique-opened="false"
:active-text-color="variables.menuActiveText"
:collapse-transition="false"
mode="vertical"
>
<sidebar-item v-for="route in routes" :key="route.path" :item="route" :base-path="route.path" />
</el-menu>
</el-scrollbar>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import Logo from './Logo'
import SidebarItem from './SidebarItem'
import variables from '@/styles/variables.scss'
export default {
components: { SidebarItem, Logo },
computed: {
...mapGetters([
'sidebar'
]),
routes() {
return this.$router.options.routes
},
activeMenu() {
const route = this.$route
const { meta, path } = route
// if set path, the sidebar will highlight the path you set
if (meta.activeMenu) {
return meta.activeMenu
}
return path
},
showLogo() {
return this.$store.state.settings.sidebarLogo
},
variables() {
return variables
},
isCollapse() {
return !this.sidebar.opened
}
}
}
</script>

@ -0,0 +1,3 @@
export { default as Navbar } from './Navbar'
export { default as Sidebar } from './Sidebar'
export { default as AppMain } from './AppMain'

@ -0,0 +1,93 @@
<template>
<div :class="classObj" class="app-wrapper">
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
<sidebar class="sidebar-container" />
<div class="main-container">
<div :class="{'fixed-header':fixedHeader}">
<navbar />
</div>
<app-main />
</div>
</div>
</template>
<script>
import { Navbar, Sidebar, AppMain } from './components'
import ResizeMixin from './mixin/ResizeHandler'
export default {
name: 'Layout',
components: {
Navbar,
Sidebar,
AppMain
},
mixins: [ResizeMixin],
computed: {
sidebar() {
return this.$store.state.app.sidebar
},
device() {
return this.$store.state.app.device
},
fixedHeader() {
return this.$store.state.settings.fixedHeader
},
classObj() {
return {
hideSidebar: !this.sidebar.opened,
openSidebar: this.sidebar.opened,
withoutAnimation: this.sidebar.withoutAnimation,
mobile: this.device === 'mobile'
}
}
},
methods: {
handleClickOutside() {
this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
}
}
}
</script>
<style lang="scss" scoped>
@import "~@/styles/mixin.scss";
@import "~@/styles/variables.scss";
.app-wrapper {
@include clearfix;
position: relative;
height: 100%;
width: 100%;
&.mobile.openSidebar{
position: fixed;
top: 0;
}
}
.drawer-bg {
background: #000;
opacity: 0.3;
width: 100%;
top: 0;
height: 100%;
position: absolute;
z-index: 999;
}
.fixed-header {
position: fixed;
top: 0;
right: 0;
z-index: 9;
width: calc(100% - #{$sideBarWidth});
transition: width 0.28s;
}
.hideSidebar .fixed-header {
width: calc(100% - 54px)
}
.mobile .fixed-header {
width: 100%;
}
</style>

@ -0,0 +1,45 @@
import store from '@/store'
const { body } = document
const WIDTH = 992 // refer to Bootstrap's responsive design
export default {
watch: {
$route(route) {
if (this.device === 'mobile' && this.sidebar.opened) {
store.dispatch('app/closeSideBar', { withoutAnimation: false })
}
}
},
beforeMount() {
window.addEventListener('resize', this.$_resizeHandler)
},
beforeDestroy() {
window.removeEventListener('resize', this.$_resizeHandler)
},
mounted() {
const isMobile = this.$_isMobile()
if (isMobile) {
store.dispatch('app/toggleDevice', 'mobile')
store.dispatch('app/closeSideBar', { withoutAnimation: true })
}
},
methods: {
// use $_ for mixins properties
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
$_isMobile() {
const rect = body.getBoundingClientRect()
return rect.width - 1 < WIDTH
},
$_resizeHandler() {
if (!document.hidden) {
const isMobile = this.$_isMobile()
store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop')
if (isMobile) {
store.dispatch('app/closeSideBar', { withoutAnimation: true })
}
}
}
}
}

@ -0,0 +1,58 @@
import Vue from 'vue'
import 'normalize.css/normalize.css' // A modern alternative to CSS resets
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import locale from 'element-ui/lib/locale/lang/en' // lang i18n
import '@/styles/index.scss' // global css
import App from './App'
import store from './store'
import router from './router'
import '@/icons' // icon
import '@/permission' // permission control
/**
* If you don't want to use mock-server
* you want to use MockJs for mock api
* you can execute: mockXHR()
*
* Currently MockJs will be used in the production environment,
* please remove it before going online ! ! !
*/
if (process.env.NODE_ENV === 'production') {
const { mockXHR } = require('../mock')
mockXHR()
}
// set ElementUI lang to EN
Vue.use(ElementUI, { locale })
// 如果想要中文版 element-ui按如下方式声明
// Vue.use(ElementUI)
Vue.config.productionTip = false
Vue.prototype.$myGlobalVariable = {
age: '20',
weight: '65',
height: '175',
selectedSex: '0',
selectedActivity: '1',
calories:'',
protein:'',
carb:'',
fat:'',
BMR:'',
};
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})

@ -0,0 +1,64 @@
import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken } from '@/utils/auth' // get token from cookie
import getPageTitle from '@/utils/get-page-title'
NProgress.configure({ showSpinner: false }) // NProgress Configuration
const whiteList = ['/login'] // no redirect whitelist
router.beforeEach(async(to, from, next) => {
// start progress bar
NProgress.start()
// set page title
document.title = getPageTitle(to.meta.title)
// determine whether the user has logged in
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') {
// if is logged in, redirect to the home page
next({ path: '/' })
NProgress.done()
} else {
const hasGetUserInfo = store.getters.name
if (hasGetUserInfo) {
next()
} else {
try {
// get user info
await store.dispatch('user/getInfo')
next()
} catch (error) {
// remove token and go to login page to re-login
await store.dispatch('user/resetToken')
Message.error(error || 'Has Error')
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
}
} else {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) {
// in the free login whitelist, go directly
next()
} else {
// other pages that do not have permission to access are redirected to the login page.
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
})
router.afterEach(() => {
// finish progress bar
NProgress.done()
})

@ -0,0 +1,199 @@
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
/* Layout */
import Layout from '@/layout'
/**
* Note: sub-menu only appear when route children.length >= 1
* Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
*
* hidden: true if set true, item will not show in the sidebar(default is false)
* alwaysShow: true if set true, will always show the root menu
* if not set alwaysShow, when item has more than one children route,
* it will becomes nested mode, otherwise not show the root menu
* redirect: noRedirect if set noRedirect will no redirect in the breadcrumb
* name:'router-name' the name is used by <keep-alive> (must set!!!)
* meta : {
roles: ['admin','editor'] control the page roles (you can set multiple roles)
title: 'title' the name show in sidebar and breadcrumb (recommend set)
icon: 'svg-name'/'el-icon-x' the icon show in the sidebar
breadcrumb: false if set false, the item will hidden in breadcrumb(default is true)
activeMenu: '/example/list' if set path, the sidebar will highlight the path you set
}
*/
/**
* constantRoutes
* a base page that does not have permission requirements
* all roles can be accessed
*/
export const constantRoutes = [
{
path: '/login',
component: () => import('@/views/login/index'),
hidden: true
},
{
path: '/404',
component: () => import('@/views/404'),
hidden: true
},
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [{
path: 'dashboard',
name: 'Dashboard',
component: () => import('@/views/dashboard/index'),
meta: { title: '首页', icon: 'dashboard' }
}]
},
{
// 治理定义左边这栏菜单
path: '/sys',
component: Layout,
redirect: '/sys/user',
name: 'sysManage',
meta: { title: '饮食规划', icon: 'el-icon-s-help' },
// 上边的右边是图标图标要svg格式先不管
children: [
// children是二级菜单
{
path: 'user',
name: '个人信息',
component: () => import('@/views/table/index'),
// 上面是点开后导引到哪个文件
meta: { title: '个人信息', icon: 'table' }
},
{
path: 'table',
name: '生成菜谱',
component: () => import('@/views/sys/user2'),
// 上面是点开后导引到哪个文件
meta: { title: '饮食建议', icon: 'table' }
},
{
path: 'tree',
name: '查看菜谱',
component: () => import('@/views/tree'),
meta: { title: '每日菜谱', icon: 'tree' }
}
]
},
// {
// path: '/form',
// component: Layout,
// children: [
// {
// path: 'index',
// name: 'Form',
// component: () => import('@/views/form/index'),
// meta: { title: 'Form', icon: 'form' }
// }
// ]
// },
{
path: '/nested',
component: Layout,
redirect: '/nested/menu1',
name: 'Nested',
meta: { title: '菜品搜索', icon: 'nested' },
children: [
{
path: 'menu1',
component: () => import('@/views/nested/menu1/index'),
name: 'Menu1',
meta: { title: '面食' }
},
{
path: 'menu4',
component: () => import('@/views/nested/menu4/index'),
name: 'Menu4',
meta: { title: '炒菜' },
},
{
path: 'menu3',
component: () => import('@/views/nested/menu3/index'),
name: 'Menu3',
meta: { title: '饮品' }
},
{
path: 'menu5',
component: () => import('@/views/nested/menu5/index'),
name: 'Menu5',
meta: { title: '其它' }
},
{
path: 'menu2',
component: () => import('@/views/nested/menu2/index'),
name: 'Menu2',
meta: { title: '直接搜索' }
}
]
},
{
path: '/form',
component: Layout,
children: [
{
path: 'index',
name: 'Form',
component: () => import('@/views/form/index'),
meta: { title: '修改菜品数据', icon: 'form' }
}
]
},
{
path: '/form',
component: Layout,
children: [
{
path: 'id',
name: 'Form',
component: () => import('@/views/form/id'),
meta: { title: '评价反馈', icon: 'form' }
}
]
},
// {
// path: 'external-link',
// component: Layout,
// children: [
// {
// path: 'https://panjiachen.github.io/vue-element-admin-site/#/',
// meta: { title: 'External Link', icon: 'link' }
// }
// ]
// },
// 404 page must be placed at the end !!!
{ path: '*', redirect: '/404', hidden: true }
]
const createRouter = () => new Router({
// mode: 'hash', // require service support
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})
const router = createRouter()
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher // reset router
}
export default router

@ -0,0 +1,11 @@
// 数据库连接配置 db.js
module.exports = {
mysql: {
host: '192.168.×××.××',//mysql连接ip地址
user: '***',
password: '***',//mySql用户名密码
database: '***',//mySql数据库名
port: '3306'//mysql连接端口
}
}

@ -0,0 +1,20 @@
// node 后端服务器
const userApi = require('./api/userApi');
const fs = require('fs');
const path = require('path');
const bodyParser = require('body-parser');
const express = require('express');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
// 后端api路由
app.use('/api', userApi);
// 监听端口
app.listen(3306);
console.log('success listen at port:3000......');

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save