├── server
├── .vscode
│ └── settings.json
├── tools
│ ├── gormt.exe
│ └── config.yml
├── conf
│ ├── gen_router.data
│ ├── config.yml
│ └── cert
│ │ └── apiclient_cert.pem
├── internal
│ ├── service
│ │ ├── history
│ │ │ ├── def.go
│ │ │ ├── history.go
│ │ │ └── common.go
│ │ ├── login
│ │ │ ├── oauth2.go
│ │ │ └── def.go
│ │ ├── order
│ │ │ └── sql.go
│ │ ├── notify
│ │ │ ├── common.go
│ │ │ ├── def.go
│ │ │ └── notify.go
│ │ ├── file
│ │ │ └── file.go
│ │ ├── oplog
│ │ │ └── common.go
│ │ ├── weixin
│ │ │ └── def.go
│ │ └── product
│ │ │ ├── def.go
│ │ │ └── common.go
│ ├── config
│ │ └── test_def.go
│ └── api
│ │ └── context.go
├── gogenerate.go
├── docs
│ └── markdown
│ │ ├── Upload.md
│ │ └── Login.md
└── generate
│ └── proto_makefile
├── admin
├── .eslintignore
├── public
│ ├── favicon.ico
│ └── index.html
├── tests
│ └── unit
│ │ ├── .eslintrc.js
│ │ ├── utils
│ │ ├── param2Obj.spec.js
│ │ ├── formatTime.spec.js
│ │ ├── validate.spec.js
│ │ └── parseTime.spec.js
│ │ └── components
│ │ ├── Hamburger.spec.js
│ │ └── SvgIcon.spec.js
├── postcss.config.js
├── .env.production
├── src
│ ├── assets
│ │ ├── 401_images
│ │ │ └── 401.gif
│ │ ├── 404_images
│ │ │ ├── 404.png
│ │ │ └── 404_cloud.png
│ │ └── custom-theme
│ │ │ └── fonts
│ │ │ ├── element-icons.ttf
│ │ │ └── element-icons.woff
│ ├── views
│ │ ├── nested
│ │ │ ├── menu2
│ │ │ │ └── index.vue
│ │ │ └── menu1
│ │ │ │ ├── menu1-3
│ │ │ │ └── index.vue
│ │ │ │ ├── index.vue
│ │ │ │ ├── menu1-2
│ │ │ │ ├── menu1-2-1
│ │ │ │ │ └── index.vue
│ │ │ │ ├── menu1-2-2
│ │ │ │ │ └── index.vue
│ │ │ │ └── index.vue
│ │ │ │ └── menu1-1
│ │ │ │ └── index.vue
│ │ ├── error-log
│ │ │ ├── components
│ │ │ │ ├── ErrorTestB.vue
│ │ │ │ └── ErrorTestA.vue
│ │ │ └── index.vue
│ │ ├── example
│ │ │ ├── components
│ │ │ │ ├── Dropdown
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── SourceUrl.vue
│ │ │ │ │ ├── Comment.vue
│ │ │ │ │ └── Platform.vue
│ │ │ │ └── Warning.vue
│ │ │ ├── edit.vue
│ │ │ └── create.vue
│ │ ├── icons
│ │ │ └── svg-icons.js
│ │ ├── redirect
│ │ │ └── index.vue
│ │ ├── login
│ │ │ └── auth-redirect.vue
│ │ ├── pdf
│ │ │ └── index.vue
│ │ ├── charts
│ │ │ ├── line.vue
│ │ │ ├── mix-chart.vue
│ │ │ └── keyboard.vue
│ │ ├── permission
│ │ │ ├── page.vue
│ │ │ └── components
│ │ │ │ └── SwitchRoles.vue
│ │ ├── table
│ │ │ └── dynamic-table
│ │ │ │ ├── index.vue
│ │ │ │ └── components
│ │ │ │ └── UnfixedThead.vue
│ │ ├── excel
│ │ │ ├── components
│ │ │ │ ├── FilenameOption.vue
│ │ │ │ ├── AutoWidthOption.vue
│ │ │ │ └── BookTypeOption.vue
│ │ │ └── upload-excel.vue
│ │ ├── dashboard
│ │ │ ├── index.vue
│ │ │ └── admin
│ │ │ │ └── components
│ │ │ │ └── TransactionTable.vue
│ │ ├── profile
│ │ │ ├── components
│ │ │ │ ├── Account.vue
│ │ │ │ └── Timeline.vue
│ │ │ └── index.vue
│ │ ├── components-demo
│ │ │ ├── dnd-list.vue
│ │ │ ├── dropzone.vue
│ │ │ ├── drag-select.vue
│ │ │ ├── json-editor.vue
│ │ │ ├── drag-kanban.vue
│ │ │ ├── tinymce.vue
│ │ │ └── split-pane.vue
│ │ ├── guide
│ │ │ ├── index.vue
│ │ │ └── steps.js
│ │ ├── qiniu
│ │ │ └── upload.vue
│ │ ├── clipboard
│ │ │ └── index.vue
│ │ └── tab
│ │ │ └── index.vue
│ ├── App.vue
│ ├── icons
│ │ ├── svg
│ │ │ ├── chart.svg
│ │ │ ├── size.svg
│ │ │ ├── link.svg
│ │ │ ├── component.svg
│ │ │ ├── guide.svg
│ │ │ ├── money.svg
│ │ │ ├── email.svg
│ │ │ ├── drag.svg
│ │ │ ├── documentation.svg
│ │ │ ├── fullscreen.svg
│ │ │ ├── user.svg
│ │ │ ├── lock.svg
│ │ │ ├── excel.svg
│ │ │ ├── example.svg
│ │ │ ├── star.svg
│ │ │ ├── table.svg
│ │ │ ├── search.svg
│ │ │ ├── password.svg
│ │ │ ├── education.svg
│ │ │ ├── tab.svg
│ │ │ ├── message.svg
│ │ │ ├── theme.svg
│ │ │ ├── peoples.svg
│ │ │ ├── edit.svg
│ │ │ ├── nested.svg
│ │ │ ├── tree-table.svg
│ │ │ ├── eye.svg
│ │ │ ├── clipboard.svg
│ │ │ ├── list.svg
│ │ │ ├── icon.svg
│ │ │ ├── international.svg
│ │ │ ├── wechat.svg
│ │ │ ├── skill.svg
│ │ │ ├── people.svg
│ │ │ ├── language.svg
│ │ │ ├── eye-open.svg
│ │ │ ├── 404.svg
│ │ │ ├── zip.svg
│ │ │ ├── bug.svg
│ │ │ ├── pdf.svg
│ │ │ ├── exit-fullscreen.svg
│ │ │ └── tree.svg
│ │ └── index.js
│ ├── api
│ │ ├── qiniu.js
│ │ ├── remote-search.js
│ │ ├── user.js
│ │ ├── role.js
│ │ └── article.js
│ ├── components
│ │ ├── ImageCropper
│ │ │ └── utils
│ │ │ │ ├── mimes.js
│ │ │ │ ├── data2blob.js
│ │ │ │ └── effectRipple.js
│ │ ├── Tinymce
│ │ │ ├── toolbar.js
│ │ │ └── plugins.js
│ │ ├── MarkdownEditor
│ │ │ └── default-options.js
│ │ ├── Screenfull
│ │ │ └── index.vue
│ │ ├── Hamburger
│ │ │ └── index.vue
│ │ ├── SvgIcon
│ │ │ └── index.vue
│ │ ├── SizeSelect
│ │ │ └── index.vue
│ │ ├── Charts
│ │ │ └── mixins
│ │ │ │ └── resize.js
│ │ └── DragSelect
│ │ │ └── index.vue
│ ├── layout
│ │ ├── components
│ │ │ ├── index.js
│ │ │ ├── Sidebar
│ │ │ │ ├── FixiOSBug.js
│ │ │ │ ├── Link.vue
│ │ │ │ ├── Item.vue
│ │ │ │ └── index.vue
│ │ │ └── AppMain.vue
│ │ └── mixin
│ │ │ └── ResizeHandler.js
│ ├── utils
│ │ ├── get-page-title.js
│ │ ├── auth.js
│ │ ├── permission.js
│ │ ├── clipboard.js
│ │ ├── error-log.js
│ │ └── open-window.js
│ ├── directive
│ │ ├── waves
│ │ │ ├── index.js
│ │ │ └── waves.css
│ │ ├── el-drag-dialog
│ │ │ └── index.js
│ │ ├── clipboard
│ │ │ ├── index.js
│ │ │ └── clipboard.js
│ │ ├── permission
│ │ │ ├── index.js
│ │ │ └── permission.js
│ │ └── el-table
│ │ │ ├── index.js
│ │ │ └── adaptive.js
│ ├── store
│ │ ├── modules
│ │ │ ├── errorLog.js
│ │ │ ├── settings.js
│ │ │ ├── app.js
│ │ │ └── permission.js
│ │ ├── getters.js
│ │ └── index.js
│ ├── vendor
│ │ └── Export2Zip.js
│ ├── styles
│ │ ├── variables.scss
│ │ ├── element-variables.scss
│ │ ├── transition.scss
│ │ ├── element-ui.scss
│ │ └── mixin.scss
│ ├── settings.js
│ ├── router
│ │ └── modules
│ │ │ ├── charts.js
│ │ │ └── table.js
│ └── main.js
├── .env.development
├── plop-templates
│ ├── utils.js
│ ├── store
│ │ ├── index.hbs
│ │ └── prompt.js
│ ├── view
│ │ ├── index.hbs
│ │ └── prompt.js
│ └── component
│ │ ├── index.hbs
│ │ └── prompt.js
├── .env.staging
├── jsconfig.json
├── .editorconfig
├── .gitignore
├── plopfile.js
├── babel.config.js
├── jest.config.js
├── build
│ └── index.js
├── LICENSE
└── mock
│ ├── remote-search.js
│ ├── utils.js
│ └── index.js
├── image
├── 1.jpg
├── 10.jpg
├── 11.jpg
├── 12.jpg
├── 13.jpg
├── 2.jpg
├── 3.jpg
├── 4.jpg
├── 5.jpg
├── 6.jpg
├── 7.jpg
├── 8.jpg
└── 9.jpg
├── cert
├── cert.zip
├── 1600841165_20200807_cert.zip
├── 1600841165_20200807_cert
│ ├── apiclient_cert.p12
│ └── apiclient_cert.pem
└── 配置.txt
├── uniapp
└── commcn
│ ├── static
│ ├── to.png
│ ├── arc.png
│ ├── uni.ttf
│ ├── select.png
│ ├── tab-my.png
│ ├── temp
│ │ ├── c1.png
│ │ ├── c2.png
│ │ ├── c3.png
│ │ ├── c4.png
│ │ ├── c5.png
│ │ ├── c6.png
│ │ ├── c7.png
│ │ ├── c8.png
│ │ ├── h1.png
│ │ ├── ad1.jpg
│ │ ├── share_qq.png
│ │ ├── secskill-img.jpg
│ │ ├── share_moment.png
│ │ ├── share_qqzone.png
│ │ └── share_wechat.png
│ ├── user-bg.jpg
│ ├── yticon.ttf
│ ├── emptyCart.jpg
│ ├── selected.png
│ ├── tab-cart.png
│ ├── tab-cate.png
│ ├── tab-home.png
│ ├── truetype.ttf
│ ├── errorImage.jpg
│ ├── missing-face.png
│ ├── vip-card-bg.png
│ ├── tab-my-current.png
│ ├── tab-cart-current.png
│ ├── tab-cate-current.png
│ └── tab-home-current.png
│ ├── components
│ └── zz-prompt
│ │ └── README.md
│ ├── store
│ └── index.js
│ ├── uni.scss
│ ├── pages
│ ├── logistics
│ │ └── logistics.vue
│ └── money
│ │ └── paySuccess.vue
│ └── main.js
├── .gitignore
├── .gitmodules
└── apidoc
└── proto
├── common
└── common_public.proto
└── caoguo
└── weixin.proto
/server/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "go.inferGopath": false
3 | }
--------------------------------------------------------------------------------
/admin/.eslintignore:
--------------------------------------------------------------------------------
1 | build/*.js
2 | src/assets
3 | public
4 | dist
5 |
--------------------------------------------------------------------------------
/image/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/image/1.jpg
--------------------------------------------------------------------------------
/image/10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/image/10.jpg
--------------------------------------------------------------------------------
/image/11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/image/11.jpg
--------------------------------------------------------------------------------
/image/12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/image/12.jpg
--------------------------------------------------------------------------------
/image/13.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/image/13.jpg
--------------------------------------------------------------------------------
/image/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/image/2.jpg
--------------------------------------------------------------------------------
/image/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/image/3.jpg
--------------------------------------------------------------------------------
/image/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/image/4.jpg
--------------------------------------------------------------------------------
/image/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/image/5.jpg
--------------------------------------------------------------------------------
/image/6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/image/6.jpg
--------------------------------------------------------------------------------
/image/7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/image/7.jpg
--------------------------------------------------------------------------------
/image/8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/image/8.jpg
--------------------------------------------------------------------------------
/image/9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/image/9.jpg
--------------------------------------------------------------------------------
/cert/cert.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/cert/cert.zip
--------------------------------------------------------------------------------
/server/tools/gormt.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/server/tools/gormt.exe
--------------------------------------------------------------------------------
/admin/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/admin/public/favicon.ico
--------------------------------------------------------------------------------
/admin/tests/unit/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | jest: true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/admin/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {}
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/server/conf/gen_router.data:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/server/conf/gen_router.data
--------------------------------------------------------------------------------
/uniapp/commcn/static/to.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/to.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/arc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/arc.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/uni.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/uni.ttf
--------------------------------------------------------------------------------
/uniapp/commcn/static/select.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/select.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/tab-my.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/tab-my.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/temp/c1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/temp/c1.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/temp/c2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/temp/c2.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/temp/c3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/temp/c3.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/temp/c4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/temp/c4.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/temp/c5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/temp/c5.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/temp/c6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/temp/c6.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/temp/c7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/temp/c7.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/temp/c8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/temp/c8.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/temp/h1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/temp/h1.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/user-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/user-bg.jpg
--------------------------------------------------------------------------------
/uniapp/commcn/static/yticon.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/yticon.ttf
--------------------------------------------------------------------------------
/cert/1600841165_20200807_cert.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/cert/1600841165_20200807_cert.zip
--------------------------------------------------------------------------------
/uniapp/commcn/static/emptyCart.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/emptyCart.jpg
--------------------------------------------------------------------------------
/uniapp/commcn/static/selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/selected.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/tab-cart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/tab-cart.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/tab-cate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/tab-cate.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/tab-home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/tab-home.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/temp/ad1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/temp/ad1.jpg
--------------------------------------------------------------------------------
/uniapp/commcn/static/truetype.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/truetype.ttf
--------------------------------------------------------------------------------
/admin/.env.production:
--------------------------------------------------------------------------------
1 | # just a flag
2 | ENV = 'production'
3 |
4 | # base api
5 | VUE_APP_BASE_API = '/prod-api'
6 |
7 |
--------------------------------------------------------------------------------
/admin/src/assets/401_images/401.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/admin/src/assets/401_images/401.gif
--------------------------------------------------------------------------------
/admin/src/assets/404_images/404.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/admin/src/assets/404_images/404.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/errorImage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/errorImage.jpg
--------------------------------------------------------------------------------
/uniapp/commcn/static/missing-face.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/missing-face.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/vip-card-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/vip-card-bg.png
--------------------------------------------------------------------------------
/admin/.env.development:
--------------------------------------------------------------------------------
1 | # just a flag
2 | ENV = 'development'
3 |
4 | # base api
5 | VUE_APP_BASE_API = '/commcn/api/v1/'
6 |
--------------------------------------------------------------------------------
/admin/plop-templates/utils.js:
--------------------------------------------------------------------------------
1 | exports.notEmpty = name => v =>
2 | !v || v.trim() === '' ? `${name} is required` : true
3 |
--------------------------------------------------------------------------------
/uniapp/commcn/static/tab-my-current.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/tab-my-current.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/temp/share_qq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/temp/share_qq.png
--------------------------------------------------------------------------------
/admin/src/assets/404_images/404_cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/admin/src/assets/404_images/404_cloud.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/tab-cart-current.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/tab-cart-current.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/tab-cate-current.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/tab-cate-current.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/tab-home-current.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/tab-home-current.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/temp/secskill-img.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/temp/secskill-img.jpg
--------------------------------------------------------------------------------
/uniapp/commcn/static/temp/share_moment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/temp/share_moment.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/temp/share_qqzone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/temp/share_qqzone.png
--------------------------------------------------------------------------------
/uniapp/commcn/static/temp/share_wechat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/uniapp/commcn/static/temp/share_wechat.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | uniapp/commcn/unpackage/
2 | server/file/
3 | *.DS_Store
4 | *.log
5 | server/.DS_Store
6 | server/caoguo.exe
7 | server/caoguo
8 |
--------------------------------------------------------------------------------
/admin/.env.staging:
--------------------------------------------------------------------------------
1 | NODE_ENV = production
2 |
3 | # just a flag
4 | ENV = 'staging'
5 |
6 | # base api
7 | VUE_APP_BASE_API = '/stage-api'
8 |
9 |
--------------------------------------------------------------------------------
/cert/1600841165_20200807_cert/apiclient_cert.p12:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/cert/1600841165_20200807_cert/apiclient_cert.p12
--------------------------------------------------------------------------------
/server/internal/service/history/def.go:
--------------------------------------------------------------------------------
1 | package history
2 |
3 | type queInfo struct {
4 | UserID string
5 | Gpid string
6 | Icon string
7 | }
8 |
--------------------------------------------------------------------------------
/server/internal/service/login/oauth2.go:
--------------------------------------------------------------------------------
1 | package login
2 |
3 | //修改密码
4 | func OnChangePwd(username, passworld string) bool {
5 | return false
6 | }
7 |
--------------------------------------------------------------------------------
/admin/src/assets/custom-theme/fonts/element-icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/admin/src/assets/custom-theme/fonts/element-icons.ttf
--------------------------------------------------------------------------------
/admin/src/assets/custom-theme/fonts/element-icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xxjwxc/caoguo/HEAD/admin/src/assets/custom-theme/fonts/element-icons.woff
--------------------------------------------------------------------------------
/admin/src/views/nested/menu2/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/cert/配置.txt:
--------------------------------------------------------------------------------
1 | 密码:718921
2 | APPID: wxc085afa3e133c093
3 | mch_id: 1600841165
4 | key: adf2a407283e59ddd08dc5e27820d7d1 (md5:kcxxj)
5 | secret: 4EE0A9A43B9B911C067BEE5CC50A9972
--------------------------------------------------------------------------------
/server/gogenerate.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | // 编译所有
4 | //go:generate make -s -f generate/proto_makefile
5 | // go:generate make gen_proto -f generate/proto_makefile //部分
6 |
--------------------------------------------------------------------------------
/admin/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "./",
4 | "paths": {
5 | "@/*": ["src/*"]
6 | }
7 | },
8 | "exclude": ["node_modules", "dist"]
9 | }
--------------------------------------------------------------------------------
/admin/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/chart.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/views/nested/menu1/menu1-3/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/admin/src/api/qiniu.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function getToken() {
4 | return request({
5 | url: '/qiniu/upload/token', // 假地址 自行替换
6 | method: 'get'
7 | })
8 | }
9 |
--------------------------------------------------------------------------------
/admin/src/components/ImageCropper/utils/mimes.js:
--------------------------------------------------------------------------------
1 | export default {
2 | 'jpg': 'image/jpeg',
3 | 'png': 'image/png',
4 | 'gif': 'image/gif',
5 | 'svg': 'image/svg+xml',
6 | 'psd': 'image/photoshop'
7 | }
8 |
--------------------------------------------------------------------------------
/admin/src/views/nested/menu1/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/admin/src/views/nested/menu1/menu1-2/menu1-2-1/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/admin/src/views/nested/menu1/menu1-2/menu1-2-2/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/admin/src/views/error-log/components/ErrorTestB.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
--------------------------------------------------------------------------------
/admin/src/views/example/components/Dropdown/index.js:
--------------------------------------------------------------------------------
1 | export { default as CommentDropdown } from './Comment'
2 | export { default as PlatformDropdown } from './Platform'
3 | export { default as SourceUrlDropdown } from './SourceUrl'
4 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/size.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/views/nested/menu1/menu1-1/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/admin/src/views/nested/menu1/menu1-2/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/admin/src/views/error-log/components/ErrorTestA.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ a.a }}
5 |
6 |
7 |
8 |
9 |
14 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "ginrpc"]
2 | path = ginrpc
3 | url = https://github.com/xxjwxc/ginrpc
4 | [submodule "public"]
5 | path = public
6 | url = https://github.com/xxjwxc/public
7 | [submodule "goplugins"]
8 | path = goplugins
9 | url = https://github.com/gmsec/goplugins
10 |
--------------------------------------------------------------------------------
/admin/plop-templates/store/index.hbs:
--------------------------------------------------------------------------------
1 | {{#if state}}
2 | const state = {}
3 | {{/if}}
4 |
5 | {{#if mutations}}
6 | const mutations = {}
7 | {{/if}}
8 |
9 | {{#if actions}}
10 | const actions = {}
11 | {{/if}}
12 |
13 | export default {
14 | namespaced: true,
15 | {{options}}
16 | }
17 |
--------------------------------------------------------------------------------
/admin/src/views/example/edit.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
14 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/link.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/layout/components/index.js:
--------------------------------------------------------------------------------
1 | export { default as AppMain } from './AppMain'
2 | export { default as Navbar } from './Navbar'
3 | export { default as Settings } from './Settings'
4 | export { default as Sidebar } from './Sidebar/index.vue'
5 | export { default as TagsView } from './TagsView/index.vue'
6 |
--------------------------------------------------------------------------------
/admin/src/utils/get-page-title.js:
--------------------------------------------------------------------------------
1 | import defaultSettings from '@/settings'
2 |
3 | const title = defaultSettings.title || 'Vue Element Admin'
4 |
5 | export default function getPageTitle(pageTitle) {
6 | if (pageTitle) {
7 | return `${pageTitle} - ${title}`
8 | }
9 | return `${title}`
10 | }
11 |
--------------------------------------------------------------------------------
/admin/src/views/example/create.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
14 |
--------------------------------------------------------------------------------
/server/internal/service/history/history.go:
--------------------------------------------------------------------------------
1 | package history
2 |
3 | // Add 添加一个历史记录
4 | func Add(userID, gpid, icon string) {
5 | getLevelDB()
6 | _que.Push(queInfo{UserID: userID, Gpid: gpid, Icon: icon})
7 | }
8 |
9 | // Get 获取
10 | func Get(userID string) []queInfo {
11 | return gets(userID)
12 | }
13 |
--------------------------------------------------------------------------------
/admin/src/directive/waves/index.js:
--------------------------------------------------------------------------------
1 | import waves from './waves'
2 |
3 | const install = function(Vue) {
4 | Vue.directive('waves', waves)
5 | }
6 |
7 | if (window.Vue) {
8 | window.waves = waves
9 | Vue.use(install); // eslint-disable-line
10 | }
11 |
12 | waves.install = install
13 | export default waves
14 |
--------------------------------------------------------------------------------
/admin/src/views/icons/svg-icons.js:
--------------------------------------------------------------------------------
1 | const req = require.context('../../icons/svg', false, /\.svg$/)
2 | const requireAll = requireContext => requireContext.keys()
3 |
4 | const re = /\.\/(.*)\.svg/
5 |
6 | const svgIcons = requireAll(req).map(i => {
7 | return i.match(re)[1]
8 | })
9 |
10 | export default svgIcons
11 |
--------------------------------------------------------------------------------
/admin/.editorconfig:
--------------------------------------------------------------------------------
1 | # https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | end_of_line = lf
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.md]
13 | insert_final_newline = false
14 | trim_trailing_whitespace = false
15 |
--------------------------------------------------------------------------------
/admin/src/views/redirect/index.vue:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/admin/src/directive/el-drag-dialog/index.js:
--------------------------------------------------------------------------------
1 | import drag from './drag'
2 |
3 | const install = function(Vue) {
4 | Vue.directive('el-drag-dialog', drag)
5 | }
6 |
7 | if (window.Vue) {
8 | window['el-drag-dialog'] = drag
9 | Vue.use(install); // eslint-disable-line
10 | }
11 |
12 | drag.install = install
13 | export default drag
14 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/component.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/guide.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/icons/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import SvgIcon from '@/components/SvgIcon'// svg component
3 |
4 | // register globally
5 | Vue.component('svg-icon', SvgIcon)
6 |
7 | const req = require.context('./svg', false, /\.svg$/)
8 | const requireAll = requireContext => requireContext.keys().map(requireContext)
9 | requireAll(req)
10 |
--------------------------------------------------------------------------------
/admin/src/directive/clipboard/index.js:
--------------------------------------------------------------------------------
1 | import Clipboard from './clipboard'
2 |
3 | const install = function(Vue) {
4 | Vue.directive('Clipboard', Clipboard)
5 | }
6 |
7 | if (window.Vue) {
8 | window.clipboard = Clipboard
9 | Vue.use(install); // eslint-disable-line
10 | }
11 |
12 | Clipboard.install = install
13 | export default Clipboard
14 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/money.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/utils/auth.js:
--------------------------------------------------------------------------------
1 | import Cookies from 'js-cookie'
2 |
3 | const TokenKey = 'Admin-Token'
4 |
5 | export function getToken() {
6 | return Cookies.get(TokenKey)
7 | }
8 |
9 | export function setToken(token) {
10 | return Cookies.set(TokenKey, token)
11 | }
12 |
13 | export function removeToken() {
14 | return Cookies.remove(TokenKey)
15 | }
16 |
--------------------------------------------------------------------------------
/admin/src/directive/permission/index.js:
--------------------------------------------------------------------------------
1 | import permission from './permission'
2 |
3 | const install = function(Vue) {
4 | Vue.directive('permission', permission)
5 | }
6 |
7 | if (window.Vue) {
8 | window['permission'] = permission
9 | Vue.use(install); // eslint-disable-line
10 | }
11 |
12 | permission.install = install
13 | export default permission
14 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/email.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | **/*.log
8 |
9 | tests/**/coverage/
10 | tests/e2e/reports
11 | selenium-debug.log
12 |
13 | # Editor directories and files
14 | .idea
15 | .vscode
16 | *.suo
17 | *.ntvs*
18 | *.njsproj
19 | *.sln
20 | *.local
21 |
22 | package-lock.json
23 | yarn.lock
24 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/drag.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/directive/el-table/index.js:
--------------------------------------------------------------------------------
1 | import adaptive from './adaptive'
2 |
3 | const install = function(Vue) {
4 | Vue.directive('el-height-adaptive-table', adaptive)
5 | }
6 |
7 | if (window.Vue) {
8 | window['el-height-adaptive-table'] = adaptive
9 | Vue.use(install); // eslint-disable-line
10 | }
11 |
12 | adaptive.install = install
13 | export default adaptive
14 |
--------------------------------------------------------------------------------
/admin/src/views/login/auth-redirect.vue:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/admin/plopfile.js:
--------------------------------------------------------------------------------
1 | const viewGenerator = require('./plop-templates/view/prompt')
2 | const componentGenerator = require('./plop-templates/component/prompt')
3 | const storeGenerator = require('./plop-templates/store/prompt.js')
4 |
5 | module.exports = function(plop) {
6 | plop.setGenerator('view', viewGenerator)
7 | plop.setGenerator('component', componentGenerator)
8 | plop.setGenerator('store', storeGenerator)
9 | }
10 |
--------------------------------------------------------------------------------
/admin/src/views/pdf/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | Click to download PDF
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/admin/src/api/remote-search.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function searchUser(name) {
4 | return request({
5 | url: '/vue-element-admin/search/user',
6 | method: 'get',
7 | params: { name }
8 | })
9 | }
10 |
11 | export function transactionList(query) {
12 | return request({
13 | url: '/vue-element-admin/transaction/list',
14 | method: 'get',
15 | params: query
16 | })
17 | }
18 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/documentation.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/fullscreen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/plop-templates/view/index.hbs:
--------------------------------------------------------------------------------
1 | {{#if template}}
2 |
3 |
4 |
5 | {{/if}}
6 |
7 | {{#if script}}
8 |
20 | {{/if}}
21 |
22 | {{#if style}}
23 |
26 | {{/if}}
27 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/user.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/plop-templates/component/index.hbs:
--------------------------------------------------------------------------------
1 | {{#if template}}
2 |
3 |
4 |
5 | {{/if}}
6 |
7 | {{#if script}}
8 |
20 | {{/if}}
21 |
22 | {{#if style}}
23 |
26 | {{/if}}
27 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/lock.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/excel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/views/charts/line.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
15 |
16 |
23 |
24 |
--------------------------------------------------------------------------------
/admin/src/views/charts/mix-chart.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
15 |
16 |
23 |
24 |
--------------------------------------------------------------------------------
/admin/src/views/charts/keyboard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
15 |
16 |
23 |
24 |
--------------------------------------------------------------------------------
/admin/tests/unit/utils/param2Obj.spec.js:
--------------------------------------------------------------------------------
1 | import { param2Obj } from '@/utils/index.js'
2 | describe('Utils:param2Obj', () => {
3 | const url = 'https://github.com/PanJiaChen/vue-element-admin?name=bill&age=29&sex=1&field=dGVzdA==&key=%E6%B5%8B%E8%AF%95'
4 |
5 | it('param2Obj test', () => {
6 | expect(param2Obj(url)).toEqual({
7 | name: 'bill',
8 | age: '29',
9 | sex: '1',
10 | field: window.btoa('test'),
11 | key: '测试'
12 | })
13 | })
14 | })
15 |
--------------------------------------------------------------------------------
/admin/src/views/permission/page.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
20 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/example.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apidoc/proto/common/common_public.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3"; // 指定proto版本
2 |
3 | package common; // 指定包名
4 |
5 | // import "google/protobuf/descriptor.proto";
6 |
7 | // option go_package = "common;common"; // 指定路径
8 | option go_package = "rpc/common";
9 |
10 | message ResultResp {
11 | bool result = 1;
12 | string msg = 2;
13 | }
14 |
15 | // Empty 空
16 | message Empty {}
17 |
18 | // Page 分页
19 | message Page{
20 | int32 size = 1;// 每页尺寸
21 | int32 index = 2;// 第几页
22 | int32 limit = 3;// 总页数
23 | }
--------------------------------------------------------------------------------
/admin/src/components/Tinymce/toolbar.js:
--------------------------------------------------------------------------------
1 | // Here is a list of the toolbar
2 | // Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
3 |
4 | const toolbar = ['searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen']
5 |
6 | export default toolbar
7 |
--------------------------------------------------------------------------------
/admin/src/api/user.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function login(data) {
4 | return request({
5 | url: '/login/login',
6 | method: 'post',
7 | data
8 | })
9 | }
10 |
11 | export function getInfo(token) {
12 | return request({
13 | url: '/vue-element-admin/user/info',
14 | method: 'get',
15 | params: { token }
16 | })
17 | }
18 |
19 | export function logout() {
20 | return request({
21 | url: '/vue-element-admin/user/logout',
22 | method: 'post'
23 | })
24 | }
25 |
--------------------------------------------------------------------------------
/admin/src/store/modules/errorLog.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | logs: []
3 | }
4 |
5 | const mutations = {
6 | ADD_ERROR_LOG: (state, log) => {
7 | state.logs.push(log)
8 | },
9 | CLEAR_ERROR_LOG: (state) => {
10 | state.logs.splice(0)
11 | }
12 | }
13 |
14 | const actions = {
15 | addErrorLog({ commit }, log) {
16 | commit('ADD_ERROR_LOG', log)
17 | },
18 | clearErrorLog({ commit }) {
19 | commit('CLEAR_ERROR_LOG')
20 | }
21 | }
22 |
23 | export default {
24 | namespaced: true,
25 | state,
26 | mutations,
27 | actions
28 | }
29 |
--------------------------------------------------------------------------------
/admin/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | <%= webpackConfig.name %>
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/star.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/table.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/search.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/components/Tinymce/plugins.js:
--------------------------------------------------------------------------------
1 | // Any plugins you want to use has to be imported
2 | // Detail plugins list see https://www.tinymce.com/docs/plugins/
3 | // Custom builds see https://www.tinymce.com/download/custom-builds/
4 |
5 | const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']
6 |
7 | export default plugins
8 |
--------------------------------------------------------------------------------
/admin/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | // https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
4 | '@vue/cli-plugin-babel/preset'
5 | ],
6 | 'env': {
7 | 'development': {
8 | // babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
9 | // This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
10 | // https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html
11 | 'plugins': ['dynamic-import-node']
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/admin/src/store/getters.js:
--------------------------------------------------------------------------------
1 | const getters = {
2 | sidebar: state => state.app.sidebar,
3 | size: state => state.app.size,
4 | device: state => state.app.device,
5 | visitedViews: state => state.tagsView.visitedViews,
6 | cachedViews: state => state.tagsView.cachedViews,
7 | token: state => state.user.token,
8 | avatar: state => state.user.avatar,
9 | name: state => state.user.name,
10 | introduction: state => state.user.introduction,
11 | roles: state => state.user.roles,
12 | permission_routes: state => state.permission.routes,
13 | errorLogs: state => state.errorLog.logs
14 | }
15 | export default getters
16 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/password.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/components/ImageCropper/utils/data2blob.js:
--------------------------------------------------------------------------------
1 | /**
2 | * database64文件格式转换为2进制
3 | *
4 | * @param {[String]} data dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了
5 | * @param {[String]} mime [description]
6 | * @return {[blob]} [description]
7 | */
8 | export default function(data, mime) {
9 | data = data.split(',')[1]
10 | data = window.atob(data)
11 | var ia = new Uint8Array(data.length)
12 | for (var i = 0; i < data.length; i++) {
13 | ia[i] = data.charCodeAt(i)
14 | }
15 | // canvas.toDataURL 返回的默认格式就是 image/png
16 | return new Blob([ia], {
17 | type: mime
18 | })
19 | }
20 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/education.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/views/table/dynamic-table/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Fixed header, sorted by header order,
5 |
6 |
7 |
8 |
9 | Not fixed header, sorted by click order
10 |
11 |
12 |
13 |
14 |
15 |
24 |
25 |
--------------------------------------------------------------------------------
/server/docs/markdown/Upload.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## [推荐查看工具](https://www.iminho.me/)
4 |
5 | ## 总览:
6 | - [Upload]
7 | - [Waiting to write...]
8 |
9 | --------------------
10 |
11 | ### UploadMult
12 |
13 | #### 简要描述:
14 |
15 | - [上传文件 多个]
16 |
17 | #### 请求URL:
18 |
19 | - http://localhost:9001/commcn/api/v1/upload
20 |
21 | #### 请求方式:
22 |
23 | - post
24 |
25 | #### 请求参数:
26 |
27 |
28 | #### 请求示例:
29 | ```
30 | {}
31 | ```
32 |
33 | #### 返回参数说明:
34 |
35 |
36 | #### 返回示例:
37 |
38 | ```
39 | {}
40 | ```
41 |
42 | #### 备注:
43 |
44 | - 上传文件 多个
45 |
46 |
47 | --------------------
48 | --------------------
49 |
50 | #### 自定义类型:
51 |
52 |
53 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/tab.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/views/example/components/Warning.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/admin/src/utils/permission.js:
--------------------------------------------------------------------------------
1 | import store from '@/store'
2 |
3 | /**
4 | * @param {Array} value
5 | * @returns {Boolean}
6 | * @example see @/views/permission/directive.vue
7 | */
8 | export default function checkPermission(value) {
9 | if (value && value instanceof Array && value.length > 0) {
10 | const roles = store.getters && store.getters.roles
11 | const permissionRoles = value
12 |
13 | const hasPermission = roles.some(role => {
14 | return permissionRoles.includes(role)
15 | })
16 | return hasPermission
17 | } else {
18 | console.error(`need roles! Like v-permission="['admin','editor']"`)
19 | return false
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/message.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/theme.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/views/excel/components/FilenameOption.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
28 |
--------------------------------------------------------------------------------
/admin/src/vendor/Export2Zip.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import { saveAs } from 'file-saver'
3 | import JSZip from 'jszip'
4 |
5 | export function export_txt_to_zip(th, jsonData, txtName, zipName) {
6 | const zip = new JSZip()
7 | const txt_name = txtName || 'file'
8 | const zip_name = zipName || 'file'
9 | const data = jsonData
10 | let txtData = `${th}\r\n`
11 | data.forEach((row) => {
12 | let tempStr = ''
13 | tempStr = row.toString()
14 | txtData += `${tempStr}\r\n`
15 | })
16 | zip.file(`${txt_name}.txt`, txtData)
17 | zip.generateAsync({
18 | type: "blob"
19 | }).then((blob) => {
20 | saveAs(blob, `${zip_name}.zip`)
21 | }, (err) => {
22 | alert('导出失败')
23 | })
24 | }
25 |
--------------------------------------------------------------------------------
/uniapp/commcn/components/zz-prompt/README.md:
--------------------------------------------------------------------------------
1 | # Prompt
2 |
3 | ## 说明
4 |
5 | 一个可以输入内容并返回的prompt组件, 支持一个默认slot放入中间.
6 |
7 | ## 用法
8 |
9 | **父组件**
10 |
11 | template中
12 | ```html
13 |
14 |
15 |
16 | ```
17 |
18 | ```js
19 | import Prompt from '@/components/prompt/index.vue'
20 |
21 | export default {
22 | data() {
23 | return {
24 | // 控制弹框输入框显示
25 | promptVisible: false,
26 | }
27 | },
28 | methods: {
29 | /**
30 | * 点击弹出输入框确定
31 | */
32 | clickPromptConfirm(val) {
33 | console.log(val)
34 | },
35 | }
36 | }
37 | ```
--------------------------------------------------------------------------------
/uniapp/commcn/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 | userInfo: {},
10 | },
11 | mutations: {
12 | login(state, provider) {
13 | state.hasLogin = true;
14 | state.userInfo = provider;
15 | uni.setStorage({//缓存用户登陆状态
16 | key: 'userInfo',
17 | data: provider
18 | })
19 | console.log(state.userInfo);
20 | },
21 | logout(state) {
22 | state.hasLogin = false;
23 | state.userInfo = {};
24 | uni.removeStorage({
25 | key: 'userInfo'
26 | })
27 | }
28 | },
29 | actions: {
30 |
31 | }
32 | })
33 |
34 | export default store
35 |
--------------------------------------------------------------------------------
/admin/src/views/dashboard/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
32 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/peoples.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/components/MarkdownEditor/default-options.js:
--------------------------------------------------------------------------------
1 | // doc: https://nhnent.github.io/tui.editor/api/latest/ToastUIEditor.html#ToastUIEditor
2 | export default {
3 | minHeight: '200px',
4 | previewStyle: 'vertical',
5 | useCommandShortcut: true,
6 | useDefaultHTMLSanitizer: true,
7 | usageStatistics: false,
8 | hideModeSwitch: false,
9 | toolbarItems: [
10 | 'heading',
11 | 'bold',
12 | 'italic',
13 | 'strike',
14 | 'divider',
15 | 'hr',
16 | 'quote',
17 | 'divider',
18 | 'ul',
19 | 'ol',
20 | 'task',
21 | 'indent',
22 | 'outdent',
23 | 'divider',
24 | 'table',
25 | 'image',
26 | 'link',
27 | 'divider',
28 | 'code',
29 | 'codeblock'
30 | ]
31 | }
32 |
--------------------------------------------------------------------------------
/admin/tests/unit/components/Hamburger.spec.js:
--------------------------------------------------------------------------------
1 | import { shallowMount } from '@vue/test-utils'
2 | import Hamburger from '@/components/Hamburger/index.vue'
3 | describe('Hamburger.vue', () => {
4 | it('toggle click', () => {
5 | const wrapper = shallowMount(Hamburger)
6 | const mockFn = jest.fn()
7 | wrapper.vm.$on('toggleClick', mockFn)
8 | wrapper.find('.hamburger').trigger('click')
9 | expect(mockFn).toBeCalled()
10 | })
11 | it('prop isActive', () => {
12 | const wrapper = shallowMount(Hamburger)
13 | wrapper.setProps({ isActive: true })
14 | expect(wrapper.contains('.is-active')).toBe(true)
15 | wrapper.setProps({ isActive: false })
16 | expect(wrapper.contains('.is-active')).toBe(false)
17 | })
18 | })
19 |
--------------------------------------------------------------------------------
/admin/tests/unit/components/SvgIcon.spec.js:
--------------------------------------------------------------------------------
1 | import { shallowMount } from '@vue/test-utils'
2 | import SvgIcon from '@/components/SvgIcon/index.vue'
3 | describe('SvgIcon.vue', () => {
4 | it('iconClass', () => {
5 | const wrapper = shallowMount(SvgIcon, {
6 | propsData: {
7 | iconClass: 'test'
8 | }
9 | })
10 | expect(wrapper.find('use').attributes().href).toBe('#icon-test')
11 | })
12 | it('className', () => {
13 | const wrapper = shallowMount(SvgIcon, {
14 | propsData: {
15 | iconClass: 'test'
16 | }
17 | })
18 | expect(wrapper.classes().length).toBe(1)
19 | wrapper.setProps({ className: 'test' })
20 | expect(wrapper.classes().includes('test')).toBe(true)
21 | })
22 | })
23 |
--------------------------------------------------------------------------------
/uniapp/commcn/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 |
--------------------------------------------------------------------------------
/admin/src/layout/components/Sidebar/FixiOSBug.js:
--------------------------------------------------------------------------------
1 | export default {
2 | computed: {
3 | device() {
4 | return this.$store.state.app.device
5 | }
6 | },
7 | mounted() {
8 | // In order to fix the click on menu on the ios device will trigger the mouseleave bug
9 | // https://github.com/PanJiaChen/vue-element-admin/issues/1135
10 | this.fixBugIniOS()
11 | },
12 | methods: {
13 | fixBugIniOS() {
14 | const $subMenu = this.$refs.subMenu
15 | if ($subMenu) {
16 | const handleMouseleave = $subMenu.handleMouseleave
17 | $subMenu.handleMouseleave = (e) => {
18 | if (this.device === 'mobile') {
19 | return
20 | }
21 | handleMouseleave(e)
22 | }
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/admin/src/views/excel/components/AutoWidthOption.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | True
7 |
8 |
9 | False
10 |
11 |
12 |
13 |
14 |
15 |
35 |
--------------------------------------------------------------------------------
/admin/src/utils/clipboard.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Clipboard from 'clipboard'
3 |
4 | function clipboardSuccess() {
5 | Vue.prototype.$message({
6 | message: 'Copy successfully',
7 | type: 'success',
8 | duration: 1500
9 | })
10 | }
11 |
12 | function clipboardError() {
13 | Vue.prototype.$message({
14 | message: 'Copy failed',
15 | type: 'error'
16 | })
17 | }
18 |
19 | export default function handleClipboard(text, event) {
20 | const clipboard = new Clipboard(event.target, {
21 | text: () => text
22 | })
23 | clipboard.on('success', () => {
24 | clipboardSuccess()
25 | clipboard.destroy()
26 | })
27 | clipboard.on('error', () => {
28 | clipboardError()
29 | clipboard.destroy()
30 | })
31 | clipboard.onClick(event)
32 | }
33 |
--------------------------------------------------------------------------------
/admin/src/views/permission/components/SwitchRoles.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Your roles: {{ roles }}
5 |
6 | Switch roles:
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
33 |
--------------------------------------------------------------------------------
/admin/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import getters from './getters'
4 |
5 | Vue.use(Vuex)
6 |
7 | // https://webpack.js.org/guides/dependency-management/#requirecontext
8 | const modulesFiles = require.context('./modules', true, /\.js$/)
9 |
10 | // you do not need `import app from './modules/app'`
11 | // it will auto require all vuex module from modules file
12 | const modules = modulesFiles.keys().reduce((modules, modulePath) => {
13 | // set './app.js' => 'app'
14 | const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
15 | const value = modulesFiles(modulePath)
16 | modules[moduleName] = value.default
17 | return modules
18 | }, {})
19 |
20 | const store = new Vuex.Store({
21 | modules,
22 | getters
23 | })
24 |
25 | export default store
26 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/edit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/nested.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/api/role.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function getRoutes() {
4 | return request({
5 | url: '/vue-element-admin/routes',
6 | method: 'get'
7 | })
8 | }
9 |
10 | export function getRoles() {
11 | return request({
12 | url: '/vue-element-admin/roles',
13 | method: 'get'
14 | })
15 | }
16 |
17 | export function addRole(data) {
18 | return request({
19 | url: '/vue-element-admin/role',
20 | method: 'post',
21 | data
22 | })
23 | }
24 |
25 | export function updateRole(id, data) {
26 | return request({
27 | url: `/vue-element-admin/role/${id}`,
28 | method: 'put',
29 | data
30 | })
31 | }
32 |
33 | export function deleteRole(id) {
34 | return request({
35 | url: `/vue-element-admin/role/${id}`,
36 | method: 'delete'
37 | })
38 | }
39 |
--------------------------------------------------------------------------------
/server/internal/config/test_def.go:
--------------------------------------------------------------------------------
1 | package config
2 |
3 | import (
4 | "os"
5 | "strings"
6 | )
7 |
8 | const (
9 | testFile = `
10 | serial_number : "1.0" #版本号
11 | service_name : #服务名
12 | service_displayname : #服务显示名
13 | sercice_desc : #服务描述
14 | is_dev : false # 是否开发者模式
15 | out_dir : ./db # 输出目录
16 | singular_table : true # 单表模式:true:禁用表名复数,false:采用表明复数 参考:gorm.SingularTable
17 | simple : true #简单输出
18 | isJsonTag : true #是否打json标记
19 | mysql_info:
20 | host : 127.0.0.1
21 | port : 3306
22 | username : root
23 | password : qwer
24 | database : oauth_db
25 | `
26 | )
27 |
28 | // IsRunTesting Determine whether to use it in a test environment.判断是否在测试环境下使用
29 | func IsRunTesting() bool {
30 | if len(os.Args) > 1 {
31 | return strings.HasPrefix(os.Args[1], "-test")
32 | }
33 | return false
34 | }
35 |
--------------------------------------------------------------------------------
/admin/src/directive/permission/permission.js:
--------------------------------------------------------------------------------
1 | import store from '@/store'
2 |
3 | function checkPermission(el, binding) {
4 | const { value } = binding
5 | const roles = store.getters && store.getters.roles
6 |
7 | if (value && value instanceof Array) {
8 | if (value.length > 0) {
9 | const permissionRoles = value
10 |
11 | const hasPermission = roles.some(role => {
12 | return permissionRoles.includes(role)
13 | })
14 |
15 | if (!hasPermission) {
16 | el.parentNode && el.parentNode.removeChild(el)
17 | }
18 | }
19 | } else {
20 | throw new Error(`need roles! Like v-permission="['admin','editor']"`)
21 | }
22 | }
23 |
24 | export default {
25 | inserted(el, binding) {
26 | checkPermission(el, binding)
27 | },
28 | update(el, binding) {
29 | checkPermission(el, binding)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/server/internal/service/order/sql.go:
--------------------------------------------------------------------------------
1 | package order
2 |
3 | import "time"
4 |
5 | // BillOrderTbl 账单订单列表
6 | type BillOrderTbl struct {
7 | ID int64 `gorm:"primary_key"`
8 | BillID string `gorm:"unique_index:user_gpid;index:bill_id"` // 账单id
9 | Gpid string `gorm:"unique_index:user_gpid"` // 商品id
10 | Name string // 商品名字
11 | Price int64 // 商品价格(分)
12 | Icon string // 图标信息
13 | UserID string `gorm:"unique_index:user_gpid"` // 用户id
14 | Number int // 数量
15 | SkuList string `gorm:"unique_index:user_gpid"` // 属性列表
16 | SkuArrt string // 属性描述
17 | CreatedBy string // 创建者
18 | CreatedAt time.Time // 创建时间
19 | UpdatedBy string // 更新者
20 | UpdatedAt time.Time // 更新时间
21 | Status int // 状态
22 | CouponID int // 优惠券
23 | Title string // 优惠券名称
24 | }
25 |
--------------------------------------------------------------------------------
/admin/src/store/modules/settings.js:
--------------------------------------------------------------------------------
1 | import variables from '@/styles/element-variables.scss'
2 | import defaultSettings from '@/settings'
3 |
4 | const { showSettings, tagsView, fixedHeader, sidebarLogo } = defaultSettings
5 |
6 | const state = {
7 | theme: variables.theme,
8 | showSettings: showSettings,
9 | tagsView: tagsView,
10 | fixedHeader: fixedHeader,
11 | sidebarLogo: sidebarLogo
12 | }
13 |
14 | const mutations = {
15 | CHANGE_SETTING: (state, { key, value }) => {
16 | // eslint-disable-next-line no-prototype-builtins
17 | if (state.hasOwnProperty(key)) {
18 | state[key] = value
19 | }
20 | }
21 | }
22 |
23 | const actions = {
24 | changeSetting({ commit }, data) {
25 | commit('CHANGE_SETTING', data)
26 | }
27 | }
28 |
29 | export default {
30 | namespaced: true,
31 | state,
32 | mutations,
33 | actions
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/admin/src/views/excel/components/BookTypeOption.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
40 |
--------------------------------------------------------------------------------
/admin/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
3 | transform: {
4 | '^.+\\.vue$': 'vue-jest',
5 | '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
6 | 'jest-transform-stub',
7 | '^.+\\.jsx?$': 'babel-jest'
8 | },
9 | moduleNameMapper: {
10 | '^@/(.*)$': '/src/$1'
11 | },
12 | snapshotSerializers: ['jest-serializer-vue'],
13 | testMatch: [
14 | '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
15 | ],
16 | collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
17 | coverageDirectory: '/tests/unit/coverage',
18 | // 'collectCoverage': true,
19 | 'coverageReporters': [
20 | 'lcov',
21 | 'text-summary'
22 | ],
23 | testURL: 'http://localhost/'
24 | }
25 |
--------------------------------------------------------------------------------
/admin/src/layout/components/Sidebar/Link.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
44 |
--------------------------------------------------------------------------------
/admin/src/layout/components/Sidebar/Item.vue:
--------------------------------------------------------------------------------
1 |
34 |
35 |
42 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/tree-table.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/views/profile/components/Account.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Update
11 |
12 |
13 |
14 |
15 |
39 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/eye.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/api/article.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function fetchList(query) {
4 | return request({
5 | url: '/vue-element-admin/article/list',
6 | method: 'get',
7 | params: query
8 | })
9 | }
10 |
11 | export function fetchArticle(id) {
12 | return request({
13 | url: '/vue-element-admin/article/detail',
14 | method: 'get',
15 | params: { id }
16 | })
17 | }
18 |
19 | export function fetchPv(pv) {
20 | return request({
21 | url: '/vue-element-admin/article/pv',
22 | method: 'get',
23 | params: { pv }
24 | })
25 | }
26 |
27 | export function createArticle(data) {
28 | return request({
29 | url: '/vue-element-admin/article/create',
30 | method: 'post',
31 | data
32 | })
33 | }
34 |
35 | export function updateArticle(data) {
36 | return request({
37 | url: '/vue-element-admin/article/update',
38 | method: 'post',
39 | data
40 | })
41 | }
42 |
--------------------------------------------------------------------------------
/admin/src/styles/variables.scss:
--------------------------------------------------------------------------------
1 | // base color
2 | $blue:#324157;
3 | $light-blue:#3A71A8;
4 | $red:#C03639;
5 | $pink: #E65D6E;
6 | $green: #30B08F;
7 | $tiffany: #4AB7BD;
8 | $yellow:#FEC171;
9 | $panGreen: #30B08F;
10 |
11 | // sidebar
12 | $menuText:#bfcbd9;
13 | $menuActiveText:#409EFF;
14 | $subMenuActiveText:#f4f4f5; // https://github.com/ElemeFE/element/issues/12951
15 |
16 | $menuBg:#304156;
17 | $menuHover:#263445;
18 |
19 | $subMenuBg:#1f2d3d;
20 | $subMenuHover:#001528;
21 |
22 | $sideBarWidth: 210px;
23 |
24 | // the :export directive is the magic sauce for webpack
25 | // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
26 | :export {
27 | menuText: $menuText;
28 | menuActiveText: $menuActiveText;
29 | subMenuActiveText: $subMenuActiveText;
30 | menuBg: $menuBg;
31 | menuHover: $menuHover;
32 | subMenuBg: $subMenuBg;
33 | subMenuHover: $subMenuHover;
34 | sideBarWidth: $sideBarWidth;
35 | }
36 |
--------------------------------------------------------------------------------
/admin/src/directive/waves/waves.css:
--------------------------------------------------------------------------------
1 | .waves-ripple {
2 | position: absolute;
3 | border-radius: 100%;
4 | background-color: rgba(0, 0, 0, 0.15);
5 | background-clip: padding-box;
6 | pointer-events: none;
7 | -webkit-user-select: none;
8 | -moz-user-select: none;
9 | -ms-user-select: none;
10 | user-select: none;
11 | -webkit-transform: scale(0);
12 | -ms-transform: scale(0);
13 | transform: scale(0);
14 | opacity: 1;
15 | }
16 |
17 | .waves-ripple.z-active {
18 | opacity: 0;
19 | -webkit-transform: scale(2);
20 | -ms-transform: scale(2);
21 | transform: scale(2);
22 | -webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
23 | transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
24 | transition: opacity 1.2s ease-out, transform 0.6s ease-out;
25 | transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out;
26 | }
--------------------------------------------------------------------------------
/admin/src/styles/element-variables.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * I think element-ui's default theme color is too light for long-term use.
3 | * So I modified the default color and you can modify it to your liking.
4 | **/
5 |
6 | /* theme color */
7 | $--color-primary: #1890ff;
8 | $--color-success: #13ce66;
9 | $--color-warning: #ffba00;
10 | $--color-danger: #ff4949;
11 | // $--color-info: #1E1E1E;
12 |
13 | $--button-font-weight: 400;
14 |
15 | // $--color-text-regular: #1f2d3d;
16 |
17 | $--border-color-light: #dfe4ed;
18 | $--border-color-lighter: #e6ebf5;
19 |
20 | $--table-border: 1px solid #dfe6ec;
21 |
22 | /* icon font path, required */
23 | $--font-path: "~element-ui/lib/theme-chalk/fonts";
24 |
25 | @import "~element-ui/packages/theme-chalk/src/index";
26 |
27 | // the :export directive is the magic sauce for webpack
28 | // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
29 | :export {
30 | theme: $--color-primary;
31 | }
32 |
--------------------------------------------------------------------------------
/admin/src/styles/transition.scss:
--------------------------------------------------------------------------------
1 | // global transition css
2 |
3 | /* fade */
4 | .fade-enter-active,
5 | .fade-leave-active {
6 | transition: opacity 0.28s;
7 | }
8 |
9 | .fade-enter,
10 | .fade-leave-active {
11 | opacity: 0;
12 | }
13 |
14 | /* fade-transform */
15 | .fade-transform-leave-active,
16 | .fade-transform-enter-active {
17 | transition: all .5s;
18 | }
19 |
20 | .fade-transform-enter {
21 | opacity: 0;
22 | transform: translateX(-30px);
23 | }
24 |
25 | .fade-transform-leave-to {
26 | opacity: 0;
27 | transform: translateX(30px);
28 | }
29 |
30 | /* breadcrumb transition */
31 | .breadcrumb-enter-active,
32 | .breadcrumb-leave-active {
33 | transition: all .5s;
34 | }
35 |
36 | .breadcrumb-enter,
37 | .breadcrumb-leave-active {
38 | opacity: 0;
39 | transform: translateX(20px);
40 | }
41 |
42 | .breadcrumb-move {
43 | transition: all .5s;
44 | }
45 |
46 | .breadcrumb-leave-active {
47 | position: absolute;
48 | }
49 |
--------------------------------------------------------------------------------
/uniapp/commcn/pages/logistics/logistics.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
40 |
41 |
44 |
--------------------------------------------------------------------------------
/admin/src/settings.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | title: 'Vue Element Admin',
3 |
4 | /**
5 | * @type {boolean} true | false
6 | * @description Whether show the settings right-panel
7 | */
8 | showSettings: true,
9 |
10 | /**
11 | * @type {boolean} true | false
12 | * @description Whether need tagsView
13 | */
14 | tagsView: true,
15 |
16 | /**
17 | * @type {boolean} true | false
18 | * @description Whether fix the header
19 | */
20 | fixedHeader: false,
21 |
22 | /**
23 | * @type {boolean} true | false
24 | * @description Whether show the logo in sidebar
25 | */
26 | sidebarLogo: false,
27 |
28 | /**
29 | * @type {string | array} 'production' | ['production', 'development']
30 | * @description Need show err logs component.
31 | * The default is only used in the production env
32 | * If you want to also use it in dev, you can pass ['production', 'development']
33 | */
34 | errorLog: 'production'
35 | }
36 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/clipboard.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/list.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/router/modules/charts.js:
--------------------------------------------------------------------------------
1 | /** When your routing table is too long, you can split it into small modules**/
2 |
3 | import Layout from '@/layout'
4 |
5 | const chartsRouter = {
6 | path: '/charts',
7 | component: Layout,
8 | redirect: 'noRedirect',
9 | name: 'Charts',
10 | meta: {
11 | title: 'Charts',
12 | icon: 'chart'
13 | },
14 | children: [
15 | {
16 | path: 'keyboard',
17 | component: () => import('@/views/charts/keyboard'),
18 | name: 'KeyboardChart',
19 | meta: { title: 'Keyboard Chart', noCache: true }
20 | },
21 | {
22 | path: 'line',
23 | component: () => import('@/views/charts/line'),
24 | name: 'LineChart',
25 | meta: { title: 'Line Chart', noCache: true }
26 | },
27 | {
28 | path: 'mix-chart',
29 | component: () => import('@/views/charts/mix-chart'),
30 | name: 'MixChart',
31 | meta: { title: 'Mix Chart', noCache: true }
32 | }
33 | ]
34 | }
35 |
36 | export default chartsRouter
37 |
--------------------------------------------------------------------------------
/admin/src/views/components-demo/dnd-list.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
39 |
40 |
--------------------------------------------------------------------------------
/admin/src/views/guide/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 | Show Guide
10 |
11 |
12 |
13 |
14 |
37 |
--------------------------------------------------------------------------------
/admin/build/index.js:
--------------------------------------------------------------------------------
1 | const { run } = require('runjs')
2 | const chalk = require('chalk')
3 | const config = require('../vue.config.js')
4 | const rawArgv = process.argv.slice(2)
5 | const args = rawArgv.join(' ')
6 |
7 | if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
8 | const report = rawArgv.includes('--report')
9 |
10 | run(`vue-cli-service build ${args}`)
11 |
12 | const port = 9526
13 | const publicPath = config.publicPath
14 |
15 | var connect = require('connect')
16 | var serveStatic = require('serve-static')
17 | const app = connect()
18 |
19 | app.use(
20 | publicPath,
21 | serveStatic('./dist', {
22 | index: ['index.html', '/']
23 | })
24 | )
25 |
26 | app.listen(port, function () {
27 | console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`))
28 | if (report) {
29 | console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`))
30 | }
31 |
32 | })
33 | } else {
34 | run(`vue-cli-service build ${args}`)
35 | }
36 |
--------------------------------------------------------------------------------
/admin/src/views/example/components/Dropdown/SourceUrl.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Link
5 |
6 |
7 |
8 |
9 |
10 |
11 | URL
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
39 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/utils/error-log.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import store from '@/store'
3 | import { isString, isArray } from '@/utils/validate'
4 | import settings from '@/settings'
5 |
6 | // you can set in settings.js
7 | // errorLog:'production' | ['production', 'development']
8 | const { errorLog: needErrorLog } = settings
9 |
10 | function checkNeed() {
11 | const env = process.env.NODE_ENV
12 | if (isString(needErrorLog)) {
13 | return env === needErrorLog
14 | }
15 | if (isArray(needErrorLog)) {
16 | return needErrorLog.includes(env)
17 | }
18 | return false
19 | }
20 |
21 | if (checkNeed()) {
22 | Vue.config.errorHandler = function(err, vm, info, a) {
23 | // Don't ask me why I use Vue.nextTick, it just a hack.
24 | // detail see https://forum.vuejs.org/t/dispatch-in-vue-config-errorhandler-has-some-problem/23500
25 | Vue.nextTick(() => {
26 | store.dispatch('errorLog/addErrorLog', {
27 | err,
28 | vm,
29 | info,
30 | url: window.location.href
31 | })
32 | console.error(err, info)
33 | })
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/international.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/server/tools/config.yml:
--------------------------------------------------------------------------------
1 | base:
2 | is_dev : false
3 | out_dir : ./model # 输出目录
4 | url_tag : json # web url tag(json,db(https://github.com/google/go-querystring))
5 | language : # 语言(English,中 文)
6 | db_tag : gorm # 数据库标签(gorm,db)
7 | simple : true # 简单输出(默认gorm标签不输出)
8 | is_out_sql : false # 是否输出 sql 原信息
9 | is_out_func : true # 是否输出 快捷函数
10 | is_web_tag : true # 是否打web标记(json标记前提条件)
11 | is_web_tag_pk_hidden: true # web标记是否隐藏主键
12 | is_foreign_key : true # 是否导出外键关联
13 | is_gui : false # 是否ui模式显示
14 | is_table_name : true # 是否直接生成表名,列名
15 | is_null_to_point : false # 数据库默认 'DEFAULT NULL' 时设置结构为指针类型
16 | table_prefix : "" # 表前缀, 如果有则使用, 没有留空
17 | db_info:
18 | host : 192.155.1.150 # type=1的时候,host为yml文件全路径
19 | port : 3306
20 | database : dev_haitrain
21 | username : devserver
22 | password : dev.hello123
23 | type: 0 # 数据库类型:0:mysql , 1:sqlite , 2:mssql
24 |
25 | # sqlite
26 | # db_info:
27 | # host : /Users/xxj/Downloads/caoguo # type=1的时候,host为yml文件全路径
28 | # port :
29 | # username :
30 | # password :
31 | # database :
32 | # type: 1 # 数据库类型:0:mysql , 1:sqlite , 2:mssql
--------------------------------------------------------------------------------
/server/conf/config.yml:
--------------------------------------------------------------------------------
1 | base:
2 | serial_number: "v1" # 版本号
3 | service_name: "caoguo" # 服务名
4 | service_displayname: "caoguo" # 服务显示名
5 | sercice_desc: "caoguo" # 描述
6 | is_dev: true
7 | mysql_info:
8 | port : 3306 # 端口号
9 | username : root # 用户名
10 | host : localhost # 地址
11 | password : 123456 # 密码
12 | # host : localhost
13 | # password : qwer
14 | database : caoguo_dev # 数据库名
15 | kdniao: # 快递鸟配置
16 | business_id : 1317777
17 | app_key : 111111-2222-3333-4444-555555555
18 | email: # 发邮件配置
19 | user: xie1xiao1jun@126.com
20 | password: pppppppppppppp
21 | host: smtp.126.com:25
22 | wx_info: # 微信相关配置
23 | app_id : wxc111111111111
24 | app_secret : 111111111111111111111
25 | api_key : 1111111111111111111111111
26 | mch_id : 1111111111111111
27 | notify_url : http://www.xxjwxc.cn
28 | shear_url : ""
29 | file_host: https://localhost/commcn/api/v1
30 | oauth2_url: http://localhost/oauth2/api/v1
31 | register_url: http://localhost/register/api/v1
32 | token_type: nomal
33 | app_id: wwwthings
34 | app_secret: 4EE0A9A43B9B911C067BEE5CC50A9972
35 | port : 8001
--------------------------------------------------------------------------------
/admin/src/views/components-demo/dropzone.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
31 |
32 |
--------------------------------------------------------------------------------
/admin/src/views/example/components/Dropdown/Comment.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ !comment_disabled?'Comment: opened':'Comment: closed' }}
5 |
6 |
7 |
8 |
9 |
10 |
11 | Close comment
12 |
13 |
14 | Open comment
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
42 |
--------------------------------------------------------------------------------
/admin/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017-present PanJiaChen
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 all
13 | 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 THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/server/internal/service/notify/common.go:
--------------------------------------------------------------------------------
1 | package notify
2 |
3 | import (
4 | "caoguo/internal/core"
5 | "caoguo/internal/model"
6 | "sync"
7 | "time"
8 |
9 | "github.com/xxjwxc/public/mycache"
10 | )
11 |
12 | var cache *mycache.MyCache
13 | var once sync.Once
14 | var mtx sync.Mutex
15 |
16 | func getEmailList(username string) (resp []string) {
17 | once.Do(func() {
18 | cache = mycache.NewCache("_email_list")
19 | })
20 |
21 | mp := make(map[string][]string)
22 | mtx.Lock()
23 | defer mtx.Unlock()
24 | err := cache.Value("list", &mp)
25 | if err == nil { // 找到
26 | resp = append(resp, mp[""]...)
27 | if _, ok := mp[username]; ok {
28 | resp = append(resp, mp[username]...)
29 | }
30 | return
31 | }
32 |
33 | mp = make(map[string][]string)
34 | orm := core.Dao.GetDBr()
35 | list, _ := model.EmailNotifyTblMgr(orm.DB).Gets()
36 | for _, v := range list {
37 | mp[v.UserID] = append(mp[v.UserID], v.Email)
38 | }
39 |
40 | //添加
41 | cache.Add("list", mp, 1*time.Hour) // 1小时更新一次
42 | resp = append(resp, mp[""]...)
43 | if _, ok := mp[username]; ok {
44 | resp = append(resp, mp[username]...)
45 | }
46 | return resp
47 | }
48 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/wechat.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/skill.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/tests/unit/utils/formatTime.spec.js:
--------------------------------------------------------------------------------
1 | import { formatTime } from '@/utils/index.js'
2 | describe('Utils:formatTime', () => {
3 | const d = new Date('2018-07-13 17:54:01') // "2018-07-13 17:54:01"
4 | const retrofit = 5 * 1000
5 |
6 | it('ten digits timestamp', () => {
7 | expect(formatTime((d / 1000).toFixed(0))).toBe('7月13日17时54分')
8 | })
9 | it('test now', () => {
10 | expect(formatTime(+new Date() - 1)).toBe('刚刚')
11 | })
12 | it('less two minute', () => {
13 | expect(formatTime(+new Date() - 60 * 2 * 1000 + retrofit)).toBe('2分钟前')
14 | })
15 | it('less two hour', () => {
16 | expect(formatTime(+new Date() - 60 * 60 * 2 * 1000 + retrofit)).toBe('2小时前')
17 | })
18 | it('less one day', () => {
19 | expect(formatTime(+new Date() - 60 * 60 * 24 * 1 * 1000)).toBe('1天前')
20 | })
21 | it('more than one day', () => {
22 | expect(formatTime(d)).toBe('7月13日17时54分')
23 | })
24 | it('format', () => {
25 | expect(formatTime(d, '{y}-{m}-{d} {h}:{i}')).toBe('2018-07-13 17:54')
26 | expect(formatTime(d, '{y}-{m}-{d}')).toBe('2018-07-13')
27 | expect(formatTime(d, '{y}/{m}/{d} {h}-{i}')).toBe('2018/07/13 17-54')
28 | })
29 | })
30 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/people.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/views/error-log/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Please click the bug icon in the upper right corner
6 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
27 |
28 |
33 |
--------------------------------------------------------------------------------
/admin/src/router/modules/table.js:
--------------------------------------------------------------------------------
1 | /** When your routing table is too long, you can split it into small modules **/
2 |
3 | import Layout from '@/layout'
4 |
5 | const tableRouter = {
6 | path: '/table',
7 | component: Layout,
8 | redirect: '/table/complex-table',
9 | name: 'Table',
10 | meta: {
11 | title: 'Table',
12 | icon: 'table'
13 | },
14 | children: [
15 | {
16 | path: 'dynamic-table',
17 | component: () => import('@/views/table/dynamic-table/index'),
18 | name: 'DynamicTable',
19 | meta: { title: 'Dynamic Table' }
20 | },
21 | {
22 | path: 'drag-table',
23 | component: () => import('@/views/table/drag-table'),
24 | name: 'DragTable',
25 | meta: { title: 'Drag Table' }
26 | },
27 | {
28 | path: 'inline-edit-table',
29 | component: () => import('@/views/table/inline-edit-table'),
30 | name: 'InlineEditTable',
31 | meta: { title: 'Inline Edit' }
32 | },
33 | {
34 | path: 'complex-table',
35 | component: () => import('@/views/table/complex-table'),
36 | name: 'ComplexTable',
37 | meta: { title: 'Complex Table' }
38 | }
39 | ]
40 | }
41 | export default tableRouter
42 |
--------------------------------------------------------------------------------
/admin/src/views/qiniu/upload.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 将文件拖到此处,或点击上传
6 |
7 |
8 |
9 |
10 |
42 |
--------------------------------------------------------------------------------
/admin/src/views/excel/upload-excel.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
43 |
--------------------------------------------------------------------------------
/admin/src/views/components-demo/drag-select.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{ item }}
10 |
11 |
12 |
13 |
14 |
15 |
44 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/language.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/layout/components/AppMain.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
24 |
25 |
49 |
50 |
58 |
--------------------------------------------------------------------------------
/admin/tests/unit/utils/validate.spec.js:
--------------------------------------------------------------------------------
1 | import { validUsername, validURL, validLowerCase, validUpperCase, validAlphabets } from '@/utils/validate.js'
2 | describe('Utils:validate', () => {
3 | it('validUsername', () => {
4 | expect(validUsername('admin')).toBe(true)
5 | expect(validUsername('editor')).toBe(true)
6 | expect(validUsername('xxxx')).toBe(false)
7 | })
8 | it('validURL', () => {
9 | expect(validURL('https://github.com/PanJiaChen/vue-element-admin')).toBe(true)
10 | expect(validURL('http://github.com/PanJiaChen/vue-element-admin')).toBe(true)
11 | expect(validURL('github.com/PanJiaChen/vue-element-admin')).toBe(false)
12 | })
13 | it('validLowerCase', () => {
14 | expect(validLowerCase('abc')).toBe(true)
15 | expect(validLowerCase('Abc')).toBe(false)
16 | expect(validLowerCase('123abc')).toBe(false)
17 | })
18 | it('validUpperCase', () => {
19 | expect(validUpperCase('ABC')).toBe(true)
20 | expect(validUpperCase('Abc')).toBe(false)
21 | expect(validUpperCase('123ABC')).toBe(false)
22 | })
23 | it('validAlphabets', () => {
24 | expect(validAlphabets('ABC')).toBe(true)
25 | expect(validAlphabets('Abc')).toBe(true)
26 | expect(validAlphabets('123aBC')).toBe(false)
27 | })
28 | })
29 |
--------------------------------------------------------------------------------
/server/generate/proto_makefile:
--------------------------------------------------------------------------------
1 | NAME := caoguo
2 |
3 | BUILDSHELLFILE :=`ls ../apidoc/proto/$(NAME)/*.proto | cut -d'/' -f5`
4 | COMMSHELLFILE :=`ls ../apidoc/proto/common/*.proto | cut -d'/' -f5`
5 |
6 | gen_proto: gen_build gen_base
7 | clean_proto:
8 | rm -f rpc/common/*.pb.go
9 | gen_build:# 自定义注册
10 | @mkdir -p rpc/$(NAME)
11 | @echo "gen_build proto"
12 | @rm -f rpc/$(NAME)/*.pb.go
13 | @rm -f rpc/$(NAME)/*.pb.gmsec.go
14 | @for file in $(BUILDSHELLFILE); do \
15 | echo build $$file; \
16 | protoc --proto_path="../apidoc/proto/" --gmsec_out=plugins=gmsec:./ $(NAME)/$$file; \
17 | done;
18 | @sed -i 's/,omitempty//g' ./rpc/$(NAME)/*.pb.go #开始取消json omitempty
19 | cp -rf ./rpc/$(NAME)/ ../rpc/ #子目录向父目录拷贝
20 | @sed -i 's#common "rpc/common"#common "$(NAME)/rpc/common"#g' ./rpc/$(NAME)/*.go #开始替换common包
21 |
22 | gen_base:# 基础库
23 | @mkdir -p ../rpc/common
24 | @echo "gen proto"
25 | @rm -f rpc/common/*.pb.go
26 | @rm -f rpc/common/*.pb.gmsec.go
27 | @for file in $(COMMSHELLFILE); do \
28 | echo base $$file; \
29 | protoc --proto_path="../apidoc/proto/" --gmsec_out=plugins=gmsec:../ common/$$file; \
30 | done;
31 | @sed -i 's/,omitempty//g' ../rpc/common/*.pb.go #开始取消json omitempty
32 | cp -rf ../rpc/common/ ./rpc/ #父目录向当前目录拷贝
33 |
34 |
35 |
--------------------------------------------------------------------------------
/admin/src/views/profile/components/Timeline.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ item.title }}
7 | {{ item.content }}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
44 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/eye-open.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/utils/open-window.js:
--------------------------------------------------------------------------------
1 | /**
2 | *Created by PanJiaChen on 16/11/29.
3 | * @param {Sting} url
4 | * @param {Sting} title
5 | * @param {Number} w
6 | * @param {Number} h
7 | */
8 | export default function openWindow(url, title, w, h) {
9 | // Fixes dual-screen position Most browsers Firefox
10 | const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left
11 | const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top
12 |
13 | const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width
14 | const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height
15 |
16 | const left = ((width / 2) - (w / 2)) + dualScreenLeft
17 | const top = ((height / 2) - (h / 2)) + dualScreenTop
18 | const newWindow = window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left)
19 |
20 | // Puts focus on the newWindow
21 | if (window.focus) {
22 | newWindow.focus()
23 | }
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/server/internal/service/file/file.go:
--------------------------------------------------------------------------------
1 | package file
2 |
3 | import (
4 | "caoguo/internal/config"
5 | "mime/multipart"
6 | "net/http"
7 |
8 | "github.com/xxjwxc/public/mylog"
9 |
10 | "github.com/xxjwxc/public/message"
11 |
12 | "github.com/xxjwxc/public/myfile"
13 |
14 | "github.com/gin-gonic/gin"
15 | )
16 |
17 | // Upload file deal
18 | type Upload struct {
19 | }
20 |
21 | // UploadMult 上传文件 多个
22 | // @Router /upload [post]
23 | func (u *Upload) UploadMult(c *gin.Context) {
24 | op := myfile.NewWebFile("file/image/", true)
25 | // Multipart form
26 | form, _ := c.MultipartForm()
27 | if form == nil {
28 | mylog.ErrorString("/upload is empty")
29 | msg := message.GetErrorMsg(message.ParameterInvalid)
30 | c.JSON(http.StatusBadRequest, msg)
31 | return
32 | }
33 |
34 | var files []*multipart.FileHeader
35 | for _, v := range form.File {
36 | files = append(files, v...)
37 | }
38 |
39 | //op := myfile.NewWebFile("file/image/", true)
40 | result := make([]string, 0, len(files))
41 | for _, file := range files {
42 | src, err := op.SaveOne(file)
43 | if err != nil {
44 | return
45 | }
46 | result = append(result, config.GetFileHost()+src)
47 | }
48 |
49 | msg := message.GetSuccessMsg()
50 | msg.Data = result
51 |
52 | c.JSON(http.StatusOK, msg)
53 | }
54 |
--------------------------------------------------------------------------------
/admin/src/views/guide/steps.js:
--------------------------------------------------------------------------------
1 | const steps = [
2 | {
3 | element: '#hamburger-container',
4 | popover: {
5 | title: 'Hamburger',
6 | description: 'Open && Close sidebar',
7 | position: 'bottom'
8 | }
9 | },
10 | {
11 | element: '#breadcrumb-container',
12 | popover: {
13 | title: 'Breadcrumb',
14 | description: 'Indicate the current page location',
15 | position: 'bottom'
16 | }
17 | },
18 | {
19 | element: '#header-search',
20 | popover: {
21 | title: 'Page Search',
22 | description: 'Page search, quick navigation',
23 | position: 'left'
24 | }
25 | },
26 | {
27 | element: '#screenfull',
28 | popover: {
29 | title: 'Screenfull',
30 | description: 'Set the page into fullscreen',
31 | position: 'left'
32 | }
33 | },
34 | {
35 | element: '#size-select',
36 | popover: {
37 | title: 'Switch Size',
38 | description: 'Switch the system size',
39 | position: 'left'
40 | }
41 | },
42 | {
43 | element: '#tags-view-container',
44 | popover: {
45 | title: 'Tags view',
46 | description: 'The history of the page you visited',
47 | position: 'bottom'
48 | },
49 | padding: 0
50 | }
51 | ]
52 |
53 | export default steps
54 |
--------------------------------------------------------------------------------
/admin/tests/unit/utils/parseTime.spec.js:
--------------------------------------------------------------------------------
1 | import { parseTime } from '@/utils/index.js'
2 |
3 | describe('Utils:parseTime', () => {
4 | const d = new Date('2018-07-13 17:54:01') // "2018-07-13 17:54:01"
5 | it('timestamp', () => {
6 | expect(parseTime(d)).toBe('2018-07-13 17:54:01')
7 | })
8 |
9 | it('timestamp string', () => {
10 | expect(parseTime((d + ''))).toBe('2018-07-13 17:54:01')
11 | })
12 |
13 | it('ten digits timestamp', () => {
14 | expect(parseTime((d / 1000).toFixed(0))).toBe('2018-07-13 17:54:01')
15 | })
16 | it('new Date', () => {
17 | expect(parseTime(new Date(d))).toBe('2018-07-13 17:54:01')
18 | })
19 | it('format', () => {
20 | expect(parseTime(d, '{y}-{m}-{d} {h}:{i}')).toBe('2018-07-13 17:54')
21 | expect(parseTime(d, '{y}-{m}-{d}')).toBe('2018-07-13')
22 | expect(parseTime(d, '{y}/{m}/{d} {h}-{i}')).toBe('2018/07/13 17-54')
23 | })
24 | it('get the day of the week', () => {
25 | expect(parseTime(d, '{a}')).toBe('五') // 星期五
26 | })
27 | it('get the day of the week', () => {
28 | expect(parseTime(+d + 1000 * 60 * 60 * 24 * 2, '{a}')).toBe('日') // 星期日
29 | })
30 | it('empty argument', () => {
31 | expect(parseTime()).toBeNull()
32 | })
33 |
34 | it('null', () => {
35 | expect(parseTime(null)).toBeNull()
36 | })
37 | })
38 |
--------------------------------------------------------------------------------
/admin/src/views/example/components/Dropdown/Platform.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Platfroms({{ platforms.length }})
5 |
6 |
7 |
8 |
9 |
10 | {{ item.name }}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
47 |
--------------------------------------------------------------------------------
/admin/mock/remote-search.js:
--------------------------------------------------------------------------------
1 | const Mock = require('mockjs')
2 |
3 | const NameList = []
4 | const count = 100
5 |
6 | for (let i = 0; i < count; i++) {
7 | NameList.push(Mock.mock({
8 | name: '@first'
9 | }))
10 | }
11 | NameList.push({ name: 'mock-Pan' })
12 |
13 | module.exports = [
14 | // username search
15 | {
16 | url: '/vue-element-admin/search/user',
17 | type: 'get',
18 | response: config => {
19 | const { name } = config.query
20 | const mockNameList = NameList.filter(item => {
21 | const lowerCaseName = item.name.toLowerCase()
22 | return !(name && lowerCaseName.indexOf(name.toLowerCase()) < 0)
23 | })
24 | return {
25 | code: 20000,
26 | data: { items: mockNameList }
27 | }
28 | }
29 | },
30 |
31 | // transaction list
32 | {
33 | url: '/vue-element-admin/transaction/list',
34 | type: 'get',
35 | response: _ => {
36 | return {
37 | code: 20000,
38 | data: {
39 | total: 20,
40 | 'items|20': [{
41 | order_no: '@guid()',
42 | timestamp: +Mock.Random.date('T'),
43 | username: '@name()',
44 | price: '@float(1000, 15000, 0, 2)',
45 | 'status|1': ['success', 'pending']
46 | }]
47 | }
48 | }
49 | }
50 | }
51 | ]
52 |
--------------------------------------------------------------------------------
/admin/src/components/Screenfull/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
50 |
51 |
61 |
--------------------------------------------------------------------------------
/server/internal/service/oplog/common.go:
--------------------------------------------------------------------------------
1 | package oplog
2 |
3 | import (
4 | "caoguo/internal/model"
5 | "time"
6 |
7 | "caoguo/internal/core"
8 |
9 | "github.com/xxjwxc/public/tools"
10 | )
11 |
12 | // AddOpLog 添加日志数据
13 | func AddOpLog(operator, receive, topic, bundle, pid, ipAddr string, num0 int, Attach0 string) bool {
14 | var info model.OpLogTbl
15 | info.Operator = operator
16 | info.Receive = receive
17 | info.CreateTime = time.Now()
18 | info.Topic = topic
19 | info.Bundle = bundle
20 | info.Pid = pid
21 | info.IPAddr = ipAddr
22 | info.Num0 = num0
23 | info.Attach0 = Attach0
24 |
25 | return OpLogBaseAdd(&info)
26 | }
27 |
28 | // OpLogBaseAdd 添加日志数据
29 | func OpLogBaseAdd(info *model.OpLogTbl) bool {
30 | info.CreateTime = time.Now() //默认时间
31 | core.Dao.GetDBw().Create(info)
32 | return true
33 | }
34 |
35 | // GetWxLog 1:收藏 2:点赞 3:订单 0:全部
36 | func GetWxLog(openID string, action int) (result []*Wx_user_log_view) {
37 | orm := core.Dao.GetDBw()
38 | if action == 0 { //全部
39 | orm.Where("open_id = ?", openID).Order("create_time desc").Find(&result)
40 | } else {
41 | orm.Where("open_id = ? and type = ?", openID, action).Order("create_time desc").Find(&result)
42 | }
43 | if len(result) > 0 {
44 | for _, v := range result {
45 | tools.JSONEncode(v.Pic_url_str, &v.Pic_url)
46 | }
47 | }
48 | return
49 | }
50 |
--------------------------------------------------------------------------------
/admin/mock/utils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param {string} url
3 | * @returns {Object}
4 | */
5 | function param2Obj(url) {
6 | const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
7 | if (!search) {
8 | return {}
9 | }
10 | const obj = {}
11 | const searchArr = search.split('&')
12 | searchArr.forEach(v => {
13 | const index = v.indexOf('=')
14 | if (index !== -1) {
15 | const name = v.substring(0, index)
16 | const val = v.substring(index + 1, v.length)
17 | obj[name] = val
18 | }
19 | })
20 | return obj
21 | }
22 |
23 | /**
24 | * This is just a simple version of deep copy
25 | * Has a lot of edge cases bug
26 | * If you want to use a perfect deep copy, use lodash's _.cloneDeep
27 | * @param {Object} source
28 | * @returns {Object}
29 | */
30 | function deepClone(source) {
31 | if (!source && typeof source !== 'object') {
32 | throw new Error('error arguments', 'deepClone')
33 | }
34 | const targetObj = source.constructor === Array ? [] : {}
35 | Object.keys(source).forEach(keys => {
36 | if (source[keys] && typeof source[keys] === 'object') {
37 | targetObj[keys] = deepClone(source[keys])
38 | } else {
39 | targetObj[keys] = source[keys]
40 | }
41 | })
42 | return targetObj
43 | }
44 |
45 | module.exports = {
46 | param2Obj,
47 | deepClone
48 | }
49 |
--------------------------------------------------------------------------------
/admin/src/directive/el-table/adaptive.js:
--------------------------------------------------------------------------------
1 | import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event'
2 |
3 | /**
4 | * How to use
5 | * ...
6 | * el-table height is must be set
7 | * bottomOffset: 30(default) // The height of the table from the bottom of the page.
8 | */
9 |
10 | const doResize = (el, binding, vnode) => {
11 | const { componentInstance: $table } = vnode
12 |
13 | const { value } = binding
14 |
15 | if (!$table.height) {
16 | throw new Error(`el-$table must set the height. Such as height='100px'`)
17 | }
18 | const bottomOffset = (value && value.bottomOffset) || 30
19 |
20 | if (!$table) return
21 |
22 | const height = window.innerHeight - el.getBoundingClientRect().top - bottomOffset
23 | $table.layout.setHeight(height)
24 | $table.doLayout()
25 | }
26 |
27 | export default {
28 | bind(el, binding, vnode) {
29 | el.resizeListener = () => {
30 | doResize(el, binding, vnode)
31 | }
32 | // parameter 1 is must be "Element" type
33 | addResizeListener(window.document.body, el.resizeListener)
34 | },
35 | inserted(el, binding, vnode) {
36 | doResize(el, binding, vnode)
37 | },
38 | unbind(el) {
39 | removeResizeListener(window.document.body, el.resizeListener)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/admin/src/components/Hamburger/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
16 |
32 |
33 |
45 |
--------------------------------------------------------------------------------
/server/internal/service/weixin/def.go:
--------------------------------------------------------------------------------
1 | package weixin
2 |
3 | const (
4 | cacheSessionkey = "session_key"
5 | cacheWxUser = "wx_user_cache"
6 | )
7 |
8 | // OauthReq 微信授权请求信息
9 | type OauthReq struct {
10 | Jscode string `json:"jscode" binding:"required"` // 微信端jscode
11 | }
12 |
13 | // OauthResp 微信授权返回信息
14 | type OauthResp struct {
15 | SessionID string `json:"session_id"` // 用户sessionid 用于当前交互使用
16 | OpenID string `json:"open_id"` // openid
17 | OverdueTime int64 `json:"overdue_time"` // 逾期时间点(时间戳)
18 | }
19 |
20 | // WxSessionKey ...
21 | type WxSessionKey struct {
22 | Openid string `json:"openid"`
23 | SessionKey string `json:"session_key"`
24 | Unionid string `json:"unionid"`
25 | }
26 |
27 | // BaseSessionID 基础类型(sessionid)
28 | type BaseSessionID struct {
29 | SessionID string `json:"session_id" binding:"required"`
30 | }
31 |
32 | // WxUserinfo 用户信息
33 | type WxUserinfo struct {
34 | NickName string `json:"nickName"` //用户昵称
35 | AvatarURL string `json:"avatarUrl"` //用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
36 | Gender int `json:"gender"` //用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
37 | City string `json:"city"` //用户所在城市
38 | Province string `json:"province"` //用户所在省份
39 | Country string `json:"country"` //用户所在国家
40 | Language string `json:"language"` //用户的语言,简体中文为zh_CN
41 | }
42 |
--------------------------------------------------------------------------------
/uniapp/commcn/pages/money/paySuccess.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 支付成功
5 |
6 |
7 | 查看订单
8 | 返回首页
9 |
10 |
11 |
12 |
13 |
25 |
26 |
63 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/404.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/server/internal/service/login/def.go:
--------------------------------------------------------------------------------
1 | package login
2 |
3 | import (
4 | "github.com/xxjwxc/public/message"
5 | )
6 |
7 | // LoginReq 登陆请求
8 | type LoginReq struct {
9 | UserName string `json:"username" binding:"required"` // 用户名
10 | Password string `json:"password" binding:"required"` // 密码(用户输入的md5值,大写)
11 | }
12 |
13 | // RefreshReq reflashToken
14 | type RefreshReq struct {
15 | Token string `json:"refresh_token"` // token
16 | }
17 |
18 | type ReqChangepwd struct {
19 | AccessToken string `json:"access_token"` //access_token
20 | UserName string `json:"username"` //用户名
21 | Password string `json:"password"` //新密码
22 | }
23 |
24 | // LoginTokenMsg ...
25 | type LoginTokenMsg struct {
26 | message.MessageBody
27 | Data *LoginToken `json:"data,omitempty"`
28 | }
29 |
30 | // LoginToken ...
31 | type LoginToken struct {
32 | AccessToken string `json:"access_token,omitempty"` //access_token
33 | ExpireTime string `json:"expire_time,omitempty"` //
34 | RefreshToken string `json:"refresh_token,omitempty"` //
35 | }
36 |
37 | //
38 | // type Req_doaction struct {
39 | // mysign.Sing_head
40 | // UserName string `json:"username"` //用户名
41 | // Password string `json:"password"` //密码
42 | // Verify string `json:"verify,omitempty"` //验证码
43 | // Flag int `json:"flag,omitempty"` //1:注册,2:修改密码
44 | // Bundleid string `json:"bundleid,omitempty"` //bundleid
45 | // }
46 |
--------------------------------------------------------------------------------
/admin/plop-templates/view/prompt.js:
--------------------------------------------------------------------------------
1 | const { notEmpty } = require('../utils.js')
2 |
3 | module.exports = {
4 | description: 'generate a view',
5 | prompts: [{
6 | type: 'input',
7 | name: 'name',
8 | message: 'view name please',
9 | validate: notEmpty('name')
10 | },
11 | {
12 | type: 'checkbox',
13 | name: 'blocks',
14 | message: 'Blocks:',
15 | choices: [{
16 | name: '',
17 | value: 'template',
18 | checked: true
19 | },
20 | {
21 | name: '
51 |
--------------------------------------------------------------------------------
/admin/plop-templates/component/prompt.js:
--------------------------------------------------------------------------------
1 | const { notEmpty } = require('../utils.js')
2 |
3 | module.exports = {
4 | description: 'generate vue component',
5 | prompts: [{
6 | type: 'input',
7 | name: 'name',
8 | message: 'component name please',
9 | validate: notEmpty('name')
10 | },
11 | {
12 | type: 'checkbox',
13 | name: 'blocks',
14 | message: 'Blocks:',
15 | choices: [{
16 | name: '',
17 | value: 'template',
18 | checked: true
19 | },
20 | {
21 | name: '
56 |
--------------------------------------------------------------------------------
/server/internal/service/product/def.go:
--------------------------------------------------------------------------------
1 | package product
2 |
3 | // PContext 商品内容字段
4 | type PContext struct {
5 | Type int `json:"type"` // 类型,1:文字,2:图片,3:视频
6 | Context string `json:"context"` // 内容
7 | }
8 |
9 | // AddReq ...
10 | type AddReq struct {
11 | Name string `json:"name" binding:"required"` // 商品名
12 | GType string `json:"type" binding:"required"` // 商品类型
13 | Price int64 `json:"price" binding:"required"` // 商品价格(分)
14 | Qty int64 `json:"qty"` // 商品数量
15 | Contexts []PContext `json:"contexts"` // 商品详情
16 | Image []string `json:"imgs"` // 轮播图(图片,或者视频都可以)
17 | Icon string `json:"icon"` // 商品图标
18 | // MaxBuyQty int `json:"max_buy_qty"` // 最大购买数量
19 | }
20 |
21 | // SkuInfo sku 信息
22 | type SkuInfo struct {
23 | TypeName string `json:"type_name" binding:"required"` // 标签类型
24 | TagName string `json:"tag_name" binding:"required"` // 标签名字
25 | Premium int64 `json:"premium" binding:"required"` // 溢价值
26 | }
27 |
28 | // AddSkuReq sku
29 | type AddSkuReq struct {
30 | Gpid string `json:"gpid" binding:"required"` // 商品gpid
31 | Skus []SkuInfo `json:"skus" binding:"required"` // 商品sku信息
32 | }
33 |
34 | // UpdateSelectReq 更新推荐
35 | type UpdateSelectReq struct {
36 | Gpid string `json:"gpid" binding:"required"` // 商品gpid
37 | IsSelect bool `json:"isSelect" binding:"required"` // 是否推荐
38 | }
39 |
40 | type ReqGetContext struct {
41 | }
42 |
43 | const (
44 | _ProductPageLen = 10 // 一次最大请求
45 | )
46 |
--------------------------------------------------------------------------------
/uniapp/commcn/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import store from './store'
3 | import App from './App'
4 |
5 | import User from './utils/server/oauth'
6 | import Server from './utils/server/def'
7 | import Product from './utils/server/product'
8 | import Order from './utils/server/order'
9 | import Admin from './utils/server/admin'
10 |
11 | /**
12 | * 因工具函数属于公司资产, 所以直接在Vue实例挂载几个常用的函数
13 | * 所有测试用数据均存放于根目录json.js
14 | *
15 | * css部分使用了App.vue下的全局样式和iconfont图标,有需要图标库的可以留言。
16 | * 示例使用了uni.scss下的变量, 除变量外已尽量移除特有语法,可直接替换为其他预处理器使用
17 | */
18 | const msg = (title, duration=1500, mask=false, icon='none')=>{
19 | //统一提示方便全局修改
20 | if(Boolean(title) === false){
21 | return;
22 | }
23 | uni.showToast({
24 | title,
25 | duration,
26 | mask,
27 | icon
28 | });
29 | }
30 | const json = type=>{
31 | //模拟异步请求数据
32 | return new Promise(resolve=>{
33 | setTimeout(()=>{
34 | resolve(Json[type]);
35 | }, 500)
36 | })
37 | }
38 |
39 | const prePage = ()=>{
40 | let pages = getCurrentPages();
41 | let prePage = pages[pages.length - 2];
42 | // #ifdef H5
43 | return prePage;
44 | // #endif
45 | return prePage.$vm;
46 | }
47 |
48 |
49 | Vue.config.productionTip = false
50 | Vue.prototype.$fire = new Vue();
51 | Vue.prototype.$store = store;
52 | Vue.prototype.$api = {msg, json, prePage};
53 | Vue.prototype.$User = User;
54 | Vue.prototype.$Server = Server;
55 | Vue.prototype.$Product = Product;
56 | Vue.prototype.$Order = Order;
57 | Vue.prototype.$Admin = Admin;
58 |
59 | App.mpType = 'app'
60 |
61 | const app = new Vue({
62 | ...App
63 | })
64 | app.$mount()
--------------------------------------------------------------------------------
/server/docs/markdown/Login.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## [推荐查看工具](https://www.iminho.me/)
4 |
5 | ## 总览:
6 | - [Login]
7 | - [Waiting to write...]
8 |
9 | --------------------
10 |
11 | ### Login
12 |
13 | #### 简要描述:
14 |
15 | - [登录]
16 |
17 | #### 请求URL:
18 |
19 | - http://localhost:9001/commcn/api/v1/login/login
20 |
21 | #### 请求方式:
22 |
23 | - POST
24 |
25 | #### 请求参数:
26 |
27 | - ` LoginReq ` : 登陆请求
28 |
29 | |参数名|是否必须|类型|说明|
30 | |:---- |:---|:----- |----- |
31 | |`username` | `是`|string|用户名 |
32 | |`password` | `是`|string|密码(用户输入的md5值,大写) |
33 |
34 |
35 | #### 请求示例:
36 | ```
37 | {
38 | "password": "",
39 | "username": ""
40 | }
41 | ```
42 |
43 | #### 返回参数说明:
44 |
45 |
46 | #### 返回示例:
47 |
48 | ```
49 | {}
50 | ```
51 |
52 | #### 备注:
53 |
54 | - 登录
55 |
56 | --------------------
57 |
58 | ### RefreshToken
59 |
60 | #### 简要描述:
61 |
62 | - [刷新token管理员]
63 |
64 | #### 请求URL:
65 |
66 | - http://localhost:9001/commcn/api/v1/login.refresh_token
67 |
68 | #### 请求方式:
69 |
70 | - post
71 |
72 | #### 请求参数:
73 |
74 | - ` RefreshReq ` : reflashToken
75 |
76 | |参数名|是否必须|类型|说明|
77 | |:---- |:---|:----- |----- |
78 | |`refresh_token` | 否|string|token |
79 |
80 |
81 | #### 请求示例:
82 | ```
83 | {
84 | "refresh_token": ""
85 | }
86 | ```
87 |
88 | #### 返回参数说明:
89 |
90 |
91 | #### 返回示例:
92 |
93 | ```
94 | {}
95 | ```
96 |
97 | #### 备注:
98 |
99 | - 刷新token管理员
100 |
101 |
102 | --------------------
103 | --------------------
104 |
105 | #### 自定义类型:
106 |
107 |
108 |
--------------------------------------------------------------------------------
/admin/src/components/SvgIcon/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
47 |
48 |
63 |
--------------------------------------------------------------------------------
/admin/plop-templates/store/prompt.js:
--------------------------------------------------------------------------------
1 | const { notEmpty } = require('../utils.js')
2 |
3 | module.exports = {
4 | description: 'generate store',
5 | prompts: [{
6 | type: 'input',
7 | name: 'name',
8 | message: 'store name please',
9 | validate: notEmpty('name')
10 | },
11 | {
12 | type: 'checkbox',
13 | name: 'blocks',
14 | message: 'Blocks:',
15 | choices: [{
16 | name: 'state',
17 | value: 'state',
18 | checked: true
19 | },
20 | {
21 | name: 'mutations',
22 | value: 'mutations',
23 | checked: true
24 | },
25 | {
26 | name: 'actions',
27 | value: 'actions',
28 | checked: true
29 | }
30 | ],
31 | validate(value) {
32 | if (!value.includes('state') || !value.includes('mutations')) {
33 | return 'store require at least state and mutations'
34 | }
35 | return true
36 | }
37 | }
38 | ],
39 | actions(data) {
40 | const name = '{{name}}'
41 | const { blocks } = data
42 | const options = ['state', 'mutations']
43 | const joinFlag = `,
44 | `
45 | if (blocks.length === 3) {
46 | options.push('actions')
47 | }
48 |
49 | const actions = [{
50 | type: 'add',
51 | path: `src/store/modules/${name}.js`,
52 | templateFile: 'plop-templates/store/index.hbs',
53 | data: {
54 | options: options.join(joinFlag),
55 | state: blocks.includes('state'),
56 | mutations: blocks.includes('mutations'),
57 | actions: blocks.includes('actions')
58 | }
59 | }]
60 | return actions
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/apidoc/proto/caoguo/weixin.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3"; // 指定proto版本
2 |
3 | package weixin; // 指定包名
4 |
5 | // import "google/protobuf/descriptor.proto";
6 |
7 | option go_package = "rpc/caoguo/weixin"; // 指定路径
8 |
9 |
10 | // extend google.protobuf.FieldOptions {
11 | // string default_string = 50000;
12 | // int32 default_int = 50001;
13 | // }
14 |
15 | // 微信相关服务
16 | service Hello {
17 | // Oauth 微信授权获取登录信息
18 | rpc Oauth(OauthReq) returns (OauthResp) {}
19 |
20 | rpc UpdateUserInfo(WxUserinfo) returns (WxUserinfoResp) {}
21 | //
22 | }
23 |
24 |
25 | // OauthReq 请求结构
26 | message OauthReq {
27 | string jscode = 1; // 微信端jscode
28 | }
29 |
30 | // OauthResp 微信授权返回信息
31 | message OauthResp {
32 | string sessionID = 1 ; // 用户sessionid 用于当前交互使用
33 | int64 overdueTime = 2; // 逾期时间点(时间戳)
34 | }
35 |
36 | // WxUserinfo 用户信息
37 | message WxUserinfo {
38 | string sessionID = 1; // 用户sessionid 用于当前交互使用
39 | string nickName = 2; //用户昵称
40 | string avatarURL = 3; //用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空。若用户更换头像,原有头像URL将失效。
41 | string gender = 4; //用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
42 | string city = 5; //用户所在城市
43 | string province = 6; //用户所在省份
44 | string country = 7; //用户所在国家
45 | string language = 8; //用户的语言,简体中文为zh_CN
46 | }
47 |
48 | // WxUserinfoResp 用户信息返回
49 | message WxUserinfoResp{
50 | bool b = 1;
51 | }
52 |
53 | // GetQrcodeResp 获取二维码
54 | message GetQrcodeReq{
55 | string page = 1;// 小程序页面头部
56 | string scene = 2;// 附带参数
57 | }
58 |
59 | // GetQrcodeResp 获取二维码
60 | message GetQrcodeResp{
61 | string url = 1;// 二维码图片地址
62 | }
--------------------------------------------------------------------------------
/admin/src/components/SizeSelect/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{
9 | item.label }}
10 |
11 |
12 |
13 |
14 |
15 |
58 |
--------------------------------------------------------------------------------
/admin/src/styles/mixin.scss:
--------------------------------------------------------------------------------
1 | @mixin clearfix {
2 | &:after {
3 | content: "";
4 | display: table;
5 | clear: both;
6 | }
7 | }
8 |
9 | @mixin scrollBar {
10 | &::-webkit-scrollbar-track-piece {
11 | background: #d3dce6;
12 | }
13 |
14 | &::-webkit-scrollbar {
15 | width: 6px;
16 | }
17 |
18 | &::-webkit-scrollbar-thumb {
19 | background: #99a9bf;
20 | border-radius: 20px;
21 | }
22 | }
23 |
24 | @mixin relative {
25 | position: relative;
26 | width: 100%;
27 | height: 100%;
28 | }
29 |
30 | @mixin pct($pct) {
31 | width: #{$pct};
32 | position: relative;
33 | margin: 0 auto;
34 | }
35 |
36 | @mixin triangle($width, $height, $color, $direction) {
37 | $width: $width/2;
38 | $color-border-style: $height solid $color;
39 | $transparent-border-style: $width solid transparent;
40 | height: 0;
41 | width: 0;
42 |
43 | @if $direction==up {
44 | border-bottom: $color-border-style;
45 | border-left: $transparent-border-style;
46 | border-right: $transparent-border-style;
47 | }
48 |
49 | @else if $direction==right {
50 | border-left: $color-border-style;
51 | border-top: $transparent-border-style;
52 | border-bottom: $transparent-border-style;
53 | }
54 |
55 | @else if $direction==down {
56 | border-top: $color-border-style;
57 | border-left: $transparent-border-style;
58 | border-right: $transparent-border-style;
59 | }
60 |
61 | @else if $direction==left {
62 | border-right: $color-border-style;
63 | border-top: $transparent-border-style;
64 | border-bottom: $transparent-border-style;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/admin/src/views/clipboard/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | copy
8 |
9 |
10 |
11 |
12 |
13 | copy
14 |
15 |
16 |
17 |
18 |
19 |
20 |
49 |
50 |
--------------------------------------------------------------------------------
/server/internal/service/notify/def.go:
--------------------------------------------------------------------------------
1 | package notify
2 |
3 | const (
4 | body = `
5 |
6 |
7 |
8 |
9 |
10 | |
11 | 潞潮公社
12 | |
13 |
14 |
15 |
16 |
17 |
18 | 新下单提醒
19 |
20 | 订单号 : %v
21 | 商品列表:
22 | %v
23 | 请不要回复此邮件,谢谢!
24 | LUCHAO development center
25 | %v
26 |
27 | |
28 |
29 |
30 |
31 |
32 |
33 | `
34 | subject = "LUCHAO place order notify. %v"
35 | )
36 |
--------------------------------------------------------------------------------
/admin/src/layout/components/Sidebar/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
55 |
--------------------------------------------------------------------------------
/server/internal/service/notify/notify.go:
--------------------------------------------------------------------------------
1 | package notify
2 |
3 | import (
4 | "caoguo/internal/config"
5 | "caoguo/internal/core"
6 | "caoguo/internal/model"
7 | "fmt"
8 | "time"
9 |
10 | "github.com/xxjwxc/public/mylog"
11 |
12 | "github.com/xxjwxc/public/tools"
13 |
14 | "github.com/xxjwxc/public/myemail"
15 | )
16 |
17 | // NotifyEmail 邮件提醒
18 | func NotifyEmail(billId string) {
19 | orm := core.Dao.GetDBr()
20 | orders, _ := model.BillOrderTblMgr(orm.DB).GetFromBillID(billId)
21 |
22 | var gpids []string
23 | for _, v := range orders {
24 | gpids = append(gpids, v.Gpid)
25 | }
26 |
27 | mgr := model.ProductTblMgr(orm.DB)
28 | mgr.SetIsRelated(false) // 关闭外键查询
29 | products, _ := mgr.GetBatchFromGpid(gpids)
30 |
31 | mpname := make(map[string]string)
32 | for _, v := range products {
33 | mpname[v.Gpid] = v.PlatformID
34 | }
35 |
36 | mp := make(map[string][]*model.BillOrderTbl)
37 | for _, v := range orders {
38 | mp[mpname[v.Gpid]] = append(mp[mpname[v.Gpid]], v)
39 | }
40 |
41 | // 开始组织发送
42 | email := config.GetEmail()
43 | myemail := myemail.New(email.User, email.Password, email.Host, "LUCHAO")
44 | for k, v := range mp {
45 | to := getEmailList(k)
46 | if len(to) > 0 {
47 | var lplist string
48 | for _, v1 := range v {
49 | lplist += fmt.Sprintf("商品名:(%v),商品属性:(%v),数量:(%v)
", v1.Name, v1.SkuArrt, v1.Number)
50 | }
51 | b, _ := myemail.SendMail(to, fmt.Sprintf(subject, tools.GetUtcTime(time.Now())),
52 | fmt.Sprintf(body, billId, lplist, tools.GetTimeStr(time.Now())))
53 | if b {
54 | mylog.Infof("send email %v success.", to)
55 | }
56 | }
57 | }
58 | // -------------end
59 | }
60 |
--------------------------------------------------------------------------------
/admin/src/views/components-demo/json-editor.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 |
29 |
30 |
36 |
37 |
--------------------------------------------------------------------------------
/admin/src/components/Charts/mixins/resize.js:
--------------------------------------------------------------------------------
1 | import { debounce } from '@/utils'
2 |
3 | export default {
4 | data() {
5 | return {
6 | $_sidebarElm: null,
7 | $_resizeHandler: null
8 | }
9 | },
10 | mounted() {
11 | this.initListener()
12 | },
13 | activated() {
14 | if (!this.$_resizeHandler) {
15 | // avoid duplication init
16 | this.initListener()
17 | }
18 |
19 | // when keep-alive chart activated, auto resize
20 | this.resize()
21 | },
22 | beforeDestroy() {
23 | this.destroyListener()
24 | },
25 | deactivated() {
26 | this.destroyListener()
27 | },
28 | methods: {
29 | // use $_ for mixins properties
30 | // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
31 | $_sidebarResizeHandler(e) {
32 | if (e.propertyName === 'width') {
33 | this.$_resizeHandler()
34 | }
35 | },
36 | initListener() {
37 | this.$_resizeHandler = debounce(() => {
38 | this.resize()
39 | }, 100)
40 | window.addEventListener('resize', this.$_resizeHandler)
41 |
42 | this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
43 | this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
44 | },
45 | destroyListener() {
46 | window.removeEventListener('resize', this.$_resizeHandler)
47 | this.$_resizeHandler = null
48 |
49 | this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
50 | },
51 | resize() {
52 | const { chart } = this
53 | chart && chart.resize()
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/pdf.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/components/DragSelect/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
50 |
51 |
66 |
--------------------------------------------------------------------------------
/admin/src/views/tab/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | mounted times :{{ createdTimes }}
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
52 |
53 |
58 |
--------------------------------------------------------------------------------
/admin/src/store/modules/permission.js:
--------------------------------------------------------------------------------
1 | import { asyncRoutes, constantRoutes } from '@/router'
2 |
3 | /**
4 | * Use meta.role to determine if the current user has permission
5 | * @param roles
6 | * @param route
7 | */
8 | function hasPermission(roles, route) {
9 | if (route.meta && route.meta.roles) {
10 | return roles.some(role => route.meta.roles.includes(role))
11 | } else {
12 | return true
13 | }
14 | }
15 |
16 | /**
17 | * Filter asynchronous routing tables by recursion
18 | * @param routes asyncRoutes
19 | * @param roles
20 | */
21 | export function filterAsyncRoutes(routes, roles) {
22 | const res = []
23 |
24 | routes.forEach(route => {
25 | const tmp = { ...route }
26 | if (hasPermission(roles, tmp)) {
27 | if (tmp.children) {
28 | tmp.children = filterAsyncRoutes(tmp.children, roles)
29 | }
30 | res.push(tmp)
31 | }
32 | })
33 |
34 | return res
35 | }
36 |
37 | const state = {
38 | routes: [],
39 | addRoutes: []
40 | }
41 |
42 | const mutations = {
43 | SET_ROUTES: (state, routes) => {
44 | state.addRoutes = routes
45 | state.routes = constantRoutes.concat(routes)
46 | }
47 | }
48 |
49 | const actions = {
50 | generateRoutes({ commit }, roles) {
51 | return new Promise(resolve => {
52 | let accessedRoutes
53 | if (roles.includes('admin')) {
54 | accessedRoutes = asyncRoutes || []
55 | } else {
56 | accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
57 | }
58 | commit('SET_ROUTES', accessedRoutes)
59 | resolve(accessedRoutes)
60 | })
61 | }
62 | }
63 |
64 | export default {
65 | namespaced: true,
66 | state,
67 | mutations,
68 | actions
69 | }
70 |
--------------------------------------------------------------------------------
/server/internal/service/product/common.go:
--------------------------------------------------------------------------------
1 | package product
2 |
3 | import (
4 | "caoguo/internal/api"
5 | "caoguo/internal/core"
6 | "caoguo/internal/model"
7 | "caoguo/internal/service/weixin"
8 |
9 | "github.com/xxjwxc/public/mylog"
10 | "github.com/xxjwxc/public/tools"
11 | )
12 |
13 | // GetProductByGpids 通过gpid获取商品信息
14 | func GetProductByGpids(gpids []string) (map[string]*model.ProductTbl, error) {
15 | orm := core.Dao.GetDBr()
16 | pds, err := model.ProductTblMgr(orm.DB).GetBatchFromGpid(gpids)
17 | if err != nil {
18 | return nil, err
19 | }
20 |
21 | mp := make(map[string]*model.ProductTbl, len(pds))
22 | for _, v := range pds {
23 | mp[v.Gpid] = v
24 | }
25 |
26 | return mp, nil
27 | }
28 |
29 | // GetImages image output
30 | func GetImages(src string) []string {
31 | var out []string
32 | tools.JSONEncode(src, &out)
33 | return out
34 | }
35 |
36 | // GetContext 获取图文详情
37 | func GetContext(src string) (img []string, video []string) {
38 | var out []PContext
39 | tools.JSONEncode(src, &out)
40 | for _, v := range out {
41 | if v.Type == 2 { // 图片
42 | img = append(img, v.Context)
43 | } else if v.Type == 3 { // 视频
44 | video = append(video, v.Context)
45 | }
46 | }
47 |
48 | return
49 | }
50 |
51 | func getIsFavorite(c *api.Context, gpid string) bool {
52 | sessionID := c.GetSessionToken()
53 | mylog.Infof("sessionid:%v", sessionID)
54 | session := weixin.GetSessionkey(sessionID)
55 | if len(session.Openid) == 0 {
56 | return false
57 | }
58 |
59 | mgr := model.FavoriteTblMgr(core.Dao.GetDBw().DB)
60 | resp, err := mgr.FetchUniqueIndexByUserGpid(gpid, session.Openid)
61 | if err != nil { // 没找到
62 | return false
63 | }
64 |
65 | return (resp.ID > 0)
66 | }
67 |
--------------------------------------------------------------------------------
/admin/src/views/components-demo/drag-kanban.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
39 |
66 |
67 |
--------------------------------------------------------------------------------
/admin/mock/index.js:
--------------------------------------------------------------------------------
1 | const Mock = require('mockjs')
2 | const { param2Obj } = require('./utils')
3 |
4 | const user = require('./user')
5 | const role = require('./role')
6 | const article = require('./article')
7 | const search = require('./remote-search')
8 |
9 | const mocks = [
10 | ...user,
11 | ...role,
12 | ...article,
13 | ...search
14 | ]
15 |
16 | // for front mock
17 | // please use it cautiously, it will redefine XMLHttpRequest,
18 | // which will cause many of your third-party libraries to be invalidated(like progress event).
19 | function mockXHR() {
20 | // mock patch
21 | // https://github.com/nuysoft/Mock/issues/300
22 | Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
23 | Mock.XHR.prototype.send = function() {
24 | if (this.custom.xhr) {
25 | this.custom.xhr.withCredentials = this.withCredentials || false
26 |
27 | if (this.responseType) {
28 | this.custom.xhr.responseType = this.responseType
29 | }
30 | }
31 | this.proxy_send(...arguments)
32 | }
33 |
34 | function XHR2ExpressReqWrap(respond) {
35 | return function(options) {
36 | let result = null
37 | if (respond instanceof Function) {
38 | const { body, type, url } = options
39 | // https://expressjs.com/en/4x/api.html#req
40 | result = respond({
41 | method: type,
42 | body: JSON.parse(body),
43 | query: param2Obj(url)
44 | })
45 | } else {
46 | result = respond
47 | }
48 | return Mock.mock(result)
49 | }
50 | }
51 |
52 | for (const i of mocks) {
53 | Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
54 | }
55 | }
56 |
57 | module.exports = {
58 | mocks,
59 | mockXHR
60 | }
61 |
--------------------------------------------------------------------------------
/server/internal/service/history/common.go:
--------------------------------------------------------------------------------
1 | package history
2 |
3 | import (
4 | "fmt"
5 | "path"
6 | "strings"
7 | "sync"
8 |
9 | "github.com/xxjwxc/public/mysort"
10 |
11 | "github.com/xxjwxc/public/myleveldb"
12 | "github.com/xxjwxc/public/myqueue"
13 | "github.com/xxjwxc/public/tools"
14 | )
15 |
16 | var _que *myqueue.MyQueue
17 | var lv myleveldb.MyLevelDB
18 | var once sync.Once
19 |
20 | func myinit() {
21 | _que = myqueue.New()
22 | lv = (myleveldb.OnInitDB(path.Join(tools.GetCurrentDirectory(), "file/database/leveldb_history")))
23 |
24 | go onDeal() // 开始消费
25 | }
26 |
27 | func getLevelDB() *myleveldb.MyLevelDB {
28 | once.Do(myinit)
29 | return &lv
30 | }
31 |
32 | func onDeal() {
33 | leveldb := getLevelDB()
34 | // defer leveldb.OnDestoryDB()
35 |
36 | for {
37 | info := _que.Pop().(queInfo)
38 | var tmp []string
39 | leveldb.Get(info.UserID, &tmp)
40 | var sort mysort.Lifo
41 | for _, v := range tmp {
42 | sort.Add(v)
43 | }
44 | sort.PushGrab(fmt.Sprintf("%v@%v", info.Gpid, info.Icon))
45 |
46 | its := sort.Gets()
47 | items := make([]string, 0, len(its))
48 | for _, v := range its {
49 | items = append(items, v.(string))
50 | }
51 | if len(items) > 10 {
52 | items = items[:10]
53 | }
54 | leveldb.Add(info.UserID, items)
55 | }
56 | }
57 |
58 | // gets 获取
59 | func gets(userID string) (resp []queInfo) {
60 | leveldb := getLevelDB()
61 | // defer leveldb.OnDestoryDB()
62 | var items []string
63 | leveldb.Get(userID, &items)
64 | for _, v := range items {
65 | s := strings.Split(v, "@")
66 | if len(s) > 1 {
67 | resp = append(resp, queInfo{
68 | UserID: userID,
69 | Gpid: s[0],
70 | Icon: v[len(s[0])+1:],
71 | })
72 | }
73 | }
74 |
75 | return resp
76 | }
77 |
--------------------------------------------------------------------------------
/admin/src/views/components-demo/tinymce.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
30 |
31 |
36 |
37 |
--------------------------------------------------------------------------------
/admin/src/directive/clipboard/clipboard.js:
--------------------------------------------------------------------------------
1 | // Inspired by https://github.com/Inndy/vue-clipboard2
2 | const Clipboard = require('clipboard')
3 | if (!Clipboard) {
4 | throw new Error('you should npm install `clipboard` --save at first ')
5 | }
6 |
7 | export default {
8 | bind(el, binding) {
9 | if (binding.arg === 'success') {
10 | el._v_clipboard_success = binding.value
11 | } else if (binding.arg === 'error') {
12 | el._v_clipboard_error = binding.value
13 | } else {
14 | const clipboard = new Clipboard(el, {
15 | text() { return binding.value },
16 | action() { return binding.arg === 'cut' ? 'cut' : 'copy' }
17 | })
18 | clipboard.on('success', e => {
19 | const callback = el._v_clipboard_success
20 | callback && callback(e) // eslint-disable-line
21 | })
22 | clipboard.on('error', e => {
23 | const callback = el._v_clipboard_error
24 | callback && callback(e) // eslint-disable-line
25 | })
26 | el._v_clipboard = clipboard
27 | }
28 | },
29 | update(el, binding) {
30 | if (binding.arg === 'success') {
31 | el._v_clipboard_success = binding.value
32 | } else if (binding.arg === 'error') {
33 | el._v_clipboard_error = binding.value
34 | } else {
35 | el._v_clipboard.text = function() { return binding.value }
36 | el._v_clipboard.action = function() { return binding.arg === 'cut' ? 'cut' : 'copy' }
37 | }
38 | },
39 | unbind(el, binding) {
40 | if (binding.arg === 'success') {
41 | delete el._v_clipboard_success
42 | } else if (binding.arg === 'error') {
43 | delete el._v_clipboard_error
44 | } else {
45 | el._v_clipboard.destroy()
46 | delete el._v_clipboard
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/exit-fullscreen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/icons/svg/tree.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/admin/src/views/profile/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
69 |
--------------------------------------------------------------------------------
/admin/src/views/components-demo/split-pane.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
39 |
40 |
68 |
--------------------------------------------------------------------------------