├── README.md ├── admin ├── .env.development ├── .env.production ├── .gitignore ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ └── static │ │ └── lib │ │ ├── echarts │ │ ├── dark.js │ │ ├── echarts.min.js │ │ └── shine.js │ │ └── jsencrypt.min.js ├── src │ ├── App.vue │ ├── api │ │ ├── common │ │ │ ├── authorize.js │ │ │ ├── index.js │ │ │ ├── menu.js │ │ │ └── messageCenter.js │ │ ├── index.js │ │ └── instance.js │ ├── assets │ │ ├── css │ │ │ ├── common.scss │ │ │ ├── reset.scss │ │ │ └── variables.scss │ │ └── images │ │ │ ├── avatar.png │ │ │ ├── beian2.png │ │ │ ├── favicon.ico │ │ │ ├── favicon.png │ │ │ ├── login-bg.jpg │ │ │ ├── security.png │ │ │ ├── sprites-arrow-20.png │ │ │ ├── sprites-common-20.png │ │ │ ├── sprites-commons-30.png │ │ │ ├── sprites-edit-20.png │ │ │ ├── sprites-login-20.png │ │ │ └── success.png │ ├── components │ │ ├── BaseInfo │ │ │ └── index.vue │ │ ├── Charts │ │ │ ├── PieRnglike │ │ │ │ └── index.vue │ │ │ ├── chartColor.js │ │ │ └── index.vue │ │ ├── FileUploader │ │ │ └── index.vue │ │ ├── FormDialog │ │ │ ├── Form │ │ │ │ ├── FormItem.vue │ │ │ │ └── index.vue │ │ │ ├── index.js │ │ │ └── main.vue │ │ ├── PagerSelf │ │ │ └── index.vue │ │ ├── Pagination │ │ │ └── index.vue │ │ ├── TableColumnFilter │ │ │ └── index.vue │ │ ├── TableFilter │ │ │ ├── SearchItem.vue │ │ │ ├── components │ │ │ │ ├── HSelect.vue │ │ │ │ └── ZoneSelect │ │ │ │ │ └── index.vue │ │ │ └── index.vue │ │ ├── TableMain │ │ │ ├── TableItem.vue │ │ │ ├── components │ │ │ │ └── ContextMenu │ │ │ │ │ ├── index.js │ │ │ │ │ └── main.vue │ │ │ └── index.vue │ │ └── layout │ │ │ ├── EmptyLayout.vue │ │ │ ├── components │ │ │ ├── Breadcrumb.vue │ │ │ ├── HeaderBar.vue │ │ │ ├── LangSelect.vue │ │ │ ├── MenuBar.vue │ │ │ ├── MenuBarItem.vue │ │ │ ├── MenuToggle │ │ │ │ └── index.vue │ │ │ ├── MessageIco.vue │ │ │ ├── MyCollection.vue │ │ │ ├── ServiceMenu.vue │ │ │ └── UserInfo.vue │ │ │ ├── index.vue │ │ │ └── mixin │ │ │ └── ResizeHandler.js │ ├── filters │ │ └── index.js │ ├── main.js │ ├── router │ │ └── index.js │ ├── store │ │ ├── getters.js │ │ ├── index.js │ │ └── modules │ │ │ ├── app.js │ │ │ └── user.js │ ├── utils │ │ ├── cloudPlatform.js │ │ ├── constant.js │ │ ├── eventTracer.js │ │ ├── index.js │ │ ├── scrollTo.js │ │ └── validate.js │ └── views │ │ ├── dashboard │ │ ├── api │ │ │ └── index.js │ │ ├── router.js │ │ └── views │ │ │ └── index.vue │ │ ├── errorPage │ │ ├── 401.vue │ │ ├── 403.vue │ │ ├── 404.vue │ │ └── permission.vue │ │ ├── good │ │ ├── api │ │ │ ├── category.js │ │ │ ├── good.js │ │ │ └── index.js │ │ ├── router.js │ │ └── views │ │ │ ├── category │ │ │ └── index.vue │ │ │ └── list │ │ │ ├── edit.vue │ │ │ └── index.vue │ │ ├── login │ │ ├── router.js │ │ └── views │ │ │ ├── Login.vue │ │ │ └── particles.js │ │ ├── merchant │ │ ├── api │ │ │ ├── index.js │ │ │ └── merchant.js │ │ ├── router.js │ │ └── views │ │ │ └── merchant │ │ │ ├── detail.vue │ │ │ └── index.vue │ │ ├── order │ │ ├── api │ │ │ ├── index.js │ │ │ └── order.js │ │ ├── router.js │ │ └── views │ │ │ └── list │ │ │ ├── detail.vue │ │ │ └── index.vue │ │ ├── setting │ │ ├── router.js │ │ └── views │ │ │ ├── person │ │ │ └── index.vue │ │ │ └── shop │ │ │ └── index.vue │ │ └── system │ │ ├── api │ │ ├── file.js │ │ ├── index.js │ │ ├── log.js │ │ ├── menu.js │ │ ├── permission.js │ │ ├── role.js │ │ └── user.js │ │ ├── router.js │ │ └── views │ │ ├── file │ │ └── index.vue │ │ ├── log │ │ └── index.vue │ │ ├── menu │ │ └── index.vue │ │ ├── permission │ │ └── index.vue │ │ ├── role │ │ ├── index.vue │ │ ├── roleMenu.vue │ │ └── rolePermission.vue │ │ └── user │ │ └── index.vue └── vue.config.js ├── eggjs-uniapp-shop.sql ├── server ├── .autod.conf.js ├── .eslintignore ├── .eslintrc ├── .github │ └── workflows │ │ └── nodejs.yml ├── .gitignore ├── .travis.yml ├── README.md ├── app │ ├── config │ │ ├── index.ts │ │ └── permission.ts │ ├── controller │ │ ├── good │ │ │ ├── category.ts │ │ │ ├── home.ts │ │ │ └── order.ts │ │ ├── home.ts │ │ ├── log │ │ │ └── message.ts │ │ ├── member │ │ │ ├── address.ts │ │ │ └── fav.ts │ │ ├── merchant │ │ │ └── index.ts │ │ └── system │ │ │ ├── file.ts │ │ │ ├── menu.ts │ │ │ ├── permission.ts │ │ │ ├── req_log.ts │ │ │ ├── role.ts │ │ │ └── user.ts │ ├── extend │ │ ├── context.ts │ │ └── helper.ts │ ├── middleware │ │ ├── admin_req_log.ts │ │ ├── execption.ts │ │ └── requireLogin.ts │ ├── model │ │ ├── Good.ts │ │ ├── GoodCategory.ts │ │ ├── GoodImage.ts │ │ ├── GoodOrder.ts │ │ ├── GoodOrderLine.ts │ │ ├── GoodSpec.ts │ │ ├── LogMessage.ts │ │ ├── Merchant.ts │ │ ├── SystemFile.ts │ │ ├── SystemMenu.ts │ │ ├── SystemPermission.ts │ │ ├── SystemReqLog.ts │ │ ├── SystemRole.ts │ │ ├── SystemRoleMenu.ts │ │ ├── SystemRolePermission.ts │ │ ├── SystemUser.ts │ │ ├── UserAddress.ts │ │ └── UserFav.ts │ ├── public │ │ └── doc │ │ │ ├── api_data.json │ │ │ ├── api_project.json │ │ │ ├── css │ │ │ └── style.css │ │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ │ ├── img │ │ │ └── favicon.ico │ │ │ ├── index.html │ │ │ └── vendor │ │ │ ├── bootstrap.min.css │ │ │ ├── path-to-regexp │ │ │ └── LICENSE │ │ │ └── prism.css │ ├── router.ts │ └── service │ │ ├── good │ │ ├── category.ts │ │ ├── home.ts │ │ └── order.ts │ │ ├── log │ │ └── message.ts │ │ ├── member │ │ ├── address.ts │ │ └── fav.ts │ │ ├── merchant │ │ └── index.ts │ │ └── system │ │ ├── file.ts │ │ ├── menu.ts │ │ ├── permission.ts │ │ ├── req_log.ts │ │ ├── role.ts │ │ └── user.ts ├── appveyor.yml ├── config │ ├── config.default.ts │ ├── config.local.ts │ ├── config.prod.ts │ └── plugin.ts ├── package-lock.json ├── package.json ├── test │ └── app │ │ ├── controller │ │ └── home.test.ts │ │ └── service │ │ └── Test.test.ts ├── tsconfig.json └── typings │ ├── app │ ├── controller │ │ └── index.d.ts │ ├── extend │ │ ├── context.d.ts │ │ └── helper.d.ts │ ├── index.d.ts │ ├── middleware │ │ └── index.d.ts │ ├── model │ │ └── index.d.ts │ └── service │ │ └── index.d.ts │ ├── config │ ├── index.d.ts │ └── plugin.d.ts │ └── index.d.ts └── uniapp ├── App.vue ├── Json.js ├── common ├── api │ ├── axios.js │ ├── common │ │ ├── file.js │ │ └── index.js │ ├── good │ │ ├── category.js │ │ └── index.js │ ├── index.js │ └── user │ │ ├── address.js │ │ ├── fav.js │ │ ├── index.js │ │ └── order.js └── utils │ └── index.js ├── components ├── empty.vue ├── mix-list-cell.vue ├── mix-loading │ └── mix-loading.vue ├── share.vue ├── uni-load-more │ └── uni-load-more.vue ├── uni-number-box.vue └── upload-images.vue ├── main.js ├── manifest.json ├── node_modules ├── axios │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── UPGRADE_GUIDE.md │ ├── dist │ │ ├── axios.js │ │ ├── axios.map │ │ ├── axios.min.js │ │ └── axios.min.map │ ├── index.d.ts │ ├── index.js │ ├── lib │ │ ├── adapters │ │ │ ├── README.md │ │ │ ├── http.js │ │ │ └── xhr.js │ │ ├── axios.js │ │ ├── cancel │ │ │ ├── Cancel.js │ │ │ ├── CancelToken.js │ │ │ └── isCancel.js │ │ ├── core │ │ │ ├── Axios.js │ │ │ ├── InterceptorManager.js │ │ │ ├── README.md │ │ │ ├── buildFullPath.js │ │ │ ├── createError.js │ │ │ ├── dispatchRequest.js │ │ │ ├── enhanceError.js │ │ │ ├── mergeConfig.js │ │ │ ├── settle.js │ │ │ └── transformData.js │ │ ├── defaults.js │ │ ├── helpers │ │ │ ├── README.md │ │ │ ├── bind.js │ │ │ ├── buildURL.js │ │ │ ├── combineURLs.js │ │ │ ├── cookies.js │ │ │ ├── deprecatedMethod.js │ │ │ ├── isAbsoluteURL.js │ │ │ ├── isURLSameOrigin.js │ │ │ ├── normalizeHeaderName.js │ │ │ ├── parseHeaders.js │ │ │ └── spread.js │ │ └── utils.js │ └── package.json └── follow-redirects │ ├── LICENSE │ ├── README.md │ ├── debug.js │ ├── http.js │ ├── https.js │ ├── index.js │ └── package.json ├── package-lock.json ├── pages.json ├── pages ├── address │ ├── address.vue │ └── addressManage.vue ├── cart │ └── cart.vue ├── category │ └── category.vue ├── detail │ └── detail.vue ├── index │ └── index.vue ├── money │ ├── money.vue │ ├── orderSuccess.vue │ ├── pay.vue │ └── paySuccess.vue ├── notice │ └── notice.vue ├── order │ ├── createOrder.vue │ └── order.vue ├── product │ ├── list.vue │ └── product.vue ├── public │ └── login.vue ├── set │ └── set.vue ├── user │ ├── fav.vue │ └── user.vue └── userinfo │ ├── setting.vue │ └── userinfo.vue ├── static ├── arc.png ├── emptyCart.jpg ├── errorImage.jpg ├── missing-face.png ├── select.png ├── selected.png ├── tab-cart-current.png ├── tab-cart.png ├── tab-cate-current.png ├── tab-cate.png ├── tab-home-current.png ├── tab-home.png ├── tab-my-current.png ├── tab-my.png ├── temp │ ├── ad-splash.jpg │ ├── ad1.jpg │ ├── ad2.jpg │ ├── ad3.jpg │ ├── banner1.jpg │ ├── banner2.jpg │ ├── banner3.jpg │ ├── banner4.jpg │ ├── c1.png │ ├── c2.png │ ├── c3.png │ ├── c4.png │ ├── c5.png │ ├── c6.png │ ├── c7.png │ ├── c8.png │ ├── cate1.jpg │ ├── cate10.jpg │ ├── cate11.jpg │ ├── cate12.jpg │ ├── cate13.jpg │ ├── cate14.jpg │ ├── cate15.jpg │ ├── cate16.jpg │ ├── cate17.jpg │ ├── cate18.jpg │ ├── cate19.jpg │ ├── cate2.jpg │ ├── cate20.jpg │ ├── cate21.jpg │ ├── cate22.jpg │ ├── cate23.jpg │ ├── cate24.jpg │ ├── cate3.jpg │ ├── cate4.jpg │ ├── cate5.jpg │ ├── cate6.jpg │ ├── cate7.jpg │ ├── cate8.jpg │ ├── cate9.jpg │ ├── h1.png │ ├── secskill-img.jpg │ ├── share_moment.png │ ├── share_qq.png │ ├── share_qqzone.png │ └── share_wechat.png ├── user-bg.jpg ├── vip-card-bg.png └── yticon.ttf ├── store └── index.js └── uni.scss /README.md: -------------------------------------------------------------------------------- 1 | # eggjs-uniapp-shop 2 | 基于eggjs的商场管理系统,包含后端服务、后台管理、小程序商城 3 | 4 | ##技术栈 5 | 6 | 微信小程序:uni-app 7 | 8 | pc前端:vue2 + vuex + vue-router + element-ui 9 | 10 | 后端:node + egg.js + ES6 11 | 12 | ## 演示 13 | 14 | 后台管理地址:[http://mall.tucy.top/] 15 | 16 | 演示环境账号密码: 17 | |账号 | 密码 | 权限| 18 | | :----------: | :----: | :----------------------: | 19 | |admin|123456 |超级管理员,拥有菜单、权限商家等功能管理| 20 | |tcy|123456|商家,拥有商品、订单等功能| 21 | 22 | ## 功能模块 23 | 24 | -- 小程序 25 | 26 | ✔登录 ✔分类列表 ✔商品列表 ✔购物车 ✔订单管理 ✔地址管理 ✔我的收藏 ✔资料设置 27 | 28 | -- pc管理后台 29 | 30 | ** 系统管理员 ** 31 | 32 | ✔ 用户管理 33 | ✔ 角色管理 34 | ✔ 权限管理 35 | ✔ 操作日志 36 | ✔ 文件管理 37 | ✔ 商家管理 38 | 39 | ** 商家 ** 40 | 41 | ✔ 商品管理 42 | ✔ 订单管理 43 | ✔ 商品分类 44 | ✔ 个人资料 45 | ✔ 店铺资料 46 | 47 | ## 欢迎Star && PR 48 | 49 | 如果项目有帮助到你可以点个Star支持下。有更好的实现欢迎PR。 50 | 51 | ## 沟通交流 52 | 53 | 交流群:145679486 54 | 55 | -------------------------------------------------------------------------------- /admin/.env.development: -------------------------------------------------------------------------------- 1 | VUE_APP_SERVER_URL=http://localhost:7001 2 | VUE_APP_MODULE=system,login,merchant,good,setting,dashboard,order -------------------------------------------------------------------------------- /admin/.env.production: -------------------------------------------------------------------------------- 1 | VUE_APP_SERVER_URL= 2 | VUE_APP_MODULE=system,login,merchant,good,setting,dashboard,order -------------------------------------------------------------------------------- /admin/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /admin/README.md: -------------------------------------------------------------------------------- 1 | # devops-viper 2 | 3 | ## Project setup 4 | ``` 5 | npm install 6 | ``` 7 | 8 | ### Compiles and hot-reloads for development 9 | ``` 10 | npm run serve 11 | ``` 12 | 13 | ### Compiles and minifies for production 14 | ``` 15 | npm run build 16 | ``` 17 | 18 | ### Lints and fixes files 19 | ``` 20 | npm run lint 21 | ``` 22 | 23 | ### Customize configuration 24 | See [Configuration Reference](https://cli.vuejs.org/config/). 25 | -------------------------------------------------------------------------------- /admin/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /admin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "devops-viper", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "@tinymce/tinymce-vue": "^3.2.4", 12 | "ansicolor": "^1.1.93", 13 | "axios": "^0.20.0", 14 | "core-js": "^3.6.5", 15 | "element-ui": "^2.13.2", 16 | "js-cookie": "^2.2.1", 17 | "node-sass": "^4.14.1", 18 | "sass-loader": "^10.0.4", 19 | "vue": "^2.6.11", 20 | "vue-router": "^3.4.7", 21 | "vuex": "^3.5.1" 22 | }, 23 | "devDependencies": { 24 | "@vue/cli-plugin-babel": "~4.5.0", 25 | "@vue/cli-plugin-eslint": "~4.5.0", 26 | "@vue/cli-service": "~4.5.0", 27 | "babel-eslint": "^10.1.0", 28 | "eslint": "^6.7.2", 29 | "eslint-plugin-vue": "^6.2.2", 30 | "vue-template-compiler": "^2.6.11" 31 | }, 32 | "eslintConfig": { 33 | "root": true, 34 | "env": { 35 | "node": true 36 | }, 37 | "extends": [ 38 | "plugin:vue/essential", 39 | "eslint:recommended" 40 | ], 41 | "parserOptions": { 42 | "parser": "babel-eslint" 43 | }, 44 | "rules": {} 45 | }, 46 | "browserslist": [ 47 | "> 1%", 48 | "last 2 versions", 49 | "not dead" 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /admin/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/admin/public/favicon.ico -------------------------------------------------------------------------------- /admin/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 |
20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /admin/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | 16 | 19 | -------------------------------------------------------------------------------- /admin/src/api/common/authorize.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 用户相关api接口 3 | * 4 | * @author 5 | * @email 6 | * @phone 7 | * @create 2019-02-12 11:00 8 | * */ 9 | 10 | import axios from '../index'; 11 | 12 | export default{ 13 | me:()=>axios.get('/authorize/me'), 14 | login:(opt)=>axios.post('/authorize/login',{token_type: 'SMART_SESSIONID',...opt}), 15 | logout:()=>axios.get('/authorize/login-out') 16 | } -------------------------------------------------------------------------------- /admin/src/api/common/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 公共api接口 3 | * 4 | * @author 5 | * @email 6 | * @phone 7 | * @create 2019-02-12 11:00 8 | * */ 9 | 10 | import axios from '../index'; 11 | import {genNonDuplicateID} from '@/utils/index'; 12 | import menu from './menu' 13 | 14 | export default{ 15 | menu 16 | } 17 | /** 18 | * @description 设置语言 19 | * 20 | * @return [ Object ] 必反,返回菜单数组 21 | * 22 | * */ 23 | export function setLanguage(lan){ 24 | return axios.get('/language?locale='+lan); 25 | } 26 | /** 27 | * @description 主机操作触发事件 28 | * 29 | * params {Object} opt 参数对象 必含属性eventIds 30 | * @return {} 31 | * */ 32 | // var tracerTime = 0; 33 | export function eventTracer(opt){ 34 | return axios.get('/eventTracer',{params:opt}); 35 | } 36 | 37 | /** 38 | * @description 文件上传 39 | * 40 | * @return [ Object ] 必反,返回菜单数组 41 | * 42 | * */ 43 | export function fileUpload(formData,currFile,progressCallback,singleLoading){ 44 | 45 | return axios({ 46 | method: 'post', 47 | url: '/api/file/upload?random='+genNonDuplicateID(6), 48 | headers: { 49 | 'Content-Type': 'multipart/form-data' 50 | }, 51 | data: formData, 52 | onUploadProgress: (progressEvent) => { 53 | if(!currFile) return 54 | currFile['percent'] = (progressEvent.loaded / progressEvent.total * 100 | 0); 55 | if(progressCallback && typeof progressCallback == 'function'){ 56 | progressCallback(currFile['percent']); 57 | } 58 | 59 | if(singleLoading){ 60 | singleLoading['percent'] = (progressEvent.loaded / progressEvent.total * 100 | 0); 61 | if(progressCallback && typeof progressCallback == 'function'){ 62 | progressCallback(singleLoading['percent']); 63 | } 64 | } 65 | } 66 | }) 67 | 68 | // return axios.post('/hyperone/file/upload?random='+genNonDuplicateID(6),formData); 69 | } 70 | /** 71 | * @description 文件删除 72 | * 73 | * @return [ Object ] 74 | * 75 | * */ 76 | export function deleteUpload(opt){ 77 | return axios.delete('/file/'+opt.id); 78 | } 79 | 80 | 81 | //获取当前系统版本 82 | export function getCurrentVersion(){ 83 | return axios.get('/version'); 84 | } -------------------------------------------------------------------------------- /admin/src/api/common/messageCenter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 审计日志 3 | * 4 | * @author 5 | * @email 6 | * @phone 7 | * @create 2019-09-17 11:00 8 | * */ 9 | 10 | import axios from '@/api'; 11 | 12 | export default{ 13 | list:()=>axios.get('/messageCenter/'+id), 14 | remove:(id)=>axios.post('/messageCenter/readOrDelete',id) 15 | } -------------------------------------------------------------------------------- /admin/src/api/instance.js: -------------------------------------------------------------------------------- 1 | import system from '@/views/system/api' 2 | import merchant from '@/views/merchant/api' 3 | export default{ 4 | system, 5 | merchant 6 | } -------------------------------------------------------------------------------- /admin/src/assets/css/variables.scss: -------------------------------------------------------------------------------- 1 | // base color 2 | $base-color: #d55e9a; //基础粉色 3 | $blue-auto:#5fbbfc; //基础蓝色 4 | $blue-dark:#256ba9; //基础蓝色 5 | $theme-bg: rgba(67,67,67,1); //头部与左侧黑色 6 | $light-blue: #3A71A8; //蓝色 7 | $red-auto: #ff0000; //红色 8 | $green-auto: #39c700; //绿色 9 | $orange-auto: #ff9600; //橙色 10 | $orange-light: #faf2ed; 11 | $background-aoto:#efe6d6; //背景颜色 12 | 13 | $black-dark: #323232; //菜单选中背景色 14 | $black-light: #434343; //菜单背景色 15 | $black-pale: #666666; 16 | $black-half: #aaa; 17 | $gray-1: #808080; //文字颜色 18 | $gray-2: #cccccc; //文字 19 | $gray-3: #e7e7e7; //描边 20 | $gray-4: #f2f2f2; //表头 21 | $gray-5: #fafafa; //隔行换色 22 | 23 | $red-select: #ff8d1a; 24 | 25 | $boxShadow: rgba(0,0,0,.05); 26 | -------------------------------------------------------------------------------- /admin/src/assets/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/admin/src/assets/images/avatar.png -------------------------------------------------------------------------------- /admin/src/assets/images/beian2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/admin/src/assets/images/beian2.png -------------------------------------------------------------------------------- /admin/src/assets/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/admin/src/assets/images/favicon.ico -------------------------------------------------------------------------------- /admin/src/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/admin/src/assets/images/favicon.png -------------------------------------------------------------------------------- /admin/src/assets/images/login-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/admin/src/assets/images/login-bg.jpg -------------------------------------------------------------------------------- /admin/src/assets/images/security.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/admin/src/assets/images/security.png -------------------------------------------------------------------------------- /admin/src/assets/images/sprites-arrow-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/admin/src/assets/images/sprites-arrow-20.png -------------------------------------------------------------------------------- /admin/src/assets/images/sprites-common-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/admin/src/assets/images/sprites-common-20.png -------------------------------------------------------------------------------- /admin/src/assets/images/sprites-commons-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/admin/src/assets/images/sprites-commons-30.png -------------------------------------------------------------------------------- /admin/src/assets/images/sprites-edit-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/admin/src/assets/images/sprites-edit-20.png -------------------------------------------------------------------------------- /admin/src/assets/images/sprites-login-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/admin/src/assets/images/sprites-login-20.png -------------------------------------------------------------------------------- /admin/src/assets/images/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/admin/src/assets/images/success.png -------------------------------------------------------------------------------- /admin/src/components/FormDialog/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import main from './main.vue' 3 | import store from '@/store' 4 | const Constructor = Vue.extend(main); 5 | let instance 6 | 7 | const initInstance = (options) => { 8 | instance = new Constructor({ 9 | el: document.createElement('div'), 10 | store, 11 | data: options 12 | }); 13 | document.body.appendChild(instance.$el) 14 | instance.doClose = function(){ 15 | instance.visible = false; 16 | setTimeout(()=>{ 17 | if(instance){ 18 | instance.svisible=false; 19 | document.body.removeChild(instance && instance.$el); 20 | instance =null 21 | } 22 | },300) 23 | }; 24 | }; 25 | 26 | const dialogForm = { 27 | show(options) { 28 | if(!instance){ 29 | initInstance(options) 30 | } 31 | // for (let prop in options) { 32 | // if (options.hasOwnProperty(prop)) { 33 | // instance[prop] = options[prop]; 34 | // } 35 | // } 36 | instance.visible =true 37 | }, 38 | hide(){ 39 | instance && instance.doClose() 40 | }, 41 | close() { 42 | instance && instance.doClose(); 43 | } 44 | } 45 | export default dialogForm -------------------------------------------------------------------------------- /admin/src/components/FormDialog/main.vue: -------------------------------------------------------------------------------- 1 | 19 | 78 | -------------------------------------------------------------------------------- /admin/src/components/PagerSelf/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 23 | 83 | -------------------------------------------------------------------------------- /admin/src/components/TableColumnFilter/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 21 | 48 | -------------------------------------------------------------------------------- /admin/src/components/TableFilter/components/ZoneSelect/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 55 | -------------------------------------------------------------------------------- /admin/src/components/TableMain/TableItem.vue: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /admin/src/components/TableMain/components/ContextMenu/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import main from './main.vue' 3 | import store from '@/store' 4 | const Constructor = Vue.extend(main); 5 | let instance 6 | 7 | const initInstance = (options) => { 8 | instance = new Constructor({ 9 | el: document.createElement('div'), 10 | store, 11 | data: options 12 | }); 13 | document.body.appendChild(instance.$el) 14 | instance.doClose = function(){ 15 | instance.visible = false; 16 | 17 | document.body.removeChild(instance.$el); 18 | instance =null 19 | 20 | 21 | } 22 | }; 23 | 24 | const dialogForm = { 25 | show(options) { 26 | if(instance){ 27 | instance.doClose(); 28 | } 29 | setTimeout(()=>{ 30 | initInstance(options) 31 | 32 | instance.visible =true 33 | }) 34 | 35 | }, 36 | hide(){ 37 | instance && instance.doClose() 38 | } 39 | } 40 | export default dialogForm -------------------------------------------------------------------------------- /admin/src/components/layout/EmptyLayout.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /admin/src/components/layout/components/LangSelect.vue: -------------------------------------------------------------------------------- 1 | 14 | 62 | -------------------------------------------------------------------------------- /admin/src/components/layout/components/MenuBarItem.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | -------------------------------------------------------------------------------- /admin/src/components/layout/components/MenuToggle/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | 16 | 32 | 33 | 41 | -------------------------------------------------------------------------------- /admin/src/components/layout/mixin/ResizeHandler.js: -------------------------------------------------------------------------------- 1 | import store from '@/store' 2 | 3 | const { body } = document 4 | const WIDTH = 900 5 | const RATIO = 3 6 | 7 | export default { 8 | watch: { 9 | $route() { 10 | if (this.device === 'mobile' && this.sidebar.opened) { 11 | // store.dispatch('closeSideBar', { withoutAnimation: false }) 12 | } 13 | } 14 | }, 15 | beforeMount() { 16 | window.addEventListener('resize', this.resizeHandler) 17 | }, 18 | mounted() { 19 | const isMobile = this.isMobile() 20 | if (isMobile) { 21 | store.dispatch('toggleDevice', 'mobile') 22 | store.dispatch('showSideBar', { withoutAnimation: true }) 23 | } 24 | /* header二级菜单添加最大高度,防止内容溢出 */ 25 | let bodyHeight = body.clientHeight; 26 | let submenus = document.getElementsByClassName('submenu'); 27 | for(let i=0;i { 18 | Vue.filter(key, filters[key]) 19 | }) 20 | /* 全局权限配置 */ 21 | Vue.prototype.$auth = function(authId, action) { 22 | if (store.getters.permission && store.getters.permission[authId] && store.getters.permission[authId][action]) { 23 | return true; 24 | } 25 | return false; 26 | } 27 | import TableMain from '@/components/TableMain'; 28 | Vue.component('TableMain',TableMain) 29 | import TableFilter from '@/components/TableFilter'; 30 | Vue.component('TableFilter',TableFilter) 31 | new Vue({ 32 | render: h => h(App), 33 | router, 34 | store 35 | }).$mount('#app') 36 | -------------------------------------------------------------------------------- /admin/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | import store from '@/store'; 4 | Vue.use(VueRouter) 5 | 6 | const routes = [ 7 | ] 8 | 9 | const router = new VueRouter({ 10 | mode: 'hash', 11 | base: process.env.BASE_URL, 12 | routes 13 | }) 14 | var isAdd = false; 15 | var initDynamicRouters = function(callback){ 16 | if(isAdd){ 17 | callback && callback(); 18 | return; 19 | } 20 | /* 根据env配置文件,动态加载路由 */ 21 | Promise.all( 22 | process.env.VUE_APP_MODULE && process.env.VUE_APP_MODULE.split(',').map(item=>{ 23 | return import('@/views/'+item+'/router') 24 | }) 25 | ).then(modules=>{ 26 | modules.forEach((module)=>{ 27 | router.options.routes = [...module.default,...router.options.routes] 28 | router.addRoutes(module.default) 29 | }) 30 | /* 添加404路由,必须加在路由最后面 */ 31 | let notfoundRoute = [{ 32 | path: '*', 33 | component: ()=>import('@/components/layout/index.vue'), 34 | children: [{ 35 | path: '', 36 | component: () => import('@/views/errorPage/404.vue'), 37 | hidden: true 38 | }] 39 | }] 40 | router.options.routes = [...router.options.routes,...notfoundRoute] 41 | router.addRoutes(notfoundRoute); 42 | callback && callback(); 43 | isAdd=true; 44 | }) 45 | } 46 | initDynamicRouters(); 47 | 48 | router.beforeEach((to, from, next) => { 49 | const whiteList = ['/login','/401','/404','/403','/signup'] // 不需要重定向白名单 50 | // next();return;//暂时去掉登录拦截 51 | if (whiteList.indexOf(to.path) != -1 || to.path.indexOf('login')>-1) { // 在免登录白名单,直接进入 52 | next() 53 | } else { 54 | if (!store.getters.user.id) { // 判断页面是否刷新 55 | store.dispatch('GetUserInfo',true).then(() => {// 拉取user_info 56 | next({ 57 | path: to.path, 58 | query: to.query, 59 | params: to.params, 60 | replace: true 61 | }) 62 | 63 | }).catch(() => { 64 | let path = '/login' 65 | next({ 66 | path: path, 67 | query: { redirect: to.fullPath }, 68 | replace: true 69 | }) 70 | }) 71 | } else { 72 | next() 73 | } 74 | } 75 | // eslint-disable-next-line no-console 76 | 77 | }) 78 | router.afterEach(() => { 79 | 80 | }); 81 | 82 | export default router 83 | -------------------------------------------------------------------------------- /admin/src/store/getters.js: -------------------------------------------------------------------------------- 1 | export default { 2 | user: state => state.user.user, 3 | sidebar: state => state.app.sidebar, 4 | device: state => state.app.device, 5 | theme: state => state.app.theme, 6 | baseUrl: state=>state.app.baseUrl, 7 | } -------------------------------------------------------------------------------- /admin/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | import app from './modules/app' 5 | import user from './modules/user' 6 | import getters from './getters' 7 | 8 | Vue.use(Vuex); 9 | 10 | export default new Vuex.Store({ 11 | modules: { 12 | app, 13 | user, 14 | }, 15 | getters, 16 | }) -------------------------------------------------------------------------------- /admin/src/store/modules/user.js: -------------------------------------------------------------------------------- 1 | import systemApi from '@/views/system/api'; 2 | import Cookies from 'js-cookie' 3 | const user = { 4 | state: { 5 | user: {}, 6 | }, 7 | 8 | mutations: { 9 | SET_USER: (state, user) => { 10 | state.user = user 11 | localStorage.setItem('currentUser',JSON.stringify(user)); 12 | }, 13 | }, 14 | 15 | actions: { 16 | 17 | // 获取用户信息,refresh为true时,从后台获取数据 18 | GetUserInfo({ dispatch,commit, state },refresh) { 19 | 20 | return new Promise((resolve, reject) => { 21 | if(refresh){ 22 | systemApi.user.info().then((response,error) => { 23 | if(!response){ reject();return ;} 24 | commit('SET_USER', response.result); 25 | Cookies.set('currentUser',response.result.id); 26 | resolve(response) 27 | }).catch(error => { 28 | console.log(error,'error') 29 | reject(error) 30 | }) 31 | 32 | }else{ 33 | let currentUserId = Cookies.get('currentUser'); 34 | let currentUser = localStorage.getItem('currentUser'); 35 | if(currentUserId && currentUser){ 36 | currentUser = JSON.parse(currentUser); 37 | commit('SET_USER', currentUser); 38 | resolve({result:currentUser}); 39 | }else{ 40 | reject() 41 | } 42 | } 43 | }) 44 | }, 45 | 46 | // 登出 47 | LogOut({ commit, state }) { 48 | return new Promise((resolve, reject) => { 49 | systemApi.user.logout(state.token).then(() => { 50 | commit('SET_USER', {}); 51 | Cookies.remove('currentUser'); 52 | localStorage.removeItem('currentUser'); 53 | resolve() 54 | }).catch(error => { 55 | reject(error) 56 | }) 57 | }) 58 | }, 59 | clearUser({ commit, state }){ 60 | commit('SET_USER', {}); 61 | Cookies.remove('currentUser'); 62 | localStorage.removeItem('currentUser'); 63 | }, 64 | 65 | } 66 | }; 67 | 68 | export default user -------------------------------------------------------------------------------- /admin/src/utils/constant.js: -------------------------------------------------------------------------------- 1 | /* 2 | * des 枚举类型(数据转换) 3 | * 4 | * author hwx 5 | * 6 | * */ 7 | 8 | 9 | /** 10 | * @description FIXME qinjunqiang 优化调整 11 | * value 对应后台的参数(* 该字段的值不可随意修改) 12 | * title 仅仅是写给自己看或后期维护的人看(过一段时间后给自己或维护的人看能很快对应上) 13 | * displayName 最终的翻译后的字段 14 | * */ 15 | let _constMap = (() => { 16 | let obj = { 17 | UserStatus:[ 18 | {value: 1,label:'可用'}, 19 | {value: 2,label:'禁用'} 20 | ], 21 | UserSex:[ 22 | {value: 1,label:'男'}, 23 | {value: 2,label:'女'} 24 | ], 25 | UserType:[ 26 | {value: 1,label:'管理员'}, 27 | {value: 2,label:'商家'}, 28 | {value: 3,label:'用户'}, 29 | ], 30 | // ordered: '待付款', inpayment: '付款中', paid: '已付款,待发货', receiving: '已发货,待收货', completed: '已完成', canceled: '已取消',closed:已关闭 31 | OrderStatus:[ 32 | {value: "ordered",label: '待付款'}, 33 | {value: "inpayment",label: '付款中'}, 34 | {value: "paid",label: '待发货'}, 35 | {value: "receiving",label: '待收货'}, 36 | {value: "completed",label: '已完成'}, 37 | {value: "canceled",label: '已取消'}, 38 | {value: "closed",label: '已关闭'}, 39 | ] 40 | }; 41 | 42 | for (let key in obj) { 43 | let item = obj[key]; 44 | 45 | for (let i = 0; i < item.length; i++) { 46 | let cItem = item[i]; 47 | let k = item[i].langKey?item[i].langKey:'common'; 48 | 49 | // 给每一个数组对象新增一个翻译 lang 参数 50 | //!cItem['displayName'] && (cItem['displayName'] = i18n.t(k + '.' + cItem.lang)); 51 | } 52 | } 53 | 54 | return obj; 55 | })(); 56 | 57 | export const constantMap = _constMap; -------------------------------------------------------------------------------- /admin/src/utils/scrollTo.js: -------------------------------------------------------------------------------- 1 | Math.easeInOutQuad = function(t, b, c, d) { 2 | t /= d / 2 3 | if (d <= 0){ 4 | return c; 5 | } 6 | if (t < 1) { 7 | return c / 2 * t * t + b 8 | } 9 | t-- 10 | return -c / 2 * (t * (t - 2) - 1) + b 11 | } 12 | 13 | // requestAnimationFrame for Smart Animating http://goo.gl/sx5sts 14 | var requestAnimFrame = (function() { 15 | return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) } 16 | })() 17 | 18 | // because it's so fucking difficult to detect the scrolling element, just move them all 19 | function move(amount,container) { 20 | if(container){ 21 | container.scrollTop = amount; 22 | }else{ 23 | document.documentElement.scrollTop = amount 24 | document.body.parentNode.scrollTop = amount 25 | document.body.scrollTop = amount 26 | } 27 | 28 | } 29 | 30 | function position(container) { 31 | if(!container){ 32 | return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop 33 | }else{ 34 | return container.scrollTop 35 | } 36 | } 37 | 38 | export function scrollTo(to, duration, callback,container) { 39 | const start = position(container) 40 | const change = to - start 41 | const increment = 20 42 | let currentTime = 0 43 | duration = (typeof (duration) === 'undefined') ? 500 : duration 44 | var animateScroll = function() { 45 | // increment the time 46 | currentTime += increment 47 | // find the value with the quadratic in-out easing function 48 | var val = Math.easeInOutQuad(currentTime, start, change, duration) 49 | // move the document.body 50 | move(val,container) 51 | // do the animation unless its over 52 | if (currentTime < duration) { 53 | requestAnimFrame(animateScroll) 54 | } else { 55 | if (callback && typeof (callback) === 'function') { 56 | // the animation is done so lets callback 57 | callback() 58 | } 59 | } 60 | } 61 | animateScroll() 62 | } 63 | -------------------------------------------------------------------------------- /admin/src/views/dashboard/api/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/admin/src/views/dashboard/api/index.js -------------------------------------------------------------------------------- /admin/src/views/dashboard/router.js: -------------------------------------------------------------------------------- 1 | import Layout from '@/components/layout/index.vue' 2 | 3 | export default [{ 4 | path: '/', 5 | component: Layout, 6 | redirect: '/dashboard', 7 | children: [ 8 | { 9 | path: '/dashboard', 10 | component: ()=>import('./views/index'), 11 | }, 12 | ] 13 | }] -------------------------------------------------------------------------------- /admin/src/views/dashboard/views/index.vue: -------------------------------------------------------------------------------- 1 | 14 | 35 | -------------------------------------------------------------------------------- /admin/src/views/errorPage/401.vue: -------------------------------------------------------------------------------- 1 | 9 | 17 | 30 | -------------------------------------------------------------------------------- /admin/src/views/errorPage/403.vue: -------------------------------------------------------------------------------- 1 | 9 | 17 | 30 | -------------------------------------------------------------------------------- /admin/src/views/errorPage/404.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 18 | -------------------------------------------------------------------------------- /admin/src/views/good/api/category.js: -------------------------------------------------------------------------------- 1 | import axios from '@/api'; 2 | export default{ 3 | save:(params)=>axios.post('/api/goodCategory/save',params), 4 | select:(params)=>axios.get('/api/goodCategory/list',{params}), 5 | list:(params)=>axios.get('/api/goodCategory',{params}), 6 | tree:(params)=>axios.get('/api/goodCategory/tree',{params}), 7 | remove:(id)=>axios.delete('/api/goodCategory/'+id), 8 | update:(params)=>axios.post('/api/goodCategory/update',params), 9 | } -------------------------------------------------------------------------------- /admin/src/views/good/api/good.js: -------------------------------------------------------------------------------- 1 | import axios from '@/api'; 2 | export default{ 3 | save:(params)=>axios.post('/api/good/save',params), 4 | list:(params)=>axios.get('/api/good',{params}), 5 | detail:(id)=>axios.get('/api/good/'+id), 6 | remove:(id)=>axios.delete('/api/good/'+id), 7 | update:(params)=>axios.post('/api/good/update',params), 8 | } -------------------------------------------------------------------------------- /admin/src/views/good/api/index.js: -------------------------------------------------------------------------------- 1 | import good from './good' 2 | import category from './category' 3 | export default{ 4 | good, 5 | category 6 | } -------------------------------------------------------------------------------- /admin/src/views/good/router.js: -------------------------------------------------------------------------------- 1 | import Layout from '@/components/layout/index.vue' 2 | 3 | export default [{ 4 | path: '/good', 5 | component: Layout, 6 | redirect: '/good/list', 7 | children: [ 8 | { 9 | path: 'list', 10 | component: ()=>import('./views/list'), 11 | }, 12 | { 13 | path: 'list/create', 14 | component: ()=>import('./views/list/edit'), 15 | }, 16 | { 17 | path: 'category', 18 | component: ()=>import('./views/category'), 19 | }, 20 | ] 21 | }] -------------------------------------------------------------------------------- /admin/src/views/login/router.js: -------------------------------------------------------------------------------- 1 | import Login from './views/Login.vue' 2 | 3 | export default [ 4 | { 5 | path: '/login', 6 | name: 'login', 7 | component: Login, 8 | }, 9 | ] -------------------------------------------------------------------------------- /admin/src/views/merchant/api/index.js: -------------------------------------------------------------------------------- 1 | import merchant from './merchant' 2 | export default{ 3 | merchant 4 | } -------------------------------------------------------------------------------- /admin/src/views/merchant/api/merchant.js: -------------------------------------------------------------------------------- 1 | import axios from '@/api'; 2 | export default{ 3 | save:(params)=>axios.post('/api/merchant/save',params), 4 | list:(params)=>axios.get('/api/merchant',{params}), 5 | remove:(id)=>axios.delete('/api/merchant/'+id), 6 | update:(params)=>axios.post('/api/merchant/update',params), 7 | } -------------------------------------------------------------------------------- /admin/src/views/merchant/router.js: -------------------------------------------------------------------------------- 1 | import Layout from '@/components/layout/index.vue' 2 | 3 | export default [{ 4 | path: '/merchant', 5 | component: Layout, 6 | redirect: '/merchant/merchant', 7 | children: [ 8 | { 9 | path: 'merchant', 10 | component: ()=>import('./views/merchant'), 11 | }, 12 | ] 13 | }] -------------------------------------------------------------------------------- /admin/src/views/order/api/index.js: -------------------------------------------------------------------------------- 1 | import order from './order' 2 | export default{ 3 | order 4 | } -------------------------------------------------------------------------------- /admin/src/views/order/api/order.js: -------------------------------------------------------------------------------- 1 | import axios from '@/api'; 2 | export default{ 3 | save:(params)=>axios.post('/api/order/save',params), 4 | list:(params)=>axios.get('/api/order',{params}), 5 | detail:(id)=>axios.get('/api/order/'+id), 6 | remove:(id)=>axios.delete('/api/order/'+id), 7 | update:(params)=>axios.post('/api/order/update',params), 8 | } -------------------------------------------------------------------------------- /admin/src/views/order/router.js: -------------------------------------------------------------------------------- 1 | import Layout from '@/components/layout/index.vue' 2 | 3 | export default [{ 4 | path: '/order', 5 | component: Layout, 6 | redirect: '/order/list', 7 | children: [ 8 | { 9 | path: 'list', 10 | component: ()=>import('./views/list'), 11 | }, 12 | ] 13 | }] -------------------------------------------------------------------------------- /admin/src/views/setting/router.js: -------------------------------------------------------------------------------- 1 | import Layout from '@/components/layout/index.vue' 2 | 3 | export default [{ 4 | path: '/setting', 5 | component: Layout, 6 | redirect: '/setting/person', 7 | children: [ 8 | { 9 | path: 'person', 10 | component: ()=>import('./views/person'), 11 | }, 12 | { 13 | path: 'shop', 14 | component: ()=>import('./views/shop'), 15 | }, 16 | ] 17 | }] -------------------------------------------------------------------------------- /admin/src/views/system/api/file.js: -------------------------------------------------------------------------------- 1 | import axios from '@/api'; 2 | export default{ 3 | save:(params)=>axios.post('/api/file/save',params), 4 | list:(params)=>axios.get('/api/file',{params}), 5 | remove:(id)=>axios.delete('/api/file/'+id), 6 | update:(params)=>axios.post('/api/file/update',params), 7 | } -------------------------------------------------------------------------------- /admin/src/views/system/api/index.js: -------------------------------------------------------------------------------- 1 | import user from './user' 2 | import menu from './menu' 3 | import role from './role' 4 | import permission from './permission' 5 | import file from './file' 6 | import log from './log' 7 | export default{user,menu,role,permission,file,log} -------------------------------------------------------------------------------- /admin/src/views/system/api/log.js: -------------------------------------------------------------------------------- 1 | import axios from '@/api'; 2 | export default{ 3 | list:(params)=>axios.get('/api/system/reqlog',{params}), 4 | select:(params)=>axios.get('/api/system/reqlog/list',{params}), 5 | save:(opt)=>axios.post('/api/system/reqlog/save',opt), 6 | remove:(id)=>axios.delete('/api/system/reqlog/'+id), 7 | } -------------------------------------------------------------------------------- /admin/src/views/system/api/menu.js: -------------------------------------------------------------------------------- 1 | import axios from '@/api'; 2 | export default{ 3 | tree:(params)=>axios.get('/api/menu/tree',{params}), 4 | list:(params)=>axios.get('/api/menu',{params}), 5 | select:(params)=>axios.get('/api/menu/list',{params}), 6 | save:(opt)=>axios.post('/api/menu/save',opt), 7 | remove:(id)=>axios.delete('/api/menu/'+id), 8 | } -------------------------------------------------------------------------------- /admin/src/views/system/api/permission.js: -------------------------------------------------------------------------------- 1 | import axios from '@/api'; 2 | export default{ 3 | list:(params)=>axios.get('/api/permission',{params}), 4 | select:(params)=>axios.get('/api/permission/list',{params}), 5 | save:(opt)=>axios.post('/api/permission/save',opt), 6 | remove:(id)=>axios.delete('/api/permission/'+id), 7 | } -------------------------------------------------------------------------------- /admin/src/views/system/api/role.js: -------------------------------------------------------------------------------- 1 | import axios from '@/api'; 2 | export default{ 3 | list:(params)=>axios.get('/api/role',{params}), 4 | select:(params)=>axios.get('/api/role/list',{params}), 5 | detail:(id)=>axios.get('/api/role/'+id), 6 | save:(opt)=>axios.post('/api/role/save',opt), 7 | remove:(id)=>axios.delete('/api/role/'+id), 8 | //角色菜单保存 9 | menuSave:(id,opt)=>axios.post('/api/role/'+id+'/menu',opt), 10 | //角色菜单列表 11 | menuList:(id)=>axios.get('/api/role/'+id+'/menu'), 12 | //角色权限列表 13 | authList:(id)=>axios.get('/api/role/'+id+'/permission'), 14 | //角色权限保存 15 | authSave:(id,opt)=>axios.post('/api/role/'+id+'/permission',opt), 16 | } -------------------------------------------------------------------------------- /admin/src/views/system/api/user.js: -------------------------------------------------------------------------------- 1 | import axios from '@/api'; 2 | export default{ 3 | login:(params)=>axios.post('/api/user/login',params), 4 | logout:()=>axios.get('/api/user/logout'), 5 | save:(params)=>axios.post('/api/user/save',params), 6 | info:()=>axios.get('/api/user/info'), 7 | list:(params)=>axios.get('/api/user',{params}), 8 | remove:(id)=>axios.delete('/api/user/'+id), 9 | detail:(id)=>axios.get('/api/user/detail/'+id), 10 | update:(params)=>axios.post('/api/user/update',params), 11 | menu:()=>axios.get('/api/user/menu'), 12 | } -------------------------------------------------------------------------------- /admin/src/views/system/router.js: -------------------------------------------------------------------------------- 1 | import Layout from '@/components/layout/index.vue' 2 | 3 | export default [{ 4 | path: '/system', 5 | component: Layout, 6 | redirect: '/system/menu', 7 | children: [ 8 | { 9 | path: 'menu', 10 | component: ()=>import('./views/menu'), 11 | }, 12 | { 13 | path: 'role', 14 | component: ()=>import('./views/role'), 15 | }, 16 | { 17 | path: 'permission', 18 | component: ()=>import('./views/permission'), 19 | }, 20 | { 21 | path: 'user', 22 | component: ()=>import('./views/user'), 23 | }, 24 | { 25 | path: 'file', 26 | component: ()=>import('./views/file'), 27 | }, 28 | { 29 | path: 'log', 30 | component: ()=>import('./views/log'), 31 | } 32 | ] 33 | }] -------------------------------------------------------------------------------- /admin/vue.config.js: -------------------------------------------------------------------------------- 1 | module.exports={ 2 | lintOnSave: false, 3 | publicPath: '/', 4 | // 输出文件目录 5 | outputDir: 'dist', 6 | assetsDir: 'assets', 7 | productionSourceMap: false, 8 | pages: { 9 | index: { 10 | // page 的入口 11 | entry: 'src/main.js', 12 | // 模板来源 13 | template: 'public/index.html', 14 | // 在 dist/index.html 的输出 15 | filename: 'index.html', 16 | // 当使用 title 选项时, 17 | // template 中的 title 标签需要是 <%= htmlWebpackPlugin.options.title %> 18 | title: '后台管理系统', 19 | // 在这个页面中包含的块,默认情况下会包含 20 | // 提取出来的通用 chunk 和 vendor chunk。 21 | chunks: ['chunk-vendors', 'chunk-common', 'index'] 22 | } 23 | 24 | } 25 | } -------------------------------------------------------------------------------- /server/.autod.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | write: true, 5 | plugin: 'autod-egg', 6 | prefix: '^', 7 | devprefix: '^', 8 | exclude: [ 9 | 'test/fixtures', 10 | 'coverage', 11 | ], 12 | dep: [ 13 | 'egg', 14 | 'egg-scripts', 15 | ], 16 | devdep: [ 17 | 'autod', 18 | 'autod-egg', 19 | 'egg-bin', 20 | 'tslib', 21 | 'typescript', 22 | ], 23 | keep: [ 24 | ], 25 | semver: [ 26 | ], 27 | test: 'scripts', 28 | }; 29 | -------------------------------------------------------------------------------- /server/.eslintignore: -------------------------------------------------------------------------------- 1 | **/*.d.ts 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /server/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint-config-egg/typescript", 3 | "parserOptions": { 4 | "project": "./tsconfig.json" 5 | } 6 | } -------------------------------------------------------------------------------- /server/.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ${{ matrix.os }} 16 | 17 | strategy: 18 | matrix: 19 | node-version: [8.x] 20 | os: [ubuntu-latest, windows-latest, macos-latest] 21 | 22 | steps: 23 | - uses: actions/checkout@v2 24 | - name: Use Node.js ${{ matrix.node-version }} 25 | uses: actions/setup-node@v1 26 | with: 27 | node-version: ${{ matrix.node-version }} 28 | - run: npm i -g npminstall && npminstall 29 | - run: npm run ci 30 | env: 31 | CI: true 32 | -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | logs/ 2 | npm-debug.log 3 | node_modules/ 4 | coverage/ 5 | .idea/ 6 | run/ 7 | logs/ 8 | .DS_Store 9 | .vscode 10 | *.swp 11 | *.lock 12 | *.js 13 | !.autod.conf.js 14 | 15 | app/**/*.js 16 | test/**/*.js 17 | config/**/*.js 18 | app/**/*.map 19 | test/**/*.map 20 | config/**/*.map 21 | app/public/uploads/ 22 | -------------------------------------------------------------------------------- /server/.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: node_js 3 | node_js: 4 | - '8' 5 | before_install: 6 | - npm i npminstall -g 7 | install: 8 | - npminstall 9 | script: 10 | - npm run ci 11 | after_script: 12 | - npminstall codecov && codecov 13 | -------------------------------------------------------------------------------- /server/README.md: -------------------------------------------------------------------------------- 1 | # eggjs-uniapp-shop 2 | ### 基于egg.js+jwt+mysql编写的开箱即用的权限管理后台 3 | ### 后台: egg.js 4 | ### 数据库: mysql 5 | 6 | 7 | 👤 **tuchongyang** 8 | 9 | * Github: [@tuchongyang](https://github.com/tuchongyang) 10 | * QQ: 779311998 11 | * QQ群: 145679486 12 | 13 | ### 已实现功能 14 | #### 使用之前请先了解`egg.js`,然后把`/server/config/config.local.js`数据库配置成自己的,只要手动创建数据库就行,数据表在系统运行时会自动创建,并且自动创建超级管理员账号,为了系统稳定性该账号不可以被删除,不可以被降级权限 15 | 16 | - [x] 注册 17 | - [x] 登录 18 | - [x] token校验过期处理(临时过期,永久过期) 19 | - [ ] 微信登录 20 | - [x] 个人资料修改 21 | - [x] 角色管理,(增加,删除,修改)系统默认创建超级管理员角色,除了超级管理员任何角色不可对其删除修改 22 | - [x] 权限管理 对每个角色分配不同的页面路由权限和按钮权限,(当前角色的用户只能分配自己拥有的页面权限和按钮权限) 23 | - [x] 管理员对普通用户资料修改 24 | - [x] 账号管理(增加,删除,修改)系统默认创建超级管理员账号,除了超级管理员任何角色不可对其删除修改 25 | - [x] 添加账号 26 | - [x] 用户列表 27 | - [x] 用户状态管理 28 | 29 | 30 | 31 | 32 | ## 结语 33 | 如果这个框架对你有帮助的话,请给个星点个star 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /server/app/config/index.ts: -------------------------------------------------------------------------------- 1 | import permission from './permission' 2 | export default {permission} -------------------------------------------------------------------------------- /server/app/config/permission.ts: -------------------------------------------------------------------------------- 1 | export default{ 2 | actionNames: { 3 | "detail":'详情', 4 | "query":"查询", 5 | "add":"添加", 6 | "delete":"删除" 7 | } 8 | } -------------------------------------------------------------------------------- /server/app/controller/good/category.ts: -------------------------------------------------------------------------------- 1 | import { Controller } from 'egg'; 2 | import { bp } from 'egg-blueprint' 3 | /** 4 | * @Controller 商品分类 5 | */ 6 | bp.prefix('/api/goodCategory', 'GoodCategoryController') 7 | export default class GoodCategoryController extends Controller { 8 | /** 分页列表 */ 9 | @bp.get('/') 10 | public async index() { 11 | const { ctx } = this; 12 | let list = await ctx.service.good.category.list(ctx.query) 13 | ctx.success(list) 14 | } 15 | /** 不分页列表 */ 16 | @bp.get('/list') 17 | public async list() { 18 | const { ctx } = this; 19 | let list = await ctx.service.good.category.select(ctx.query) 20 | ctx.success(list) 21 | } 22 | /** 不分页列表,树形,用于类型选择框 */ 23 | @bp.get('/tree') 24 | public async tree() { 25 | const { ctx } = this; 26 | let list = await ctx.service.good.category.select(ctx.query); 27 | var getChildren = (parentId)=>{ 28 | var results = list.filter(a=>a.parentId==parentId); 29 | for(let i=0;i{ 66 | ctx.success() 67 | }).catch(err=>{ 68 | ctx.fail(400,err.message) 69 | }) 70 | } 71 | /**获取角色权限 */ 72 | @bp.get('/:id/permission') 73 | public async permission(){ 74 | const { ctx } = this; 75 | const data = await ctx.service.system.role.getPermission(ctx.params.id) 76 | ctx.success(data) 77 | } 78 | /**新增、保存角色权限 */ 79 | @bp.post('/:id/permission') 80 | public async permissionSave(){ 81 | const { ctx } = this; 82 | await ctx.service.system.role.savePermission(ctx.params.id,ctx.request.body).then(()=>{ 83 | ctx.success() 84 | }).catch(err=>{ 85 | ctx.fail(400,err.message) 86 | }) 87 | } 88 | 89 | 90 | 91 | } -------------------------------------------------------------------------------- /server/app/extend/context.ts: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | SUCCESS_CODE: 200, // 成功 3 | NO_LOGIN_CODE: 401, // 未登录 4 | UNIQUE_CODE: 200, // 唯一性冲突 5 | ERROR_CODE: 500, // 失败 6 | user() { 7 | return this.ctx.session.user; 8 | }, 9 | 10 | success(data, status) { 11 | this.body = { status: this.SUCCESS_CODE, result:data }; 12 | this.status = status || 200; 13 | }, 14 | 15 | fail(status, message,data) { 16 | this.body = { status, message, result:data }; 17 | this.status = status||400; 18 | }, 19 | 20 | notFound(msg) { 21 | msg = msg || 'not found'; 22 | this.throw(404, msg); 23 | } 24 | }; -------------------------------------------------------------------------------- /server/app/extend/helper.ts: -------------------------------------------------------------------------------- 1 | import { IHelper } from 'egg'; 2 | module.exports = { 3 | /** 4 | * 获取请求IP 5 | */ 6 | getReqIP(this: IHelper) { 7 | const req: any = this.ctx.req; 8 | return (req.headers['x-forwarded-for'] || // 判断是否有反向代理 IP 9 | req.connection.remoteAddress || // 判断 connection 的远程 IP 10 | req.socket.remoteAddress || // 判断后端的 socket 的 IP 11 | req.connection.socket.remoteAddress).replace('::ffff:', ''); 12 | }, 13 | randomNo(j) { 14 | var random_no = ""; 15 | for (var i = 0; i < j; i++) //j位随机数,用以加在时间戳后面。 16 | { 17 | random_no += Math.floor(Math.random() * 10); 18 | } 19 | random_no = new Date().getTime() + random_no; 20 | return random_no; 21 | } 22 | }; -------------------------------------------------------------------------------- /server/app/middleware/admin_req_log.ts: -------------------------------------------------------------------------------- 1 | import { Context } from 'egg'; 2 | 3 | /** 4 | * 日志中间件,记录请求 5 | */ 6 | export default function AdminReqLog(): any { 7 | return async (ctx: Context, next: () => Promise) => { 8 | const startTime = Date.now(); 9 | await next(); 10 | const reportTime = Date.now() - startTime; 11 | const { url } = ctx; 12 | // 该接口不做记录/admin/sys/log/page 13 | if (url.startsWith('/api') && !url.startsWith('/api/system/reqlog') && ctx.req.method!=='GET') { 14 | ctx.service.system.reqLog.save(url.split('?')[0], 15 | ctx.req.method === 'GET' ? ctx.request.query : ctx.request.body, ctx.status, reportTime, ctx.req.method, ctx.session && ctx.session.user ? ctx.session.user.id : null); 16 | } 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /server/app/middleware/execption.ts: -------------------------------------------------------------------------------- 1 | import { Context } from 'egg'; 2 | 3 | /** 4 | * 统一异常处理 5 | */ 6 | export default function Exception(): any { 7 | return async (ctx: Context, next: () => Promise) => { 8 | try { 9 | await next(); 10 | } catch (err) { 11 | const { errors } = err; 12 | ctx.logger.error('[Exception]', err.message, errors); 13 | ctx.set('Content-Type', 'application/json'); 14 | // 生产环境时 500 错误的详细错误内容不返回给客户端,因为可能包含敏感信息 15 | const status = err.status || 500; 16 | const message = status === 500 && ctx.app.config.env === 'prod' ? '服务器好像出了点问题...稍后再试试' : err.message; 17 | ctx.status = status; 18 | ctx.body = JSON.stringify({ 19 | status: err.errorCode || 500, 20 | message, 21 | }); 22 | } 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /server/app/middleware/requireLogin.ts: -------------------------------------------------------------------------------- 1 | import { Context } from 'egg'; 2 | module.exports = function(needLogin){ 3 | return async function requireLogin(ctx: Context) { 4 | const token = ctx.request.header.authorization; 5 | needLogin = typeof(needLogin)=='undefined'?true:needLogin 6 | // let decode: any; 7 | if (token) { 8 | try { 9 | // 解码token 10 | var pass = false; 11 | ctx.app.jwt.verify(token, ctx.app.config.secret,(err, payload) => { 12 | if(err){ 13 | needLogin && ctx.fail(401,err.message||'登录过期') 14 | pass = false 15 | return false 16 | } 17 | else{ 18 | ctx.session.user = payload.user; 19 | // console.log('获取到用户===============',payload) 20 | pass =true 21 | } 22 | }); 23 | 24 | return pass; 25 | } catch (error) { 26 | needLogin && ctx.fail(401,error.message||'解析失败') 27 | return !needLogin; 28 | } 29 | } else { 30 | needLogin && ctx.fail(401,"未登录") 31 | return !needLogin; 32 | } 33 | } 34 | }; 35 | 36 | -------------------------------------------------------------------------------- /server/app/model/Good.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { STRING, INTEGER,TEXT,DECIMAL } = app.Sequelize; 3 | 4 | const Good = app.model.define('good', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | name: { type: STRING, allowNull: false }, // 商品名称 7 | description: { type: STRING }, // 商品描述 8 | content: { type: TEXT }, // 商品描述 9 | thumbnail: INTEGER, // 缩略图,关联图片id 10 | // salePrice: { type: DECIMAL}, // 售卖价 11 | // marketPrice: { type: DECIMAL}, // 市场价 12 | categoryId: INTEGER, // 关联商品分类 13 | mechantId: INTEGER, // 关联商家id 14 | salePrice: DECIMAL, //售价,用于显示和排序,实际价格以商品规格为主 15 | marketPrice: DECIMAL, 16 | sales: {type: INTEGER, defaultValue: 0}, // 销量,方便做排序 17 | status: { type: INTEGER, defaultValue: 1 }, // 状态: 1:上架 2:下架 18 | },{freezeTableName: true}); 19 | // 表关联的字段 20 | Good.associate = function() { 21 | // 一对多 22 | app.model.Good.hasMany(app.model.GoodImage, { foreignKey: 'goodId', targetKey: 'id'}); 23 | // 一对多 24 | app.model.Good.hasMany(app.model.GoodSpec, { foreignKey: 'goodId', targetKey: 'id',as:'apecs'}); 25 | // 一对一 26 | Good.belongsTo(app.model.GoodCategory, { foreignKey: 'categoryId', targetKey: 'id', as: 'category'});// 一对一 27 | Good.belongsTo(app.model.SystemFile, { foreignKey: 'thumbnail', targetKey: 'id', as: 'thumbnailImage'}); 28 | } 29 | return Good; 30 | }; -------------------------------------------------------------------------------- /server/app/model/GoodCategory.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { STRING, INTEGER,TEXT } = app.Sequelize; 3 | 4 | const GoodCategory = app.model.define('good_category', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | name: { type: STRING, allowNull: false }, // 名称 7 | description: { type: TEXT }, // 商品描述 8 | imageId: INTEGER, // 分类图标 9 | parentId: { type: INTEGER}, // 上级Id 10 | merchantId: INTEGER, // 关联商家id 11 | status: { type: INTEGER, defaultValue: 1 }, // 状态: 1:可用 2:禁用 12 | },{freezeTableName: true}); 13 | // 表关联的字段 14 | GoodCategory.associate = function() { 15 | GoodCategory.belongsTo(app.model.GoodCategory, { foreignKey: 'parentId', targetKey: 'id', as: 'parent'}); 16 | GoodCategory.belongsTo(app.model.SystemFile, { foreignKey: 'imageId', targetKey: 'id', as: 'image'}); 17 | } 18 | return GoodCategory; 19 | }; -------------------------------------------------------------------------------- /server/app/model/GoodImage.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { INTEGER } = app.Sequelize; 3 | 4 | const GoodImage = app.model.define('good_image', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | fileId: INTEGER, // 图片id 7 | goodId: INTEGER, // 关联商品id 8 | mechantId: INTEGER, // 关联商家id 9 | },{freezeTableName: true}); 10 | // 表关联的字段 11 | GoodImage.associate = function() { 12 | // 一对一 13 | GoodImage.belongsTo(app.model.SystemFile, { foreignKey: 'fileId', targetKey: 'id', as: 'file'}); 14 | } 15 | return GoodImage; 16 | }; -------------------------------------------------------------------------------- /server/app/model/GoodOrder.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { STRING, INTEGER,ENUM,DECIMAL } = app.Sequelize; 3 | 4 | const GoodOrder = app.model.define('good_order', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | orderNo: { type: STRING, unique:true, allowNull: false }, // 商品名称 7 | // ordered: '待付款', inpayment: '付款中', paid: '已付款,待发货', receiving: '已发货,待收货', completed: '已完成', canceled: '已取消',closed:已关闭 8 | status: ENUM('ordered', 'inpayment', 'paid', 'receiving', 'completed', 'canceled','closed'), 9 | addressId: INTEGER, // 地址Id 10 | address: STRING,//收货地址:省市区街道+详细 11 | linkMan: STRING, 12 | linkPhone: STRING, 13 | goodsTotalQty: DECIMAL,//商品总数量 14 | totalAmount:DECIMAL, 15 | merchantId: INTEGER, 16 | shopName: STRING, 17 | remark:STRING,//备注 18 | userName: STRING, 19 | userId: INTEGER, 20 | 21 | },{freezeTableName: true}); 22 | // 表关联的字段 23 | GoodOrder.associate = function() { 24 | // 一对多 25 | app.model.GoodOrder.hasMany(app.model.GoodOrderLine, { foreignKey: 'orderId', targetKey: 'id',as:'goodList'}); 26 | GoodOrder.belongsTo(app.model.Merchant, { foreignKey: 'merchantId', targetKey: 'id', as: 'merchant'});// 一对一 27 | GoodOrder.belongsTo(app.model.SystemUser, { foreignKey: 'userId', targetKey: 'id', as: 'user'}); 28 | } 29 | return GoodOrder; 30 | }; -------------------------------------------------------------------------------- /server/app/model/GoodOrderLine.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { STRING, INTEGER,DECIMAL } = app.Sequelize; 3 | 4 | const GoodOrderLine = app.model.define('good_order_line', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | goodId: INTEGER, 7 | goodName: STRING, 8 | salePrice: DECIMAL, 9 | marketPrice: DECIMAL, 10 | qty: INTEGER, 11 | amount: DECIMAL, 12 | orderId: INTEGER, 13 | goodPic: STRING, 14 | goodSpecId: INTEGER, 15 | goodSpecName: STRING, 16 | goodCategoryName: STRING, 17 | goodCategoryId: INTEGER, 18 | 19 | },{freezeTableName: true}); 20 | // 表关联的字段 21 | GoodOrderLine.associate = function() { 22 | 23 | } 24 | return GoodOrderLine; 25 | }; -------------------------------------------------------------------------------- /server/app/model/GoodSpec.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { STRING, INTEGER,DECIMAL,TEXT } = app.Sequelize; 3 | 4 | const GoodSpec = app.model.define('good_spec', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | name: { type: STRING, allowNull: false }, // 规格名称 7 | description: { type: TEXT }, // 商品描述 8 | pic: { type: STRING}, // 缩略图 9 | salePrice: { type: DECIMAL}, // 售卖价 10 | marketPrice: { type: DECIMAL}, // 市场价 11 | stock: INTEGER, // 库存 12 | sales: {type: INTEGER, defaultValue: 0}, //销量 13 | goodId: INTEGER, // 关联商品id 14 | mechantId: INTEGER, // 关联商家id 15 | },{freezeTableName: true}); 16 | 17 | return GoodSpec; 18 | }; -------------------------------------------------------------------------------- /server/app/model/LogMessage.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { STRING, INTEGER } = app.Sequelize; 3 | 4 | const Message = app.model.define('log_message', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | title: STRING, // 消息名 7 | content: STRING, //消息内容 8 | sender: { type: INTEGER, defaultValue: 1 }, //发送者,1 系统,2 其他 9 | receiver: INTEGER, // 接收消息的人,0:全部成员,其他 用户id 10 | status: { type: INTEGER, defaultValue: 1 },//1 未读 2 已读 11 | },{freezeTableName: true}); 12 | 13 | return Message; 14 | }; -------------------------------------------------------------------------------- /server/app/model/Merchant.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { STRING, INTEGER } = app.Sequelize; 3 | 4 | const Merchant = app.model.define('merchant', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | appId: { type: STRING, unique: true, }, // 小程序appId 7 | appSecret: { type: STRING }, // 邮箱 8 | mchId: { type: STRING}, // 微信商户id 9 | mchKey: { type: STRING}, // 微信商户key 10 | name: STRING, // 商户名称 11 | userId: INTEGER, // 关联用户id 12 | status: { type: INTEGER, defaultValue: 1 }, // 状态: 1:启用 2:禁用 13 | address: STRING,//商户地址 14 | logoId: INTEGER 15 | // session_key: STRING, // 微信session_key 16 | },{freezeTableName: true}); 17 | // 表关联的字段 18 | Merchant.associate = function() { 19 | Merchant.belongsTo(app.model.SystemFile, { foreignKey: 'logoId', targetKey: 'id', as: 'logo'}); 20 | } 21 | return Merchant; 22 | }; -------------------------------------------------------------------------------- /server/app/model/SystemFile.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { STRING, INTEGER } = app.Sequelize; 3 | 4 | const SystemFile = app.model.define('system_file', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | format: STRING, 7 | url: STRING,//文件路径,相对路径,用于前端图片访问 8 | path: STRING,//物理路径,服务器上的路径 9 | size: INTEGER,//文件大小 10 | name: STRING,//文件名称 11 | type: STRING,//文件类型 image/video/application 12 | creator: INTEGER,//创建的用户id 13 | },{freezeTableName: true,timestamps: true}); 14 | 15 | return SystemFile; 16 | }; -------------------------------------------------------------------------------- /server/app/model/SystemMenu.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { STRING, INTEGER } = app.Sequelize; 3 | 4 | const User = app.model.define('system_menu', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | name: STRING, // 菜单名 7 | url: STRING, //菜单路径 8 | icon: STRING, //菜单图标 9 | parentId: { type: INTEGER, defaultValue: null }, // 上级菜单id 10 | sort: INTEGER, 11 | status: { type: INTEGER, defaultValue: 1 }, // 状态: 0:禁用, 1:启用 12 | },{freezeTableName: true}); 13 | 14 | return User; 15 | }; -------------------------------------------------------------------------------- /server/app/model/SystemPermission.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { STRING } = app.Sequelize; 3 | 4 | const Permission = app.model.define('system_permission', { 5 | id: { type: STRING, primaryKey: true },//权限id 6 | name: STRING, //权限名 7 | describe: STRING, //描述 8 | actions: STRING, // 操作 9 | },{freezeTableName: true}); 10 | 11 | return Permission; 12 | }; -------------------------------------------------------------------------------- /server/app/model/SystemReqLog.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { STRING, INTEGER } = app.Sequelize; 3 | 4 | const ReqLog = app.model.define('system_req_log', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | ip: STRING, 7 | userId: INTEGER, 8 | params: STRING, 9 | action: STRING, 10 | method: STRING, 11 | status: { type: INTEGER }, // 状态: 0:禁用, 1:启用 12 | consumeTime: INTEGER 13 | // session_key: STRING, // 微信session_key 14 | },{timestamps: true,freezeTableName: true}); 15 | // 表关联的字段 16 | ReqLog.associate = function() { 17 | // 一对一 18 | ReqLog.belongsTo(app.model.SystemUser, { foreignKey: 'userId', targetKey: 'id', as: 'user'}); 19 | } 20 | return ReqLog; 21 | }; -------------------------------------------------------------------------------- /server/app/model/SystemRole.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { STRING, INTEGER } = app.Sequelize; 3 | 4 | const User = app.model.define('system_role', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | name: STRING, // 角色名 7 | describe: STRING, // 角色描述 8 | status: { type: INTEGER, defaultValue: 1 }, // 状态: 0:禁用, 1:启用 9 | // session_key: STRING, // 微信session_key 10 | },{timestamps: true,freezeTableName: true}); 11 | 12 | return User; 13 | }; -------------------------------------------------------------------------------- /server/app/model/SystemRoleMenu.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { INTEGER } = app.Sequelize; 3 | 4 | const RoleMenu = app.model.define('system_role_menu', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | roleId: INTEGER, // 角色Id 7 | menuId: INTEGER, //菜单Id 8 | },{freezeTableName: true}); 9 | // 表关联的字段 10 | RoleMenu.associate = function() { 11 | /** 12 | * User.belongsTo(关联的模型, { foreignKey: '使用什么字段关联', targetKey: '与关联的模型那个字段关联', as: '别名' }); 13 | */ 14 | // 一对一 15 | RoleMenu.belongsTo(app.model.SystemMenu, { foreignKey: 'menuId', targetKey: 'id', as: 'menu'}); 16 | } 17 | return RoleMenu; 18 | }; -------------------------------------------------------------------------------- /server/app/model/SystemRolePermission.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { INTEGER,STRING } = app.Sequelize; 3 | 4 | const RolePermission = app.model.define('system_role_permission', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | roleId: INTEGER, // 角色Id 7 | permissionId: STRING, //权限Id 8 | actions: STRING 9 | },{freezeTableName: true}); 10 | // 表关联的字段 11 | RolePermission.associate = function() { 12 | /** 13 | * User.belongsTo(关联的模型, { foreignKey: '使用什么字段关联', targetKey: '与关联的模型那个字段关联', as: '别名' }); 14 | */ 15 | // 一对一 16 | RolePermission.belongsTo(app.model.SystemPermission, { foreignKey: 'permissionId', targetKey: 'id', as: 'permission'}); 17 | } 18 | return RolePermission; 19 | }; -------------------------------------------------------------------------------- /server/app/model/SystemUser.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { STRING, INTEGER } = app.Sequelize; 3 | 4 | const User = app.model.define('system_user', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | username: { type: STRING, unique: true, allowNull: false }, // 用户名 7 | email: { type: STRING }, // 邮箱 8 | password: { type: STRING, allowNull: false }, // 密码 9 | name: STRING, // 姓名 10 | sex: { type: INTEGER, defaultValue: 1 }, // 用户性别:1男性, 2女性, 0未知 11 | // age: { type: INTEGER, defaultValue: 0 }, // 年龄 12 | avatarId: INTEGER, // 头像 13 | type: INTEGER, // 类型,1:管理员,2:商家,3:普通用户 14 | phone: { type: STRING }, // 手机号码 15 | roleId: INTEGER, // 角色id 16 | status: { type: INTEGER, defaultValue: 1 }, // 用户状态: 0:禁用, 1:启用 17 | lastLoginTime: INTEGER, // 上次登录时间 18 | unionid: STRING, // 微信unionid 19 | openid: STRING, // 微信openid 20 | // session_key: STRING, // 微信session_key 21 | },{freezeTableName: true}); 22 | 23 | // 表关联的字段 24 | User.associate = function() { 25 | // 一对多 26 | // app.model.User.hasMany(app.model.Diary, { foreignKey: 'user_id', targetKey: 'id'}); 27 | /** 28 | * User.belongsTo(关联的模型, { foreignKey: '使用什么字段关联', targetKey: '与关联的模型那个字段关联', as: '别名' }); 29 | */ 30 | // 一对一 31 | User.belongsTo(app.model.SystemFile, { foreignKey: 'avatarId', targetKey: 'id', as: 'avatar'}); 32 | User.belongsTo(app.model.SystemRole, { foreignKey: 'roleId', targetKey: 'id', as: 'role'}); 33 | } 34 | return User; 35 | }; -------------------------------------------------------------------------------- /server/app/model/UserAddress.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { STRING, INTEGER,BOOLEAN,DOUBLE } = app.Sequelize; 3 | 4 | const UserAddress = app.model.define('user_address', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | province: { type: STRING, allowNull: false }, // 省 7 | city: { type: STRING }, // 市 8 | district: { type: STRING, }, // 区 9 | township: STRING, // 街道 10 | place: STRING, //详细地址 11 | linkMan: STRING, 12 | linkPhone: STRING, 13 | isDefault: BOOLEAN, 14 | longitude: DOUBLE, // 15 | latitude: DOUBLE, 16 | userId: INTEGER, 17 | // session_key: STRING, // 微信session_key 18 | },{freezeTableName: true}); 19 | 20 | // 表关联的字段 21 | UserAddress.associate = function() { 22 | // 一对一 23 | UserAddress.belongsTo(app.model.SystemUser, { foreignKey: 'userId', targetKey: 'id', as: 'user'}); 24 | } 25 | return UserAddress; 26 | }; -------------------------------------------------------------------------------- /server/app/model/UserFav.ts: -------------------------------------------------------------------------------- 1 | module.exports = app => { 2 | const { INTEGER } = app.Sequelize; 3 | 4 | const UserFav = app.model.define('user_fav', { 5 | id: { type: INTEGER, primaryKey: true, autoIncrement: true }, 6 | goodId: INTEGER, 7 | userId: INTEGER, 8 | // session_key: STRING, // 微信session_key 9 | },{freezeTableName: true}); 10 | 11 | // 表关联的字段 12 | UserFav.associate = function() { 13 | // 一对一 14 | UserFav.belongsTo(app.model.SystemUser, { foreignKey: 'userId', targetKey: 'id', as: 'user'}); 15 | UserFav.belongsTo(app.model.Good, { foreignKey: 'goodId', targetKey: 'id', as: 'good'}); 16 | } 17 | return UserFav; 18 | }; -------------------------------------------------------------------------------- /server/app/public/doc/api_project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tinyshop商城", 3 | "version": "0.1.0", 4 | "description": "tinyshop商城api文档", 5 | "title": "tinyshop商城API文档", 6 | "url": "http://mall.tucy.top", 7 | "sampleUrl": false, 8 | "defaultVersion": "0.0.0", 9 | "apidoc": "0.3.0", 10 | "generator": { 11 | "name": "apidoc", 12 | "time": "2021-01-15T13:43:52.945Z", 13 | "url": "https://apidocjs.com", 14 | "version": "0.26.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /server/app/public/doc/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/server/app/public/doc/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /server/app/public/doc/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/server/app/public/doc/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /server/app/public/doc/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/server/app/public/doc/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /server/app/public/doc/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/server/app/public/doc/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /server/app/public/doc/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/server/app/public/doc/img/favicon.ico -------------------------------------------------------------------------------- /server/app/public/doc/vendor/path-to-regexp/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /server/app/public/doc/vendor/prism.css: -------------------------------------------------------------------------------- 1 | /* PrismJS 1.21.0 2 | https://prismjs.com/download.html#themes=prism-tomorrow&languages=clike+javascript+bash+c+csharp+cpp+clojure+elixir+erlang+go+http+json+json5+jsonp+lua+perl+python+rust */ 3 | /** 4 | * prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML 5 | * Based on https://github.com/chriskempson/tomorrow-theme 6 | * @author Rose Pritchard 7 | */ 8 | 9 | code[class*="language-"], 10 | pre[class*="language-"] { 11 | color: #ccc; 12 | background: none; 13 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 14 | font-size: 1em; 15 | text-align: left; 16 | white-space: pre; 17 | word-spacing: normal; 18 | word-break: normal; 19 | word-wrap: normal; 20 | line-height: 1.5; 21 | 22 | -moz-tab-size: 4; 23 | -o-tab-size: 4; 24 | tab-size: 4; 25 | 26 | -webkit-hyphens: none; 27 | -moz-hyphens: none; 28 | -ms-hyphens: none; 29 | hyphens: none; 30 | 31 | } 32 | 33 | /* Code blocks */ 34 | pre[class*="language-"] { 35 | padding: 1em; 36 | margin: .5em 0; 37 | overflow: auto; 38 | } 39 | 40 | :not(pre) > code[class*="language-"], 41 | pre[class*="language-"] { 42 | background: #2d2d2d; 43 | } 44 | 45 | /* Inline code */ 46 | :not(pre) > code[class*="language-"] { 47 | padding: .1em; 48 | border-radius: .3em; 49 | white-space: normal; 50 | } 51 | 52 | .token.comment, 53 | .token.block-comment, 54 | .token.prolog, 55 | .token.doctype, 56 | .token.cdata { 57 | color: #999; 58 | } 59 | 60 | .token.punctuation { 61 | color: #ccc; 62 | } 63 | 64 | .token.tag, 65 | .token.attr-name, 66 | .token.namespace, 67 | .token.deleted { 68 | color: #e2777a; 69 | } 70 | 71 | .token.function-name { 72 | color: #6196cc; 73 | } 74 | 75 | .token.boolean, 76 | .token.number, 77 | .token.function { 78 | color: #f08d49; 79 | } 80 | 81 | .token.property, 82 | .token.class-name, 83 | .token.constant, 84 | .token.symbol { 85 | color: #f8c555; 86 | } 87 | 88 | .token.selector, 89 | .token.important, 90 | .token.atrule, 91 | .token.keyword, 92 | .token.builtin { 93 | color: #cc99cd; 94 | } 95 | 96 | .token.string, 97 | .token.char, 98 | .token.attr-value, 99 | .token.regex, 100 | .token.variable { 101 | color: #7ec699; 102 | } 103 | 104 | .token.operator, 105 | .token.entity, 106 | .token.url { 107 | color: #67cdcc; 108 | } 109 | 110 | .token.important, 111 | .token.bold { 112 | font-weight: bold; 113 | } 114 | .token.italic { 115 | font-style: italic; 116 | } 117 | 118 | .token.entity { 119 | cursor: help; 120 | } 121 | 122 | .token.inserted { 123 | color: green; 124 | } 125 | 126 | -------------------------------------------------------------------------------- /server/app/router.ts: -------------------------------------------------------------------------------- 1 | import { Application } from 'egg'; 2 | import { Blueprint } from 'egg-blueprint' 3 | 4 | export default (app: Application) => { 5 | const { controller, router } = app; 6 | router.get('/test1', controller.home.test); 7 | Blueprint(app); 8 | }; 9 | -------------------------------------------------------------------------------- /server/app/service/good/category.ts: -------------------------------------------------------------------------------- 1 | import { Service } from 'egg'; 2 | 3 | /** 4 | * role Service 5 | */ 6 | export default class CategoryService extends Service { 7 | 8 | /** 9 | * 列表 10 | * @param params - 列表查询参数 11 | */ 12 | public async list(options) { 13 | let {page = 1, pageSize = this.config.pageSize} = options 14 | let list = await this.app.model.GoodCategory.findAndCountAll({ 15 | limit: +pageSize, 16 | offset: pageSize * (page-1), 17 | order:[ 18 | ['created_at','DESC'] 19 | ], 20 | include:[ 21 | {model: this.app.model.GoodCategory,as: 'parent'}, 22 | {model: this.app.model.SystemFile,as: 'image'}, 23 | ] 24 | }) 25 | return list; 26 | } 27 | /** 28 | * 列表 29 | * @param params - 列表查询参数 30 | */ 31 | public async select(options) { 32 | var where = {}; 33 | for(const i in options){ 34 | options[i] && (where[i] = options[i]) 35 | } 36 | let list = await this.app.model.GoodCategory.findAll({ 37 | where: where, 38 | include:[ 39 | {model: this.app.model.SystemFile,as: 'image'}, 40 | ] 41 | }) 42 | return list; 43 | } 44 | 45 | /** 46 | * 保存 47 | * @param options - 参数 48 | */ 49 | public async save(options: any) { 50 | const { ctx } = this 51 | let results = { code: 400, message: "失败", } 52 | if(!options.parentId){ 53 | delete options.parentId; 54 | } 55 | await ctx.model.GoodCategory.upsert(options).then(() => { 56 | results = { code: 0, message: "添加成功", } 57 | }).catch(err => { 58 | results = { code: 400, message: err, } 59 | }) 60 | 61 | return results 62 | } 63 | 64 | public async detail(id){ 65 | // const { ctx } = this 66 | let data = await this.app.model.GoodCategory.findOne({where: {id}}) 67 | return data 68 | } 69 | //删除 70 | public async remove(id){ 71 | let results 72 | await this.ctx.model.GoodCategory.destroy({ where: { id}}).then(() => { 73 | results = { code: 0, message: "删除成功", } 74 | }).catch(error => { 75 | results = { code: 400, message: error, } 76 | }) 77 | return results 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /server/app/service/log/message.ts: -------------------------------------------------------------------------------- 1 | import { Service } from 'egg'; 2 | 3 | 4 | /** 5 | * role Service 6 | */ 7 | export default class MessageService extends Service { 8 | 9 | /** 10 | * 列表 11 | * @param params - 列表查询参数 12 | */ 13 | public async list(options) { 14 | let {page = 1, pageSize = this.config.pageSize} = options 15 | let list = await this.app.model.LogMessage.findAndCountAll({ 16 | limit: +pageSize, 17 | offset: pageSize * (page-1) 18 | }) 19 | return list; 20 | } 21 | 22 | /** 23 | * 保存 24 | * @param options - 参数 25 | */ 26 | public async save(options: any) { 27 | const { ctx } = this 28 | let results = { code: 400, message: "失败", } 29 | await ctx.model.LogMessage.upsert(options).then(() => { 30 | results = { code: 0, message: "添加成功", } 31 | }).catch(err => { 32 | results = { code: 400, message: err, } 33 | }) 34 | 35 | return results 36 | } 37 | 38 | public async detail(id){ 39 | // const { ctx } = this 40 | let data = await this.app.model.LogMessage.findOne({where: {id}}) 41 | return data 42 | } 43 | //删除 44 | public async remove(id){ 45 | let results 46 | await this.ctx.model.LogMessage.destroy({ where: { id}}).then(() => { 47 | results = { code: 0, message: "删除成功", } 48 | }).catch(error => { 49 | results = { code: 400, message: error, } 50 | }) 51 | return results 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /server/app/service/member/address.ts: -------------------------------------------------------------------------------- 1 | import { Service } from 'egg'; 2 | 3 | /** 4 | * role Service 5 | */ 6 | export default class AddressService extends Service { 7 | 8 | /** 9 | * 列表 10 | * @param params - 列表查询参数 11 | */ 12 | public async list(options) { 13 | const { ctx } = this 14 | let {page = 1, pageSize = this.config.pageSize} = options 15 | const where = {userId: ctx.session.user.id}; 16 | if(typeof options.isDefault !== 'undefined'){ 17 | where['isDefault']=options.isDefault?true:false 18 | } 19 | let list = await this.app.model.UserAddress.findAndCountAll({ 20 | limit: +pageSize, 21 | offset: pageSize * (page-1), 22 | where: where 23 | }) 24 | return list; 25 | } 26 | /** 27 | * 列表 28 | * @param params - 列表查询参数 29 | */ 30 | public async select() { 31 | let list = await this.app.model.UserAddress.findAll() 32 | return list; 33 | } 34 | 35 | /** 36 | * 保存 37 | * @param options - 参数 38 | */ 39 | public async save(options: any) { 40 | const { ctx } = this 41 | let results = { code: 400, message: "失败", } 42 | options.userId = ctx.session.user.id; 43 | 44 | if(options.isDefault){//先将其它地址默认地址去掉 45 | await ctx.model.UserAddress.update({isDefault: false},{ 46 | where:{userId: ctx.session.user.id} 47 | }) 48 | } 49 | await ctx.model.UserAddress.upsert(options).then(() => { 50 | results = { code: 0, message: "添加成功", } 51 | }).catch(err => { 52 | results = { code: 400, message: err, } 53 | }) 54 | 55 | return results 56 | } 57 | public async detail(id){ 58 | // const { ctx } = this 59 | let data = await this.app.model.UserAddress.findOne({where: {id}}) 60 | return data 61 | } 62 | //删除 63 | public async remove(id){ 64 | let results 65 | await this.ctx.model.UserAddress.destroy({ where: { id}}).then(() => { 66 | results = { code: 0, message: "删除成功", } 67 | }).catch(error => { 68 | results = { code: 400, message: error, } 69 | }) 70 | return results 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /server/app/service/member/fav.ts: -------------------------------------------------------------------------------- 1 | import { Service } from 'egg'; 2 | 3 | /** 4 | * role Service 5 | */ 6 | export default class FavService extends Service { 7 | 8 | /** 9 | * 列表 10 | * @param params - 列表查询参数 11 | */ 12 | public async list(options) { 13 | const { ctx } = this 14 | let {page = 1, pageSize = this.config.pageSize} = options 15 | const where = {userId: ctx.session.user.id}; 16 | let list = await this.app.model.UserFav.findAndCountAll({ 17 | limit: +pageSize, 18 | offset: pageSize * (page-1), 19 | where: where, 20 | include:[ 21 | {model: this.app.model.Good, as:'good',include:[{model:this.app.model.SystemFile,as:'thumbnailImage'}]} 22 | ] 23 | }) 24 | return list; 25 | } 26 | /** 27 | * 列表 28 | * @param params - 列表查询参数 29 | */ 30 | public async select() { 31 | let list = await this.app.model.UserFav.findAll() 32 | return list; 33 | } 34 | 35 | /** 36 | * 保存 37 | * @param options - 参数 38 | */ 39 | public async save(options: any) { 40 | const { ctx } = this 41 | let results = { code: 400, message: "失败", } 42 | options.userId = ctx.session.user.id; 43 | 44 | await ctx.model.UserFav.upsert(options).then(() => { 45 | results = { code: 0, message: "添加成功", } 46 | }).catch(err => { 47 | results = { code: 400, message: err, } 48 | }) 49 | 50 | return results 51 | } 52 | public async detail(id){ 53 | // const { ctx } = this 54 | let data = await this.app.model.UserFav.findOne({where: {id}}) 55 | return data 56 | } 57 | //删除 58 | public async remove(id){ 59 | let results 60 | await this.ctx.model.UserFav.destroy({ where: { id}}).then(() => { 61 | results = { code: 0, message: "删除成功", } 62 | }).catch(error => { 63 | results = { code: 400, message: error, } 64 | }) 65 | return results 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /server/app/service/merchant/index.ts: -------------------------------------------------------------------------------- 1 | import { Service } from 'egg'; 2 | 3 | /** 4 | * role Service 5 | */ 6 | export default class MerchantService extends Service { 7 | 8 | /** 9 | * 列表 10 | * @param params - 列表查询参数 11 | */ 12 | public async list(options) { 13 | let {page = 1, pageSize = this.config.pageSize} = options 14 | let list = await this.app.model.Merchant.findAndCountAll({ 15 | limit: +pageSize, 16 | offset: pageSize * (page-1), 17 | include:[ 18 | {model: this.app.model.SystemFile,as:'logo'} 19 | ] 20 | }) 21 | return list; 22 | } 23 | /** 24 | * 列表 25 | * @param params - 列表查询参数 26 | */ 27 | public async select() { 28 | let list = await this.app.model.Merchant.findAll() 29 | return list; 30 | } 31 | 32 | /** 33 | * 保存 34 | * @param options - 参数 35 | */ 36 | public async save(options: any) { 37 | const { ctx } = this 38 | let results = { code: 400, message: "失败", } 39 | await ctx.model.Merchant.upsert(options).then(() => { 40 | results = { code: 0, message: "添加成功", } 41 | }).catch(err => { 42 | results = { code: 400, message: err, } 43 | }) 44 | 45 | return results 46 | } 47 | /** 48 | * 保存 49 | * @param options - 参数 50 | */ 51 | public async update(options: any) { 52 | const { ctx } = this 53 | let results = { code: 400, message: "失败", } 54 | await ctx.model.Merchant.update(options,{ 55 | where:{id: options.id} 56 | }).then(() => { 57 | results = { code: 0, message: "添加成功", } 58 | }).catch(err => { 59 | results = { code: 400, message: err, } 60 | }) 61 | 62 | return results 63 | } 64 | public async detail(id){ 65 | // const { ctx } = this 66 | let data = await this.app.model.Merchant.findOne({where: {id}}) 67 | return data 68 | } 69 | //删除 70 | public async remove(id){ 71 | let results 72 | await this.ctx.model.Merchant.destroy({ where: { id}}).then(() => { 73 | results = { code: 0, message: "删除成功", } 74 | }).catch(error => { 75 | results = { code: 400, message: error, } 76 | }) 77 | return results 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /server/app/service/system/file.ts: -------------------------------------------------------------------------------- 1 | import { Service } from 'egg'; 2 | const fs = require('mz/fs'); 3 | /** 4 | * role Service 5 | */ 6 | export default class FileService extends Service { 7 | 8 | /** 9 | * 列表 10 | * @param params - 列表查询参数 11 | */ 12 | public async list(options) { 13 | let {page = 1, pageSize = this.config.pageSize} = options 14 | let list = await this.app.model.SystemFile.findAndCountAll({ 15 | limit: +pageSize, 16 | offset: pageSize * (page-1) 17 | }) 18 | return list; 19 | } 20 | /** 21 | * 列表 22 | * @param params - 列表查询参数 23 | */ 24 | public async select() { 25 | let list = await this.app.model.SystemFile.findAll() 26 | return list; 27 | } 28 | 29 | /** 30 | * 保存 31 | * @param options - 参数 32 | */ 33 | public async save(options: any) { 34 | const { ctx } = this 35 | let results = { code: 400, message: "失败", } 36 | await ctx.model.SystemFile.upsert(options).then(() => { 37 | results = { code: 0, message: "添加成功", } 38 | }).catch(err => { 39 | results = { code: 400, message: err, } 40 | }) 41 | 42 | return results 43 | } 44 | 45 | public async detail(id){ 46 | // const { ctx } = this 47 | let data = await this.app.model.SystemFile.findOne({where: {id}}) 48 | return data 49 | } 50 | //删除 51 | public async remove(id){ 52 | let results 53 | let data = await this.app.model.SystemFile.findOne({where: {id}}) 54 | 55 | await this.ctx.model.SystemFile.destroy({ where: { id}}).then(() => { 56 | results = { code: 0, message: "删除成功", } 57 | }).catch(error => { 58 | results = { code: 400, message: error, } 59 | }) 60 | if(results.code===0 && data){ 61 | try{ 62 | await fs.unlinkSync(data.path) 63 | }catch(e){ 64 | console.log('err==================',e) 65 | } 66 | } 67 | return results 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /server/app/service/system/permission.ts: -------------------------------------------------------------------------------- 1 | import { Service } from 'egg'; 2 | 3 | 4 | /** 5 | * role Service 6 | */ 7 | export default class PermissionService extends Service { 8 | 9 | /** 10 | * 列表 11 | * @param params - 列表查询参数 12 | */ 13 | public async list(options) { 14 | let {page = 1, pageSize = this.config.pageSize} = options 15 | let list = await this.app.model.SystemPermission.findAndCountAll({ 16 | limit: +pageSize, 17 | offset: pageSize * (page-1) 18 | }) 19 | return list; 20 | } 21 | /** 22 | * 不分页列表 23 | * @param params - 列表查询参数 24 | */ 25 | public async select() { 26 | let list = await this.app.model.SystemPermission.findAll() 27 | return list; 28 | } 29 | 30 | /** 31 | * 保存 32 | * @param options - 参数 33 | */ 34 | public async save(options: any) { 35 | const { ctx } = this 36 | let results = { code: 400, message: "失败", } 37 | await ctx.model.SystemPermission.upsert(options).then(() => { 38 | results = { code: 0, message: "添加成功", } 39 | }).catch(err => { 40 | results = { code: 400, message: err, } 41 | }) 42 | 43 | return results 44 | } 45 | 46 | public async detail(id){ 47 | // const { ctx } = this 48 | let data = await this.app.model.SystemPermission.findOne({where: {id}}) 49 | return data 50 | } 51 | //删除 52 | public async remove(id){ 53 | let results 54 | await this.ctx.model.SystemPermission.destroy({ where: { id}}).then(() => { 55 | results = { code: 0, message: "删除成功", } 56 | }).catch(error => { 57 | results = { code: 400, message: error, } 58 | }) 59 | return results 60 | } 61 | // 获取角色菜单 62 | async getMenuTree (roleId:number) { 63 | const { ctx } = this 64 | let list = await ctx.model.SystemPermissionMenu.findAll({ 65 | where: {roleId: roleId}, 66 | include:[ 67 | {model: this.app.model.SystemMenu,as: 'menu'} 68 | ] 69 | }) 70 | list = list.map(item=>item.menu); 71 | let result:Array = []; 72 | let find = (menus,parentId)=>{ 73 | list.filter(item=>item.parentId==parentId).map(item=>{ 74 | item.dataValues.children = []; 75 | find(item.dataValues.children,item.id); 76 | menus.push(item); 77 | }) 78 | } 79 | find(result,null); 80 | return result 81 | } 82 | 83 | 84 | } 85 | -------------------------------------------------------------------------------- /server/app/service/system/req_log.ts: -------------------------------------------------------------------------------- 1 | import { Service } from 'egg'; 2 | 3 | /** 4 | * 请求追踪服务 5 | */ 6 | export default class SysReqLogService extends Service { 7 | 8 | /** 9 | * 记录日志 10 | */ 11 | async save(url: string, params: string, status: number, consumeTime: number, method: string | undefined, userId: number | null) { 12 | const ip = this.ctx.helper.getReqIP(); 13 | await this.app.model.SystemReqLog.create({ 14 | action: url, 15 | params: JSON.stringify(params), 16 | userId: userId === null ? undefined : userId, 17 | ip, 18 | method: method ? method.toUpperCase() : undefined, 19 | status, 20 | consumeTime, 21 | }); 22 | } 23 | 24 | /** 25 | * 计算日志总数 26 | */ 27 | async count() { 28 | return await this.app.model.SystemReqLog.count(); 29 | } 30 | 31 | /** 32 | * 分页加载日志信息 33 | */ 34 | async list(options) { 35 | let {page = 1, pageSize = this.config.pageSize} = options 36 | const result = await this.app.model.SystemReqLog.findAndCountAll({ 37 | order: [ 38 | ["id", 'DESC'], 39 | ], 40 | limit: +pageSize, 41 | offset: pageSize * (page-1), 42 | include:[ 43 | {model: this.app.model.SystemUser,as:'user'} 44 | ] 45 | }); 46 | return result; 47 | } 48 | 49 | 50 | //删除 51 | public async remove(id){ 52 | let results 53 | await this.ctx.model.SystemReqLog.destroy({ where: { id}}).then(() => { 54 | results = { code: 0, message: "删除成功", } 55 | }).catch(error => { 56 | results = { code: 400, message: error, } 57 | }) 58 | return results 59 | } 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /server/appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - nodejs_version: '8' 4 | 5 | install: 6 | - ps: Install-Product node $env:nodejs_version 7 | - npm i npminstall && node_modules\.bin\npminstall 8 | 9 | test_script: 10 | - node --version 11 | - npm --version 12 | - npm run test 13 | 14 | build: off 15 | -------------------------------------------------------------------------------- /server/config/config.default.ts: -------------------------------------------------------------------------------- 1 | import { EggAppConfig, EggAppInfo, PowerPartial } from 'egg'; 2 | 3 | export default (appInfo: EggAppInfo) => { 4 | const config = {} as PowerPartial; 5 | 6 | // override config from framework / plugin 7 | // use for cookie sign key, should change to your own and keep security 8 | config.keys = appInfo.name + '_1598064376175_9435'; 9 | 10 | // add your egg config in here 11 | 12 | // config.middleware = [ 'adminReqLog', 'execption', 'adminAuthority' ]; 13 | config.middleware = ['adminReqLog','execption']; 14 | 15 | // add your special config in here 16 | const bizConfig = { 17 | sourceUrl: `https://github.com/eggjs/examples/tree/master/${appInfo.name}`, 18 | }; 19 | 20 | config.jwt = { 21 | secret: "12345678", 22 | enable: false, 23 | } 24 | config.security= { 25 | csrf : { 26 | enable: false, 27 | }, 28 | domainWhiteList: [ '*' ] 29 | } 30 | config.cors = { 31 | origin: '*', 32 | allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS' 33 | }; 34 | config.sequelize = { 35 | timezone: '+08:00', 36 | dialectOptions: { 37 | dateStrings: true, 38 | typeCast(field, next) { 39 | // for reading from database 40 | if (field.type === "DATETIME") { 41 | return field.string(); 42 | } 43 | return next(); 44 | } 45 | } 46 | } 47 | config.multipart = { 48 | mode: 'file', 49 | fileSize: '100mb', 50 | }; 51 | config.pageSize = 20 52 | 53 | // the return config will combines to EggAppConfig 54 | return { 55 | ...config, 56 | ...bizConfig, 57 | }; 58 | }; 59 | -------------------------------------------------------------------------------- /server/config/config.local.ts: -------------------------------------------------------------------------------- 1 | import { EggAppConfig, PowerPartial } from 'egg'; 2 | 3 | export default () => { 4 | const config: PowerPartial = {}; 5 | config.sequelize = { 6 | dialect: "mysql",// 数据库类型 7 | host: "localhost",// host 8 | port: 3306,// 端口号 9 | username: "root",// 用户名 10 | password: "123456",// 密码 11 | database: "eggjs-uniapp-shop"// 数据库名 12 | }; 13 | 14 | return config; 15 | }; 16 | -------------------------------------------------------------------------------- /server/config/config.prod.ts: -------------------------------------------------------------------------------- 1 | import { EggAppConfig, PowerPartial } from 'egg'; 2 | 3 | export default () => { 4 | const config: PowerPartial = {}; 5 | config.sequelize = { 6 | dialect: "mysql",// 数据库类型 7 | host: "localhost",// host 8 | port: 3306,// 端口号 9 | username: "root",// 用户名 10 | password: "root",// 密码 11 | database: "eggjs-uniapp-shop"// 数据库名 12 | }; 13 | return config; 14 | }; 15 | -------------------------------------------------------------------------------- /server/config/plugin.ts: -------------------------------------------------------------------------------- 1 | import { EggPlugin } from 'egg'; 2 | 3 | const plugin: EggPlugin = { 4 | // static: true, 5 | // nunjucks: { 6 | // enable: true, 7 | // package: 'egg-view-nunjucks', 8 | // }, 9 | jwt: { 10 | enable: true, 11 | package: "egg-jwt", 12 | }, 13 | sequelize: { 14 | enable: true, 15 | package: 'egg-sequelize' 16 | }, 17 | cors: { 18 | enable: true, 19 | package: 'egg-cors' 20 | } 21 | }; 22 | 23 | export default plugin; 24 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eggjs-uniapp-shop", 3 | "version": "1.0.0", 4 | "description": "", 5 | "private": true, 6 | "egg": { 7 | "typescript": true, 8 | "declarations": true 9 | }, 10 | "scripts": { 11 | "start": "egg-scripts start --daemon --title=egg-server-eggjs-uniapp-shop", 12 | "stop": "egg-scripts stop --title=egg-server-eggjs-uniapp-shop", 13 | "dev": "egg-bin dev", 14 | "debug": "egg-bin debug", 15 | "test-local": "egg-bin test", 16 | "test": "npm run lint -- --fix && npm run test-local", 17 | "cov": "egg-bin cov", 18 | "tsc": "ets && tsc -p tsconfig.json", 19 | "ci": "npm run lint && npm run cov && npm run tsc", 20 | "autod": "autod", 21 | "lint": "eslint . --ext .ts", 22 | "clean": "ets clean" 23 | }, 24 | "dependencies": { 25 | "dayjs": "^1.9.7", 26 | "egg": "^2.6.1", 27 | "egg-blueprint": "^1.2.1", 28 | "egg-cors": "^2.2.3", 29 | "egg-jwt": "^3.1.7", 30 | "egg-redis": "^2.4.0", 31 | "egg-scripts": "^2.6.0", 32 | "egg-sequelize": "^5.2.2", 33 | "mysql2": "^2.1.0" 34 | }, 35 | "devDependencies": { 36 | "@types/mocha": "^2.2.40", 37 | "@types/node": "^7.0.12", 38 | "@types/supertest": "^2.0.0", 39 | "autod": "^3.0.1", 40 | "autod-egg": "^1.1.0", 41 | "egg-ci": "^1.8.0", 42 | "egg-bin": "^4.11.0", 43 | "egg-mock": "^3.16.0", 44 | "tslib": "^1.9.0", 45 | "eslint": "^6.7.2", 46 | "eslint-config-egg": "^8.0.0", 47 | "typescript": "^3.0.0" 48 | }, 49 | "engines": { 50 | "node": ">=8.9.0" 51 | }, 52 | "ci": { 53 | "version": "8" 54 | }, 55 | "repository": { 56 | "type": "git", 57 | "url": "" 58 | }, 59 | "eslintIgnore": [ 60 | "coverage" 61 | ], 62 | "author": "tcy", 63 | "license": "MIT" 64 | } 65 | -------------------------------------------------------------------------------- /server/test/app/controller/home.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { app } from 'egg-mock/bootstrap'; 3 | 4 | describe('test/app/controller/home.test.ts', () => { 5 | it('should GET /', async () => { 6 | const result = await app.httpRequest().get('/').expect(200); 7 | assert(result.text === 'hi, egg'); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /server/test/app/service/Test.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { Context } from 'egg'; 3 | import { app } from 'egg-mock/bootstrap'; 4 | 5 | describe('test/app/service/Test.test.js', () => { 6 | let ctx: Context; 7 | 8 | before(async () => { 9 | ctx = app.mockContext(); 10 | }); 11 | 12 | it('sayHi', async () => { 13 | const result = await ctx.service.test.sayHi('egg'); 14 | assert(result === 'hi, egg'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": true, 3 | "compilerOptions": { 4 | "target": "es2017", 5 | "module": "commonjs", 6 | "strict": true, 7 | "noImplicitAny": false, 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "charset": "utf8", 11 | "allowJs": false, 12 | "pretty": true, 13 | "noEmitOnError": false, 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "allowUnreachableCode": false, 17 | "allowUnusedLabels": false, 18 | "strictPropertyInitialization": false, 19 | "noFallthroughCasesInSwitch": true, 20 | "skipLibCheck": true, 21 | "skipDefaultLibCheck": true, 22 | "inlineSourceMap": true, 23 | "importHelpers": true 24 | }, 25 | "exclude": [ 26 | "app/public", 27 | "app/views", 28 | "node_modules*" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /server/typings/app/controller/index.d.ts: -------------------------------------------------------------------------------- 1 | // This file is created by egg-ts-helper@1.25.8 2 | // Do not modify this file!!!!!!!!! 3 | 4 | import 'egg'; 5 | import ExportHome from '../../../app/controller/home'; 6 | import ExportGoodCategory from '../../../app/controller/good/category'; 7 | import ExportGoodHome from '../../../app/controller/good/home'; 8 | import ExportGoodOrder from '../../../app/controller/good/order'; 9 | import ExportLogMessage from '../../../app/controller/log/message'; 10 | import ExportMemberAddress from '../../../app/controller/member/address'; 11 | import ExportMemberFav from '../../../app/controller/member/fav'; 12 | import ExportMerchantIndex from '../../../app/controller/merchant/index'; 13 | import ExportSystemFile from '../../../app/controller/system/file'; 14 | import ExportSystemMenu from '../../../app/controller/system/menu'; 15 | import ExportSystemPermission from '../../../app/controller/system/permission'; 16 | import ExportSystemReqLog from '../../../app/controller/system/req_log'; 17 | import ExportSystemRole from '../../../app/controller/system/role'; 18 | import ExportSystemUser from '../../../app/controller/system/user'; 19 | 20 | declare module 'egg' { 21 | interface IController { 22 | home: ExportHome; 23 | good: { 24 | category: ExportGoodCategory; 25 | home: ExportGoodHome; 26 | order: ExportGoodOrder; 27 | } 28 | log: { 29 | message: ExportLogMessage; 30 | } 31 | member: { 32 | address: ExportMemberAddress; 33 | fav: ExportMemberFav; 34 | } 35 | merchant: { 36 | index: ExportMerchantIndex; 37 | } 38 | system: { 39 | file: ExportSystemFile; 40 | menu: ExportSystemMenu; 41 | permission: ExportSystemPermission; 42 | reqLog: ExportSystemReqLog; 43 | role: ExportSystemRole; 44 | user: ExportSystemUser; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /server/typings/app/extend/context.d.ts: -------------------------------------------------------------------------------- 1 | // This file is created by egg-ts-helper@1.25.8 2 | // Do not modify this file!!!!!!!!! 3 | 4 | import 'egg'; 5 | import ExtendContext from '../../../app/extend/context'; 6 | type ExtendContextType = typeof ExtendContext; 7 | declare module 'egg' { 8 | interface Context extends ExtendContextType { } 9 | } -------------------------------------------------------------------------------- /server/typings/app/extend/helper.d.ts: -------------------------------------------------------------------------------- 1 | // This file is created by egg-ts-helper@1.25.8 2 | // Do not modify this file!!!!!!!!! 3 | 4 | import 'egg'; 5 | import ExtendIHelper from '../../../app/extend/helper'; 6 | type ExtendIHelperType = typeof ExtendIHelper; 7 | declare module 'egg' { 8 | interface IHelper extends ExtendIHelperType { } 9 | } -------------------------------------------------------------------------------- /server/typings/app/index.d.ts: -------------------------------------------------------------------------------- 1 | // This file is created by egg-ts-helper@1.25.8 2 | // Do not modify this file!!!!!!!!! 3 | 4 | import 'egg'; 5 | export * from 'egg'; 6 | export as namespace Egg; 7 | -------------------------------------------------------------------------------- /server/typings/app/middleware/index.d.ts: -------------------------------------------------------------------------------- 1 | // This file is created by egg-ts-helper@1.25.8 2 | // Do not modify this file!!!!!!!!! 3 | 4 | import 'egg'; 5 | import ExportAdminReqLog from '../../../app/middleware/admin_req_log'; 6 | import ExportExecption from '../../../app/middleware/execption'; 7 | import ExportRequireLogin from '../../../app/middleware/requireLogin'; 8 | 9 | declare module 'egg' { 10 | interface IMiddleware { 11 | adminReqLog: typeof ExportAdminReqLog; 12 | execption: typeof ExportExecption; 13 | requireLogin: typeof ExportRequireLogin; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /server/typings/app/model/index.d.ts: -------------------------------------------------------------------------------- 1 | // This file is created by egg-ts-helper@1.25.8 2 | // Do not modify this file!!!!!!!!! 3 | 4 | import 'egg'; 5 | import ExportGood from '../../../app/model/Good'; 6 | import ExportGoodCategory from '../../../app/model/GoodCategory'; 7 | import ExportGoodImage from '../../../app/model/GoodImage'; 8 | import ExportGoodOrder from '../../../app/model/GoodOrder'; 9 | import ExportGoodOrderLine from '../../../app/model/GoodOrderLine'; 10 | import ExportGoodSpec from '../../../app/model/GoodSpec'; 11 | import ExportLogMessage from '../../../app/model/LogMessage'; 12 | import ExportMerchant from '../../../app/model/Merchant'; 13 | import ExportSystemFile from '../../../app/model/SystemFile'; 14 | import ExportSystemMenu from '../../../app/model/SystemMenu'; 15 | import ExportSystemPermission from '../../../app/model/SystemPermission'; 16 | import ExportSystemReqLog from '../../../app/model/SystemReqLog'; 17 | import ExportSystemRole from '../../../app/model/SystemRole'; 18 | import ExportSystemRoleMenu from '../../../app/model/SystemRoleMenu'; 19 | import ExportSystemRolePermission from '../../../app/model/SystemRolePermission'; 20 | import ExportSystemUser from '../../../app/model/SystemUser'; 21 | import ExportUserAddress from '../../../app/model/UserAddress'; 22 | import ExportUserFav from '../../../app/model/UserFav'; 23 | 24 | declare module 'egg' { 25 | interface IModel { 26 | Good: ReturnType; 27 | GoodCategory: ReturnType; 28 | GoodImage: ReturnType; 29 | GoodOrder: ReturnType; 30 | GoodOrderLine: ReturnType; 31 | GoodSpec: ReturnType; 32 | LogMessage: ReturnType; 33 | Merchant: ReturnType; 34 | SystemFile: ReturnType; 35 | SystemMenu: ReturnType; 36 | SystemPermission: ReturnType; 37 | SystemReqLog: ReturnType; 38 | SystemRole: ReturnType; 39 | SystemRoleMenu: ReturnType; 40 | SystemRolePermission: ReturnType; 41 | SystemUser: ReturnType; 42 | UserAddress: ReturnType; 43 | UserFav: ReturnType; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /server/typings/app/service/index.d.ts: -------------------------------------------------------------------------------- 1 | // This file is created by egg-ts-helper@1.25.8 2 | // Do not modify this file!!!!!!!!! 3 | 4 | import 'egg'; 5 | type AnyClass = new (...args: any[]) => any; 6 | type AnyFunc = (...args: any[]) => T; 7 | type CanExportFunc = AnyFunc> | AnyFunc>; 8 | type AutoInstanceType : T> = U extends AnyClass ? InstanceType : U; 9 | import ExportGoodCategory from '../../../app/service/good/category'; 10 | import ExportGoodHome from '../../../app/service/good/home'; 11 | import ExportGoodOrder from '../../../app/service/good/order'; 12 | import ExportLogMessage from '../../../app/service/log/message'; 13 | import ExportMemberAddress from '../../../app/service/member/address'; 14 | import ExportMemberFav from '../../../app/service/member/fav'; 15 | import ExportMerchantIndex from '../../../app/service/merchant/index'; 16 | import ExportSystemFile from '../../../app/service/system/file'; 17 | import ExportSystemMenu from '../../../app/service/system/menu'; 18 | import ExportSystemPermission from '../../../app/service/system/permission'; 19 | import ExportSystemReqLog from '../../../app/service/system/req_log'; 20 | import ExportSystemRole from '../../../app/service/system/role'; 21 | import ExportSystemUser from '../../../app/service/system/user'; 22 | 23 | declare module 'egg' { 24 | interface IService { 25 | good: { 26 | category: AutoInstanceType; 27 | home: AutoInstanceType; 28 | order: AutoInstanceType; 29 | } 30 | log: { 31 | message: AutoInstanceType; 32 | } 33 | member: { 34 | address: AutoInstanceType; 35 | fav: AutoInstanceType; 36 | } 37 | merchant: { 38 | index: AutoInstanceType; 39 | } 40 | system: { 41 | file: AutoInstanceType; 42 | menu: AutoInstanceType; 43 | permission: AutoInstanceType; 44 | reqLog: AutoInstanceType; 45 | role: AutoInstanceType; 46 | user: AutoInstanceType; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /server/typings/config/index.d.ts: -------------------------------------------------------------------------------- 1 | // This file is created by egg-ts-helper@1.25.8 2 | // Do not modify this file!!!!!!!!! 3 | 4 | import 'egg'; 5 | import { EggAppConfig } from 'egg'; 6 | import ExportConfigDefault from '../../config/config.default'; 7 | type ConfigDefault = ReturnType; 8 | type NewEggAppConfig = ConfigDefault; 9 | declare module 'egg' { 10 | interface EggAppConfig extends NewEggAppConfig { } 11 | } -------------------------------------------------------------------------------- /server/typings/config/plugin.d.ts: -------------------------------------------------------------------------------- 1 | // This file is created by egg-ts-helper@1.25.8 2 | // Do not modify this file!!!!!!!!! 3 | 4 | import 'egg'; 5 | import 'egg-onerror'; 6 | import 'egg-session'; 7 | import 'egg-i18n'; 8 | import 'egg-watcher'; 9 | import 'egg-multipart'; 10 | import 'egg-security'; 11 | import 'egg-development'; 12 | import 'egg-logrotator'; 13 | import 'egg-schedule'; 14 | import 'egg-static'; 15 | import 'egg-jsonp'; 16 | import 'egg-view'; 17 | import 'egg-jwt'; 18 | import 'egg-sequelize'; 19 | import 'egg-cors'; 20 | import { EggPluginItem } from 'egg'; 21 | declare module 'egg' { 22 | interface EggPlugin { 23 | onerror?: EggPluginItem; 24 | session?: EggPluginItem; 25 | i18n?: EggPluginItem; 26 | watcher?: EggPluginItem; 27 | multipart?: EggPluginItem; 28 | security?: EggPluginItem; 29 | development?: EggPluginItem; 30 | logrotator?: EggPluginItem; 31 | schedule?: EggPluginItem; 32 | static?: EggPluginItem; 33 | jsonp?: EggPluginItem; 34 | view?: EggPluginItem; 35 | jwt?: EggPluginItem; 36 | sequelize?: EggPluginItem; 37 | cors?: EggPluginItem; 38 | } 39 | } -------------------------------------------------------------------------------- /server/typings/index.d.ts: -------------------------------------------------------------------------------- 1 | import 'egg'; 2 | 3 | declare module 'egg' { 4 | jwt: any 5 | } -------------------------------------------------------------------------------- /uniapp/common/api/common/file.js: -------------------------------------------------------------------------------- 1 | import axios from '../axios' 2 | import store from '@/store' 3 | 4 | export default{ 5 | upload: (tempFilePaths)=>{ 6 | const header = {"ContentType":"application/json"}; 7 | if (store.state.token) { 8 | // 给请求头添加user-token 9 | header["authorization"] = store.state.token; 10 | } 11 | return new Promise((resolve,reject)=>{ 12 | uni.uploadFile({ 13 | url: store.state.baseUrl + '/api/file/upload', //仅为示例,非真实的接口地址 14 | filePath: tempFilePaths[0], 15 | name: 'file', 16 | header: header, 17 | success: (uploadFileRes) => { 18 | resolve(JSON.parse(uploadFileRes.data)) 19 | }, 20 | fail: (err)=>{ 21 | reject(err) 22 | } 23 | }); 24 | }) 25 | 26 | 27 | // axios.post('/api/file/upload',opt) 28 | } 29 | } -------------------------------------------------------------------------------- /uniapp/common/api/common/index.js: -------------------------------------------------------------------------------- 1 | import file from './file' 2 | export default{ 3 | file 4 | } -------------------------------------------------------------------------------- /uniapp/common/api/good/category.js: -------------------------------------------------------------------------------- 1 | import axios from '../axios' 2 | 3 | export default{ 4 | list: (params)=>axios.get('/api/goodCategory',{params}), 5 | tree: (params)=>axios.get('/api/goodCategory/tree',{params}), 6 | save: (opt)=>axios.post('/api/goodCategory/save',opt), 7 | remove: (id)=>axios.delete('/api/goodCategory/'+id), 8 | } -------------------------------------------------------------------------------- /uniapp/common/api/good/index.js: -------------------------------------------------------------------------------- 1 | import axios from '../axios' 2 | import category from './category' 3 | export default{ 4 | category, 5 | list: (params)=>axios.get('/api/good',{params}), 6 | detail: (id)=>axios.get('/api/good/'+id) 7 | } -------------------------------------------------------------------------------- /uniapp/common/api/index.js: -------------------------------------------------------------------------------- 1 | import user from './user' 2 | import good from './good' 3 | import common from './common' 4 | export default{ 5 | user, 6 | good, 7 | common 8 | } -------------------------------------------------------------------------------- /uniapp/common/api/user/address.js: -------------------------------------------------------------------------------- 1 | import axios from '../axios' 2 | 3 | export default{ 4 | list: (params)=>axios.get('/api/member/address',{params}), 5 | save: (opt)=>axios.post('/api/member/address/save',opt), 6 | remove: (id)=>axios.delete('/api/member/address/'+id), 7 | } -------------------------------------------------------------------------------- /uniapp/common/api/user/fav.js: -------------------------------------------------------------------------------- 1 | import axios from '../axios' 2 | 3 | export default{ 4 | list: (params)=>axios.get('/api/member/fav',{params}), 5 | save: (opt)=>axios.post('/api/member/fav/save',opt), 6 | remove: (id)=>axios.delete('/api/member/fav/'+id), 7 | } -------------------------------------------------------------------------------- /uniapp/common/api/user/index.js: -------------------------------------------------------------------------------- 1 | import axios from '../axios' 2 | import address from './address' 3 | import order from './order' 4 | import fav from './fav' 5 | export default{ 6 | login: (opt)=>axios.post('/api/user/login',opt), 7 | info: ()=>axios.get('/api/user/info'), 8 | update: (opt)=>axios.post('/api/user/update',opt), 9 | address, 10 | order, 11 | fav 12 | } -------------------------------------------------------------------------------- /uniapp/common/api/user/order.js: -------------------------------------------------------------------------------- 1 | import axios from '../axios' 2 | 3 | export default{ 4 | list: (params)=>axios.get('/api/order',{params}), 5 | save: (opt)=>axios.post('/api/order/save',opt), 6 | remove: (id)=>axios.delete('/api/order/'+id), 7 | cancel: (id)=>axios.post('/api/order/cancel/'+id), 8 | } -------------------------------------------------------------------------------- /uniapp/components/mix-list-cell.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 76 | 77 | 120 | -------------------------------------------------------------------------------- /uniapp/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import store from './store' 3 | import App from './App' 4 | 5 | import Json from './Json' //测试用数据 6 | /** 7 | * 因工具函数属于公司资产, 所以直接在Vue实例挂载几个常用的函数 8 | * 所有测试用数据均存放于根目录json.js 9 | * 10 | * css部分使用了App.vue下的全局样式和iconfont图标,有需要图标库的可以留言。 11 | * 示例使用了uni.scss下的变量, 除变量外已尽量移除特有语法,可直接替换为其他预处理器使用 12 | */ 13 | const msg = (title, duration=1500, mask=false, icon='none')=>{ 14 | //统一提示方便全局修改 15 | if(Boolean(title) === false){ 16 | return; 17 | } 18 | uni.showToast({ 19 | title, 20 | duration, 21 | mask, 22 | icon 23 | }); 24 | } 25 | const json = type=>{ 26 | //模拟异步请求数据 27 | return new Promise(resolve=>{ 28 | setTimeout(()=>{ 29 | resolve(Json[type]); 30 | }, 500) 31 | }) 32 | } 33 | 34 | const prePage = ()=>{ 35 | let pages = getCurrentPages(); 36 | let prePage = pages[pages.length - 2]; 37 | // #ifdef H5 38 | return prePage; 39 | // #endif 40 | return prePage.$vm; 41 | } 42 | 43 | 44 | import api from './common/api' 45 | 46 | Vue.config.productionTip = false 47 | Vue.prototype.$fire = new Vue(); 48 | Vue.prototype.$store = store; 49 | Vue.prototype.$api = {msg, json, prePage,...api}; 50 | 51 | 52 | App.mpType = 'app' 53 | 54 | const app = new Vue({ 55 | ...App 56 | }) 57 | app.$mount() -------------------------------------------------------------------------------- /uniapp/node_modules/axios/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-present Matt Zabriskie 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/axios'); -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/adapters/README.md: -------------------------------------------------------------------------------- 1 | # axios // adapters 2 | 3 | The modules under `adapters/` are modules that handle dispatching a request and settling a returned `Promise` once a response is received. 4 | 5 | ## Example 6 | 7 | ```js 8 | var settle = require('./../core/settle'); 9 | 10 | module.exports = function myAdapter(config) { 11 | // At this point: 12 | // - config has been merged with defaults 13 | // - request transformers have already run 14 | // - request interceptors have already run 15 | 16 | // Make the request using config provided 17 | // Upon response settle the Promise 18 | 19 | return new Promise(function(resolve, reject) { 20 | 21 | var response = { 22 | data: responseData, 23 | status: request.status, 24 | statusText: request.statusText, 25 | headers: responseHeaders, 26 | config: config, 27 | request: request 28 | }; 29 | 30 | settle(resolve, reject, response); 31 | 32 | // From here: 33 | // - response transformers will run 34 | // - response interceptors will run 35 | }); 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/axios.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./utils'); 4 | var bind = require('./helpers/bind'); 5 | var Axios = require('./core/Axios'); 6 | var mergeConfig = require('./core/mergeConfig'); 7 | var defaults = require('./defaults'); 8 | 9 | /** 10 | * Create an instance of Axios 11 | * 12 | * @param {Object} defaultConfig The default config for the instance 13 | * @return {Axios} A new instance of Axios 14 | */ 15 | function createInstance(defaultConfig) { 16 | var context = new Axios(defaultConfig); 17 | var instance = bind(Axios.prototype.request, context); 18 | 19 | // Copy axios.prototype to instance 20 | utils.extend(instance, Axios.prototype, context); 21 | 22 | // Copy context to instance 23 | utils.extend(instance, context); 24 | 25 | return instance; 26 | } 27 | 28 | // Create the default instance to be exported 29 | var axios = createInstance(defaults); 30 | 31 | // Expose Axios class to allow class inheritance 32 | axios.Axios = Axios; 33 | 34 | // Factory for creating new instances 35 | axios.create = function create(instanceConfig) { 36 | return createInstance(mergeConfig(axios.defaults, instanceConfig)); 37 | }; 38 | 39 | // Expose Cancel & CancelToken 40 | axios.Cancel = require('./cancel/Cancel'); 41 | axios.CancelToken = require('./cancel/CancelToken'); 42 | axios.isCancel = require('./cancel/isCancel'); 43 | 44 | // Expose all/spread 45 | axios.all = function all(promises) { 46 | return Promise.all(promises); 47 | }; 48 | axios.spread = require('./helpers/spread'); 49 | 50 | module.exports = axios; 51 | 52 | // Allow use of default import syntax in TypeScript 53 | module.exports.default = axios; 54 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/cancel/Cancel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * A `Cancel` is an object that is thrown when an operation is canceled. 5 | * 6 | * @class 7 | * @param {string=} message The message. 8 | */ 9 | function Cancel(message) { 10 | this.message = message; 11 | } 12 | 13 | Cancel.prototype.toString = function toString() { 14 | return 'Cancel' + (this.message ? ': ' + this.message : ''); 15 | }; 16 | 17 | Cancel.prototype.__CANCEL__ = true; 18 | 19 | module.exports = Cancel; 20 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/cancel/CancelToken.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Cancel = require('./Cancel'); 4 | 5 | /** 6 | * A `CancelToken` is an object that can be used to request cancellation of an operation. 7 | * 8 | * @class 9 | * @param {Function} executor The executor function. 10 | */ 11 | function CancelToken(executor) { 12 | if (typeof executor !== 'function') { 13 | throw new TypeError('executor must be a function.'); 14 | } 15 | 16 | var resolvePromise; 17 | this.promise = new Promise(function promiseExecutor(resolve) { 18 | resolvePromise = resolve; 19 | }); 20 | 21 | var token = this; 22 | executor(function cancel(message) { 23 | if (token.reason) { 24 | // Cancellation has already been requested 25 | return; 26 | } 27 | 28 | token.reason = new Cancel(message); 29 | resolvePromise(token.reason); 30 | }); 31 | } 32 | 33 | /** 34 | * Throws a `Cancel` if cancellation has been requested. 35 | */ 36 | CancelToken.prototype.throwIfRequested = function throwIfRequested() { 37 | if (this.reason) { 38 | throw this.reason; 39 | } 40 | }; 41 | 42 | /** 43 | * Returns an object that contains a new `CancelToken` and a function that, when called, 44 | * cancels the `CancelToken`. 45 | */ 46 | CancelToken.source = function source() { 47 | var cancel; 48 | var token = new CancelToken(function executor(c) { 49 | cancel = c; 50 | }); 51 | return { 52 | token: token, 53 | cancel: cancel 54 | }; 55 | }; 56 | 57 | module.exports = CancelToken; 58 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/cancel/isCancel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function isCancel(value) { 4 | return !!(value && value.__CANCEL__); 5 | }; 6 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/core/InterceptorManager.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | function InterceptorManager() { 6 | this.handlers = []; 7 | } 8 | 9 | /** 10 | * Add a new interceptor to the stack 11 | * 12 | * @param {Function} fulfilled The function to handle `then` for a `Promise` 13 | * @param {Function} rejected The function to handle `reject` for a `Promise` 14 | * 15 | * @return {Number} An ID used to remove interceptor later 16 | */ 17 | InterceptorManager.prototype.use = function use(fulfilled, rejected) { 18 | this.handlers.push({ 19 | fulfilled: fulfilled, 20 | rejected: rejected 21 | }); 22 | return this.handlers.length - 1; 23 | }; 24 | 25 | /** 26 | * Remove an interceptor from the stack 27 | * 28 | * @param {Number} id The ID that was returned by `use` 29 | */ 30 | InterceptorManager.prototype.eject = function eject(id) { 31 | if (this.handlers[id]) { 32 | this.handlers[id] = null; 33 | } 34 | }; 35 | 36 | /** 37 | * Iterate over all the registered interceptors 38 | * 39 | * This method is particularly useful for skipping over any 40 | * interceptors that may have become `null` calling `eject`. 41 | * 42 | * @param {Function} fn The function to call for each interceptor 43 | */ 44 | InterceptorManager.prototype.forEach = function forEach(fn) { 45 | utils.forEach(this.handlers, function forEachHandler(h) { 46 | if (h !== null) { 47 | fn(h); 48 | } 49 | }); 50 | }; 51 | 52 | module.exports = InterceptorManager; 53 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/core/README.md: -------------------------------------------------------------------------------- 1 | # axios // core 2 | 3 | The modules found in `core/` should be modules that are specific to the domain logic of axios. These modules would most likely not make sense to be consumed outside of the axios module, as their logic is too specific. Some examples of core modules are: 4 | 5 | - Dispatching requests 6 | - Managing interceptors 7 | - Handling config 8 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/core/buildFullPath.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var isAbsoluteURL = require('../helpers/isAbsoluteURL'); 4 | var combineURLs = require('../helpers/combineURLs'); 5 | 6 | /** 7 | * Creates a new URL by combining the baseURL with the requestedURL, 8 | * only when the requestedURL is not already an absolute URL. 9 | * If the requestURL is absolute, this function returns the requestedURL untouched. 10 | * 11 | * @param {string} baseURL The base URL 12 | * @param {string} requestedURL Absolute or relative URL to combine 13 | * @returns {string} The combined full path 14 | */ 15 | module.exports = function buildFullPath(baseURL, requestedURL) { 16 | if (baseURL && !isAbsoluteURL(requestedURL)) { 17 | return combineURLs(baseURL, requestedURL); 18 | } 19 | return requestedURL; 20 | }; 21 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/core/createError.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var enhanceError = require('./enhanceError'); 4 | 5 | /** 6 | * Create an Error with the specified message, config, error code, request and response. 7 | * 8 | * @param {string} message The error message. 9 | * @param {Object} config The config. 10 | * @param {string} [code] The error code (for example, 'ECONNABORTED'). 11 | * @param {Object} [request] The request. 12 | * @param {Object} [response] The response. 13 | * @returns {Error} The created error. 14 | */ 15 | module.exports = function createError(message, config, code, request, response) { 16 | var error = new Error(message); 17 | return enhanceError(error, config, code, request, response); 18 | }; 19 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/core/dispatchRequest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | var transformData = require('./transformData'); 5 | var isCancel = require('../cancel/isCancel'); 6 | var defaults = require('../defaults'); 7 | 8 | /** 9 | * Throws a `Cancel` if cancellation has been requested. 10 | */ 11 | function throwIfCancellationRequested(config) { 12 | if (config.cancelToken) { 13 | config.cancelToken.throwIfRequested(); 14 | } 15 | } 16 | 17 | /** 18 | * Dispatch a request to the server using the configured adapter. 19 | * 20 | * @param {object} config The config that is to be used for the request 21 | * @returns {Promise} The Promise to be fulfilled 22 | */ 23 | module.exports = function dispatchRequest(config) { 24 | throwIfCancellationRequested(config); 25 | 26 | // Ensure headers exist 27 | config.headers = config.headers || {}; 28 | 29 | // Transform request data 30 | config.data = transformData( 31 | config.data, 32 | config.headers, 33 | config.transformRequest 34 | ); 35 | 36 | // Flatten headers 37 | config.headers = utils.merge( 38 | config.headers.common || {}, 39 | config.headers[config.method] || {}, 40 | config.headers 41 | ); 42 | 43 | utils.forEach( 44 | ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], 45 | function cleanHeaderConfig(method) { 46 | delete config.headers[method]; 47 | } 48 | ); 49 | 50 | var adapter = config.adapter || defaults.adapter; 51 | 52 | return adapter(config).then(function onAdapterResolution(response) { 53 | throwIfCancellationRequested(config); 54 | 55 | // Transform response data 56 | response.data = transformData( 57 | response.data, 58 | response.headers, 59 | config.transformResponse 60 | ); 61 | 62 | return response; 63 | }, function onAdapterRejection(reason) { 64 | if (!isCancel(reason)) { 65 | throwIfCancellationRequested(config); 66 | 67 | // Transform response data 68 | if (reason && reason.response) { 69 | reason.response.data = transformData( 70 | reason.response.data, 71 | reason.response.headers, 72 | config.transformResponse 73 | ); 74 | } 75 | } 76 | 77 | return Promise.reject(reason); 78 | }); 79 | }; 80 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/core/enhanceError.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Update an Error with the specified config, error code, and response. 5 | * 6 | * @param {Error} error The error to update. 7 | * @param {Object} config The config. 8 | * @param {string} [code] The error code (for example, 'ECONNABORTED'). 9 | * @param {Object} [request] The request. 10 | * @param {Object} [response] The response. 11 | * @returns {Error} The error. 12 | */ 13 | module.exports = function enhanceError(error, config, code, request, response) { 14 | error.config = config; 15 | if (code) { 16 | error.code = code; 17 | } 18 | 19 | error.request = request; 20 | error.response = response; 21 | error.isAxiosError = true; 22 | 23 | error.toJSON = function toJSON() { 24 | return { 25 | // Standard 26 | message: this.message, 27 | name: this.name, 28 | // Microsoft 29 | description: this.description, 30 | number: this.number, 31 | // Mozilla 32 | fileName: this.fileName, 33 | lineNumber: this.lineNumber, 34 | columnNumber: this.columnNumber, 35 | stack: this.stack, 36 | // Axios 37 | config: this.config, 38 | code: this.code 39 | }; 40 | }; 41 | return error; 42 | }; 43 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/core/settle.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var createError = require('./createError'); 4 | 5 | /** 6 | * Resolve or reject a Promise based on response status. 7 | * 8 | * @param {Function} resolve A function that resolves the promise. 9 | * @param {Function} reject A function that rejects the promise. 10 | * @param {object} response The response. 11 | */ 12 | module.exports = function settle(resolve, reject, response) { 13 | var validateStatus = response.config.validateStatus; 14 | if (!response.status || !validateStatus || validateStatus(response.status)) { 15 | resolve(response); 16 | } else { 17 | reject(createError( 18 | 'Request failed with status code ' + response.status, 19 | response.config, 20 | null, 21 | response.request, 22 | response 23 | )); 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/core/transformData.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | /** 6 | * Transform the data for a request or a response 7 | * 8 | * @param {Object|String} data The data to be transformed 9 | * @param {Array} headers The headers for the request or response 10 | * @param {Array|Function} fns A single function or Array of functions 11 | * @returns {*} The resulting transformed data 12 | */ 13 | module.exports = function transformData(data, headers, fns) { 14 | /*eslint no-param-reassign:0*/ 15 | utils.forEach(fns, function transform(fn) { 16 | data = fn(data, headers); 17 | }); 18 | 19 | return data; 20 | }; 21 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/helpers/README.md: -------------------------------------------------------------------------------- 1 | # axios // helpers 2 | 3 | The modules found in `helpers/` should be generic modules that are _not_ specific to the domain logic of axios. These modules could theoretically be published to npm on their own and consumed by other modules or apps. Some examples of generic modules are things like: 4 | 5 | - Browser polyfills 6 | - Managing cookies 7 | - Parsing HTTP headers 8 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/helpers/bind.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function bind(fn, thisArg) { 4 | return function wrap() { 5 | var args = new Array(arguments.length); 6 | for (var i = 0; i < args.length; i++) { 7 | args[i] = arguments[i]; 8 | } 9 | return fn.apply(thisArg, args); 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/helpers/buildURL.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | function encode(val) { 6 | return encodeURIComponent(val). 7 | replace(/%3A/gi, ':'). 8 | replace(/%24/g, '$'). 9 | replace(/%2C/gi, ','). 10 | replace(/%20/g, '+'). 11 | replace(/%5B/gi, '['). 12 | replace(/%5D/gi, ']'); 13 | } 14 | 15 | /** 16 | * Build a URL by appending params to the end 17 | * 18 | * @param {string} url The base of the url (e.g., http://www.google.com) 19 | * @param {object} [params] The params to be appended 20 | * @returns {string} The formatted url 21 | */ 22 | module.exports = function buildURL(url, params, paramsSerializer) { 23 | /*eslint no-param-reassign:0*/ 24 | if (!params) { 25 | return url; 26 | } 27 | 28 | var serializedParams; 29 | if (paramsSerializer) { 30 | serializedParams = paramsSerializer(params); 31 | } else if (utils.isURLSearchParams(params)) { 32 | serializedParams = params.toString(); 33 | } else { 34 | var parts = []; 35 | 36 | utils.forEach(params, function serialize(val, key) { 37 | if (val === null || typeof val === 'undefined') { 38 | return; 39 | } 40 | 41 | if (utils.isArray(val)) { 42 | key = key + '[]'; 43 | } else { 44 | val = [val]; 45 | } 46 | 47 | utils.forEach(val, function parseValue(v) { 48 | if (utils.isDate(v)) { 49 | v = v.toISOString(); 50 | } else if (utils.isObject(v)) { 51 | v = JSON.stringify(v); 52 | } 53 | parts.push(encode(key) + '=' + encode(v)); 54 | }); 55 | }); 56 | 57 | serializedParams = parts.join('&'); 58 | } 59 | 60 | if (serializedParams) { 61 | var hashmarkIndex = url.indexOf('#'); 62 | if (hashmarkIndex !== -1) { 63 | url = url.slice(0, hashmarkIndex); 64 | } 65 | 66 | url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams; 67 | } 68 | 69 | return url; 70 | }; 71 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/helpers/combineURLs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Creates a new URL by combining the specified URLs 5 | * 6 | * @param {string} baseURL The base URL 7 | * @param {string} relativeURL The relative URL 8 | * @returns {string} The combined URL 9 | */ 10 | module.exports = function combineURLs(baseURL, relativeURL) { 11 | return relativeURL 12 | ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') 13 | : baseURL; 14 | }; 15 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/helpers/cookies.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | module.exports = ( 6 | utils.isStandardBrowserEnv() ? 7 | 8 | // Standard browser envs support document.cookie 9 | (function standardBrowserEnv() { 10 | return { 11 | write: function write(name, value, expires, path, domain, secure) { 12 | var cookie = []; 13 | cookie.push(name + '=' + encodeURIComponent(value)); 14 | 15 | if (utils.isNumber(expires)) { 16 | cookie.push('expires=' + new Date(expires).toGMTString()); 17 | } 18 | 19 | if (utils.isString(path)) { 20 | cookie.push('path=' + path); 21 | } 22 | 23 | if (utils.isString(domain)) { 24 | cookie.push('domain=' + domain); 25 | } 26 | 27 | if (secure === true) { 28 | cookie.push('secure'); 29 | } 30 | 31 | document.cookie = cookie.join('; '); 32 | }, 33 | 34 | read: function read(name) { 35 | var match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)')); 36 | return (match ? decodeURIComponent(match[3]) : null); 37 | }, 38 | 39 | remove: function remove(name) { 40 | this.write(name, '', Date.now() - 86400000); 41 | } 42 | }; 43 | })() : 44 | 45 | // Non standard browser env (web workers, react-native) lack needed support. 46 | (function nonStandardBrowserEnv() { 47 | return { 48 | write: function write() {}, 49 | read: function read() { return null; }, 50 | remove: function remove() {} 51 | }; 52 | })() 53 | ); 54 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/helpers/deprecatedMethod.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /*eslint no-console:0*/ 4 | 5 | /** 6 | * Supply a warning to the developer that a method they are using 7 | * has been deprecated. 8 | * 9 | * @param {string} method The name of the deprecated method 10 | * @param {string} [instead] The alternate method to use if applicable 11 | * @param {string} [docs] The documentation URL to get further details 12 | */ 13 | module.exports = function deprecatedMethod(method, instead, docs) { 14 | try { 15 | console.warn( 16 | 'DEPRECATED method `' + method + '`.' + 17 | (instead ? ' Use `' + instead + '` instead.' : '') + 18 | ' This method will be removed in a future release.'); 19 | 20 | if (docs) { 21 | console.warn('For more information about usage see ' + docs); 22 | } 23 | } catch (e) { /* Ignore */ } 24 | }; 25 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/helpers/isAbsoluteURL.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Determines whether the specified URL is absolute 5 | * 6 | * @param {string} url The URL to test 7 | * @returns {boolean} True if the specified URL is absolute, otherwise false 8 | */ 9 | module.exports = function isAbsoluteURL(url) { 10 | // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL). 11 | // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed 12 | // by any combination of letters, digits, plus, period, or hyphen. 13 | return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url); 14 | }; 15 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/helpers/isURLSameOrigin.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | module.exports = ( 6 | utils.isStandardBrowserEnv() ? 7 | 8 | // Standard browser envs have full support of the APIs needed to test 9 | // whether the request URL is of the same origin as current location. 10 | (function standardBrowserEnv() { 11 | var msie = /(msie|trident)/i.test(navigator.userAgent); 12 | var urlParsingNode = document.createElement('a'); 13 | var originURL; 14 | 15 | /** 16 | * Parse a URL to discover it's components 17 | * 18 | * @param {String} url The URL to be parsed 19 | * @returns {Object} 20 | */ 21 | function resolveURL(url) { 22 | var href = url; 23 | 24 | if (msie) { 25 | // IE needs attribute set twice to normalize properties 26 | urlParsingNode.setAttribute('href', href); 27 | href = urlParsingNode.href; 28 | } 29 | 30 | urlParsingNode.setAttribute('href', href); 31 | 32 | // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils 33 | return { 34 | href: urlParsingNode.href, 35 | protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', 36 | host: urlParsingNode.host, 37 | search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '', 38 | hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', 39 | hostname: urlParsingNode.hostname, 40 | port: urlParsingNode.port, 41 | pathname: (urlParsingNode.pathname.charAt(0) === '/') ? 42 | urlParsingNode.pathname : 43 | '/' + urlParsingNode.pathname 44 | }; 45 | } 46 | 47 | originURL = resolveURL(window.location.href); 48 | 49 | /** 50 | * Determine if a URL shares the same origin as the current location 51 | * 52 | * @param {String} requestURL The URL to test 53 | * @returns {boolean} True if URL shares the same origin, otherwise false 54 | */ 55 | return function isURLSameOrigin(requestURL) { 56 | var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL; 57 | return (parsed.protocol === originURL.protocol && 58 | parsed.host === originURL.host); 59 | }; 60 | })() : 61 | 62 | // Non standard browser envs (web workers, react-native) lack needed support. 63 | (function nonStandardBrowserEnv() { 64 | return function isURLSameOrigin() { 65 | return true; 66 | }; 67 | })() 68 | ); 69 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/helpers/normalizeHeaderName.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('../utils'); 4 | 5 | module.exports = function normalizeHeaderName(headers, normalizedName) { 6 | utils.forEach(headers, function processHeader(value, name) { 7 | if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) { 8 | headers[normalizedName] = value; 9 | delete headers[name]; 10 | } 11 | }); 12 | }; 13 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/helpers/parseHeaders.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var utils = require('./../utils'); 4 | 5 | // Headers whose duplicates are ignored by node 6 | // c.f. https://nodejs.org/api/http.html#http_message_headers 7 | var ignoreDuplicateOf = [ 8 | 'age', 'authorization', 'content-length', 'content-type', 'etag', 9 | 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since', 10 | 'last-modified', 'location', 'max-forwards', 'proxy-authorization', 11 | 'referer', 'retry-after', 'user-agent' 12 | ]; 13 | 14 | /** 15 | * Parse headers into an object 16 | * 17 | * ``` 18 | * Date: Wed, 27 Aug 2014 08:58:49 GMT 19 | * Content-Type: application/json 20 | * Connection: keep-alive 21 | * Transfer-Encoding: chunked 22 | * ``` 23 | * 24 | * @param {String} headers Headers needing to be parsed 25 | * @returns {Object} Headers parsed into an object 26 | */ 27 | module.exports = function parseHeaders(headers) { 28 | var parsed = {}; 29 | var key; 30 | var val; 31 | var i; 32 | 33 | if (!headers) { return parsed; } 34 | 35 | utils.forEach(headers.split('\n'), function parser(line) { 36 | i = line.indexOf(':'); 37 | key = utils.trim(line.substr(0, i)).toLowerCase(); 38 | val = utils.trim(line.substr(i + 1)); 39 | 40 | if (key) { 41 | if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) { 42 | return; 43 | } 44 | if (key === 'set-cookie') { 45 | parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]); 46 | } else { 47 | parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; 48 | } 49 | } 50 | }); 51 | 52 | return parsed; 53 | }; 54 | -------------------------------------------------------------------------------- /uniapp/node_modules/axios/lib/helpers/spread.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Syntactic sugar for invoking a function and expanding an array for arguments. 5 | * 6 | * Common use case would be to use `Function.prototype.apply`. 7 | * 8 | * ```js 9 | * function f(x, y, z) {} 10 | * var args = [1, 2, 3]; 11 | * f.apply(null, args); 12 | * ``` 13 | * 14 | * With `spread` this example can be re-written. 15 | * 16 | * ```js 17 | * spread(function(x, y, z) {})([1, 2, 3]); 18 | * ``` 19 | * 20 | * @param {Function} callback 21 | * @returns {Function} 22 | */ 23 | module.exports = function spread(callback) { 24 | return function wrap(arr) { 25 | return callback.apply(null, arr); 26 | }; 27 | }; 28 | -------------------------------------------------------------------------------- /uniapp/node_modules/follow-redirects/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014–present Olivier Lalonde , James Talmage , Ruben Verborgh 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 17 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 18 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /uniapp/node_modules/follow-redirects/debug.js: -------------------------------------------------------------------------------- 1 | var debug; 2 | try { 3 | /* eslint global-require: off */ 4 | debug = require("debug")("follow-redirects"); 5 | } 6 | catch (error) { 7 | debug = function () { /* */ }; 8 | } 9 | module.exports = debug; 10 | -------------------------------------------------------------------------------- /uniapp/node_modules/follow-redirects/http.js: -------------------------------------------------------------------------------- 1 | module.exports = require("./").http; 2 | -------------------------------------------------------------------------------- /uniapp/node_modules/follow-redirects/https.js: -------------------------------------------------------------------------------- 1 | module.exports = require("./").https; 2 | -------------------------------------------------------------------------------- /uniapp/node_modules/follow-redirects/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_from": "follow-redirects@^1.10.0", 3 | "_id": "follow-redirects@1.13.0", 4 | "_inBundle": false, 5 | "_integrity": "sha1-tC6Nk6Kn7qXtiGM2dtZZe8jjhNs=", 6 | "_location": "/follow-redirects", 7 | "_phantomChildren": {}, 8 | "_requested": { 9 | "type": "range", 10 | "registry": true, 11 | "raw": "follow-redirects@^1.10.0", 12 | "name": "follow-redirects", 13 | "escapedName": "follow-redirects", 14 | "rawSpec": "^1.10.0", 15 | "saveSpec": null, 16 | "fetchSpec": "^1.10.0" 17 | }, 18 | "_requiredBy": [ 19 | "/axios" 20 | ], 21 | "_resolved": "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.13.0.tgz", 22 | "_shasum": "b42e8d93a2a7eea5ed88633676d6597bc8e384db", 23 | "_spec": "follow-redirects@^1.10.0", 24 | "_where": "F:\\workspace\\eggjs-uniapp-shop\\uniapp\\node_modules\\axios", 25 | "author": { 26 | "name": "Ruben Verborgh", 27 | "email": "ruben@verborgh.org", 28 | "url": "https://ruben.verborgh.org/" 29 | }, 30 | "bugs": { 31 | "url": "https://github.com/follow-redirects/follow-redirects/issues" 32 | }, 33 | "bundleDependencies": false, 34 | "contributors": [ 35 | { 36 | "name": "Olivier Lalonde", 37 | "email": "olalonde@gmail.com", 38 | "url": "http://www.syskall.com" 39 | }, 40 | { 41 | "name": "James Talmage", 42 | "email": "james@talmage.io" 43 | } 44 | ], 45 | "deprecated": false, 46 | "description": "HTTP and HTTPS modules that follow redirects.", 47 | "devDependencies": { 48 | "concat-stream": "^2.0.0", 49 | "eslint": "^5.16.0", 50 | "express": "^4.16.4", 51 | "lolex": "^3.1.0", 52 | "mocha": "^6.0.2", 53 | "nyc": "^14.1.1" 54 | }, 55 | "engines": { 56 | "node": ">=4.0" 57 | }, 58 | "files": [ 59 | "*.js" 60 | ], 61 | "funding": [ 62 | { 63 | "type": "individual", 64 | "url": "https://github.com/sponsors/RubenVerborgh" 65 | } 66 | ], 67 | "homepage": "https://github.com/follow-redirects/follow-redirects", 68 | "keywords": [ 69 | "http", 70 | "https", 71 | "url", 72 | "redirect", 73 | "client", 74 | "location", 75 | "utility" 76 | ], 77 | "license": "MIT", 78 | "main": "index.js", 79 | "name": "follow-redirects", 80 | "repository": { 81 | "type": "git", 82 | "url": "git+ssh://git@github.com/follow-redirects/follow-redirects.git" 83 | }, 84 | "scripts": { 85 | "lint": "eslint *.js test", 86 | "mocha": "nyc mocha", 87 | "test": "npm run lint && npm run mocha" 88 | }, 89 | "version": "1.13.0" 90 | } 91 | -------------------------------------------------------------------------------- /uniapp/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "axios": { 6 | "version": "0.21.0", 7 | "resolved": "https://registry.npm.taobao.org/axios/download/axios-0.21.0.tgz?cache=0&sync_timestamp=1603468783865&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faxios%2Fdownload%2Faxios-0.21.0.tgz", 8 | "integrity": "sha1-Jt8IiAOiNQ3/LCf5b++Z/klEKso=", 9 | "requires": { 10 | "follow-redirects": "^1.10.0" 11 | } 12 | }, 13 | "follow-redirects": { 14 | "version": "1.13.0", 15 | "resolved": "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.13.0.tgz", 16 | "integrity": "sha1-tC6Nk6Kn7qXtiGM2dtZZe8jjhNs=" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /uniapp/pages/money/money.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 19 | 20 | 23 | -------------------------------------------------------------------------------- /uniapp/pages/money/orderSuccess.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 25 | 26 | 63 | -------------------------------------------------------------------------------- /uniapp/pages/money/paySuccess.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 25 | 26 | 63 | -------------------------------------------------------------------------------- /uniapp/pages/userinfo/setting.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 66 | 67 | 94 | -------------------------------------------------------------------------------- /uniapp/static/arc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/arc.png -------------------------------------------------------------------------------- /uniapp/static/emptyCart.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/emptyCart.jpg -------------------------------------------------------------------------------- /uniapp/static/errorImage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/errorImage.jpg -------------------------------------------------------------------------------- /uniapp/static/missing-face.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/missing-face.png -------------------------------------------------------------------------------- /uniapp/static/select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/select.png -------------------------------------------------------------------------------- /uniapp/static/selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/selected.png -------------------------------------------------------------------------------- /uniapp/static/tab-cart-current.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/tab-cart-current.png -------------------------------------------------------------------------------- /uniapp/static/tab-cart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/tab-cart.png -------------------------------------------------------------------------------- /uniapp/static/tab-cate-current.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/tab-cate-current.png -------------------------------------------------------------------------------- /uniapp/static/tab-cate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/tab-cate.png -------------------------------------------------------------------------------- /uniapp/static/tab-home-current.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/tab-home-current.png -------------------------------------------------------------------------------- /uniapp/static/tab-home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/tab-home.png -------------------------------------------------------------------------------- /uniapp/static/tab-my-current.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/tab-my-current.png -------------------------------------------------------------------------------- /uniapp/static/tab-my.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/tab-my.png -------------------------------------------------------------------------------- /uniapp/static/temp/ad-splash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/ad-splash.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/ad1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/ad1.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/ad2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/ad2.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/ad3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/ad3.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/banner1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/banner1.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/banner2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/banner2.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/banner3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/banner3.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/banner4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/banner4.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/c1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/c1.png -------------------------------------------------------------------------------- /uniapp/static/temp/c2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/c2.png -------------------------------------------------------------------------------- /uniapp/static/temp/c3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/c3.png -------------------------------------------------------------------------------- /uniapp/static/temp/c4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/c4.png -------------------------------------------------------------------------------- /uniapp/static/temp/c5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/c5.png -------------------------------------------------------------------------------- /uniapp/static/temp/c6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/c6.png -------------------------------------------------------------------------------- /uniapp/static/temp/c7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/c7.png -------------------------------------------------------------------------------- /uniapp/static/temp/c8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/c8.png -------------------------------------------------------------------------------- /uniapp/static/temp/cate1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate1.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate10.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate11.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate12.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate13.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate14.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate15.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate16.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate17.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate18.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate18.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate19.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate2.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate20.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate20.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate21.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate21.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate22.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate22.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate23.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate23.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate24.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate24.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate3.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate4.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate5.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate6.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate7.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate8.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/cate9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/cate9.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/h1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/h1.png -------------------------------------------------------------------------------- /uniapp/static/temp/secskill-img.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/secskill-img.jpg -------------------------------------------------------------------------------- /uniapp/static/temp/share_moment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/share_moment.png -------------------------------------------------------------------------------- /uniapp/static/temp/share_qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/share_qq.png -------------------------------------------------------------------------------- /uniapp/static/temp/share_qqzone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/share_qqzone.png -------------------------------------------------------------------------------- /uniapp/static/temp/share_wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/temp/share_wechat.png -------------------------------------------------------------------------------- /uniapp/static/user-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/user-bg.jpg -------------------------------------------------------------------------------- /uniapp/static/vip-card-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/vip-card-bg.png -------------------------------------------------------------------------------- /uniapp/static/yticon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anderw/eggjs-uniapp-shop/919baae2010e45c597d6d40630ebbaa37b5ea141/uniapp/static/yticon.ttf -------------------------------------------------------------------------------- /uniapp/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | Vue.use(Vuex) 5 | 6 | const store = new Vuex.Store({ 7 | state: { 8 | hasLogin: false, 9 | user: {}, 10 | token: '', 11 | baseUrl: 'http://localhost:7001', 12 | merchantId: 1 13 | }, 14 | mutations: { 15 | login(state, provider) { 16 | state.hasLogin = true; 17 | state.user = provider; 18 | uni.setStorage({//缓存用户登陆状态 19 | key: 'userInfo', 20 | data: provider 21 | }) 22 | }, 23 | logout(state) { 24 | state.hasLogin = false; 25 | state.user = {}; 26 | uni.removeStorage({ 27 | key: 'userInfo' 28 | }) 29 | }, 30 | setToken(state,token){ 31 | state.token = token 32 | uni.setStorage({ 33 | key: 'token', 34 | data: token 35 | }) 36 | } 37 | }, 38 | actions: { 39 | logout({commit}){ 40 | commit('logout') 41 | } 42 | } 43 | }) 44 | 45 | export default store 46 | -------------------------------------------------------------------------------- /uniapp/uni.scss: -------------------------------------------------------------------------------- 1 | 2 | /* 页面左右间距 */ 3 | $page-row-spacing: 30upx; 4 | $page-color-base: #f8f8f8; 5 | $page-color-light: #f8f6fc; 6 | $base-color: #fa436a; 7 | 8 | /* 文字尺寸 */ 9 | $font-sm: 24upx; 10 | $font-base: 28upx; 11 | $font-lg: 32upx; 12 | /*文字颜色*/ 13 | $font-color-dark: #303133; 14 | $font-color-base: #606266; 15 | $font-color-light: #909399; 16 | $font-color-disabled: #C0C4CC; 17 | $font-color-spec: #4399fc; 18 | /* 边框颜色 */ 19 | $border-color-dark: #DCDFE6; 20 | $border-color-base: #E4E7ED; 21 | $border-color-light: #EBEEF5; 22 | /* 图片加载中颜色 */ 23 | $image-bg-color: #eee; 24 | /* 行为相关颜色 */ 25 | $uni-color-primary:#fa436a; 26 | $uni-color-success: #4cd964; 27 | $uni-color-warning: #f0ad4e; 28 | $uni-color-error: #dd524d; 29 | 30 | 31 | 32 | --------------------------------------------------------------------------------