├── src
├── lang
│ ├── shop
│ │ ├── zh.js
│ │ └── en.js
│ ├── product
│ │ ├── spu-detail
│ │ │ ├── zh.js
│ │ │ └── en.js
│ │ ├── attr
│ │ │ ├── en.js
│ │ │ └── zh.js
│ │ ├── spu
│ │ │ ├── zh.js
│ │ │ └── en.js
│ │ └── category
│ │ │ ├── zh.js
│ │ │ └── en.js
│ ├── biz
│ │ ├── area
│ │ │ ├── zh.js
│ │ │ └── en.js
│ │ └── imgbox
│ │ │ ├── zh.js
│ │ │ └── en.js
│ ├── multishop
│ │ ├── shop-user-account
│ │ │ ├── zh.js
│ │ │ └── en.js
│ │ ├── hot-search
│ │ │ ├── zh.js
│ │ │ └── en.js
│ │ ├── notice
│ │ │ ├── zh.js
│ │ │ └── en.js
│ │ └── shop-user
│ │ │ ├── zh.js
│ │ │ └── en.js
│ ├── rbac
│ │ ├── role
│ │ │ ├── zh.js
│ │ │ └── en.js
│ │ ├── menu-permission
│ │ │ ├── zh.js
│ │ │ └── en.js
│ │ └── menu
│ │ │ ├── en.js
│ │ │ └── zh.js
│ ├── address
│ │ ├── zh.js
│ │ └── en.js
│ ├── components
│ │ └── category-selector
│ │ │ ├── zh.js
│ │ │ └── en.js
│ ├── admin
│ │ ├── zh.js
│ │ └── en.js
│ ├── constant
│ │ ├── zh.js
│ │ └── en.js
│ ├── index.js
│ ├── zhCn.js
│ ├── en.js
│ └── order
│ │ └── order
│ │ └── zh.js
├── utils
│ ├── $t.js
│ ├── debounce.js
│ ├── auth.js
│ ├── i18n.js
│ ├── excelRequest.js
│ ├── datetime.js
│ ├── addr.js
│ └── website-config.js
├── assets
│ ├── images
│ │ ├── buyer.png
│ │ ├── car.png
│ │ ├── logo.png
│ │ ├── number.png
│ │ ├── login-bg.jpg
│ │ ├── login-img.jpg
│ │ └── password.png
│ ├── 401_images
│ │ └── 401.gif
│ └── 404_images
│ │ ├── 404.png
│ │ └── 404_cloud.png
├── stores
│ ├── index.js
│ └── modules
│ │ ├── cancel-focus-interval.js
│ │ ├── common.js
│ │ ├── app.js
│ │ ├── web-config.js
│ │ ├── permission.js
│ │ └── user.js
├── api
│ ├── delivery
│ │ ├── delivery-company.js
│ │ └── transport.js
│ ├── order
│ │ ├── order-refund.js
│ │ └── order.js
│ ├── auth
│ │ └── auth.js
│ ├── product
│ │ ├── brand.js
│ │ ├── spu.js
│ │ ├── attr.js
│ │ ├── spu-detail.js
│ │ ├── prod-info.js
│ │ ├── category.js
│ │ └── list.js
│ ├── multishop
│ │ ├── shop-user-account.js
│ │ ├── notice.js
│ │ ├── index-img.js
│ │ ├── hot-search.js
│ │ └── shop-user.js
│ ├── biz
│ │ ├── attach-file.js
│ │ └── oss.js
│ ├── system
│ │ └── addr-manage.js
│ └── rbac
│ │ ├── role.js
│ │ ├── menu-permission.js
│ │ └── menu.js
├── components
│ ├── icons-select
│ │ ├── svg-icons.js
│ │ ├── index.vue
│ │ └── element-icons.js
│ ├── tiny-mce
│ │ ├── plugins.js
│ │ ├── toolbar.js
│ │ ├── dynamicLoadScript.js
│ │ └── add-or-upload.vue
│ ├── Verifition
│ │ ├── utils
│ │ │ ├── ase.js
│ │ │ ├── axios.js
│ │ │ └── util.js
│ │ └── api
│ │ │ └── index.js
│ ├── product-details
│ │ └── index.vue
│ ├── picture-preview
│ │ └── index.vue
│ ├── Pagination
│ │ └── index.vue
│ ├── img-upload
│ │ └── index.vue
│ └── spu-category-attrs
│ │ └── index.vue
├── icons
│ ├── svg
│ │ ├── link.svg
│ │ ├── user.svg
│ │ ├── example.svg
│ │ ├── table.svg
│ │ ├── password.svg
│ │ ├── index-select.svg
│ │ ├── report.svg
│ │ ├── nested.svg
│ │ ├── order.svg
│ │ ├── index.svg
│ │ ├── distribution.svg
│ │ ├── live.svg
│ │ ├── group.svg
│ │ ├── eye.svg
│ │ ├── shop.svg
│ │ ├── analysis.svg
│ │ ├── icon-zhedie.svg
│ │ ├── language.svg
│ │ ├── promotion.svg
│ │ ├── product.svg
│ │ ├── eye-open.svg
│ │ ├── tree.svg
│ │ ├── dashboard.svg
│ │ └── form.svg
│ └── svg-icon.vue
├── App.vue
├── styles
│ ├── element-variables.scss
│ ├── variables.scss
│ ├── transition.scss
│ ├── mixin.scss
│ └── btn.scss
├── views
│ └── common
│ │ ├── redirect
│ │ └── index.vue
│ │ └── error-page
│ │ └── 401.vue
├── directive
│ ├── index.js
│ ├── rich
│ │ └── index.js
│ ├── cancelFocus
│ │ └── index.js
│ └── permission
│ │ └── index.js
├── layout
│ ├── components
│ │ ├── Sidebar
│ │ │ ├── Item.vue
│ │ │ └── main-sidebar-sub-menu.vue
│ │ └── AppMain.vue
│ └── index.vue
├── main.js
├── router
│ └── index.js
└── permission.js
├── public
├── favicon.ico
└── static
│ └── js
│ └── tinymce
│ └── js
│ └── tinymce
│ ├── langs
│ └── README.md
│ ├── skins
│ ├── ui
│ │ ├── oxide
│ │ │ ├── fonts
│ │ │ │ └── tinymce-mobile.woff
│ │ │ ├── content.mobile.min.css
│ │ │ └── skin.shadowdom.min.css
│ │ └── oxide-dark
│ │ │ ├── fonts
│ │ │ └── tinymce-mobile.woff
│ │ │ ├── content.mobile.min.css
│ │ │ └── skin.shadowdom.min.css
│ └── content
│ │ ├── default
│ │ └── content.min.css
│ │ ├── writer
│ │ └── content.min.css
│ │ ├── dark
│ │ └── content.min.css
│ │ └── document
│ │ └── content.min.css
│ └── plugins
│ ├── colorpicker
│ └── plugin.min.js
│ ├── contextmenu
│ └── plugin.min.js
│ ├── textcolor
│ └── plugin.min.js
│ ├── hr
│ └── plugin.min.js
│ ├── print
│ └── plugin.min.js
│ ├── code
│ └── plugin.min.js
│ ├── visualblocks
│ └── plugin.min.js
│ ├── nonbreaking
│ └── plugin.min.js
│ ├── pagebreak
│ └── plugin.min.js
│ ├── save
│ └── plugin.min.js
│ ├── noneditable
│ └── plugin.min.js
│ ├── tabfocus
│ └── plugin.min.js
│ ├── preview
│ └── plugin.min.js
│ ├── autoresize
│ └── plugin.min.js
│ ├── anchor
│ └── plugin.min.js
│ ├── autolink
│ └── plugin.min.js
│ ├── autosave
│ └── plugin.min.js
│ ├── legacyoutput
│ └── plugin.min.js
│ ├── insertdatetime
│ └── plugin.min.js
│ ├── bbcode
│ └── plugin.min.js
│ ├── toc
│ └── plugin.min.js
│ └── advlist
│ └── plugin.min.js
├── Dockerfile
├── doc
└── img
│ └── readme
│ ├── 商务二维码.png
│ ├── image-20210705143529597.png
│ ├── image-20231130112350296.png
│ └── image-20231130112429089.png
├── .npmrc
├── .editorconfig
├── .eslintignore
├── tsconfig.json
├── platform.conf
├── nginx.conf
├── .gitignore
├── .env.production
├── .env.development
├── index.html
├── package.json
├── .eslintrc.cjs
└── vite.config.js
/src/lang/shop/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | contactTel: '联系电话',
3 | phone: '电话'
4 | }
5 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/lang/product/spu-detail/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | spuId: '商品id',
3 | detail: '商品详情'
4 | }
5 |
--------------------------------------------------------------------------------
/src/utils/$t.js:
--------------------------------------------------------------------------------
1 | import { i18n } from '@/lang'
2 | const $t = i18n.global.t
3 | export default $t
4 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM nginx:1.20
2 | COPY ./dist /usr/share/nginx/html/dist
3 | COPY ./nginx.conf /etc/nginx/conf.d
--------------------------------------------------------------------------------
/src/lang/product/spu-detail/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | spuId: 'spu id',
3 | detail: 'detail'
4 | }
5 |
--------------------------------------------------------------------------------
/doc/img/readme/商务二维码.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/doc/img/readme/商务二维码.png
--------------------------------------------------------------------------------
/src/lang/shop/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | contactTel: 'Contact number',
3 | phone: 'Phone number'
4 | }
5 |
--------------------------------------------------------------------------------
/src/assets/images/buyer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/src/assets/images/buyer.png
--------------------------------------------------------------------------------
/src/assets/images/car.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/src/assets/images/car.png
--------------------------------------------------------------------------------
/src/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/src/assets/images/logo.png
--------------------------------------------------------------------------------
/src/assets/401_images/401.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/src/assets/401_images/401.gif
--------------------------------------------------------------------------------
/src/assets/404_images/404.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/src/assets/404_images/404.png
--------------------------------------------------------------------------------
/src/assets/images/number.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/src/assets/images/number.png
--------------------------------------------------------------------------------
/src/assets/images/login-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/src/assets/images/login-bg.jpg
--------------------------------------------------------------------------------
/src/assets/images/login-img.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/src/assets/images/login-img.jpg
--------------------------------------------------------------------------------
/src/assets/images/password.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/src/assets/images/password.png
--------------------------------------------------------------------------------
/src/assets/404_images/404_cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/src/assets/404_images/404_cloud.png
--------------------------------------------------------------------------------
/src/lang/biz/area/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | areaId: '',
3 | areaName: '地址',
4 | parentId: '上级地址',
5 | level: '等级(从1开始)'
6 | }
7 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict = true
2 | shamefully-hoist = true
3 | strict-peer-dependencies = false
4 | registry = https://registry.npmmirror.com
5 |
--------------------------------------------------------------------------------
/doc/img/readme/image-20210705143529597.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/doc/img/readme/image-20210705143529597.png
--------------------------------------------------------------------------------
/doc/img/readme/image-20231130112350296.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/doc/img/readme/image-20231130112350296.png
--------------------------------------------------------------------------------
/doc/img/readme/image-20231130112429089.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/doc/img/readme/image-20231130112429089.png
--------------------------------------------------------------------------------
/src/lang/biz/area/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | areaId: 'area id',
3 | areaName: 'area name',
4 | parentId: 'parent id',
5 | level: 'level'
6 | }
7 |
--------------------------------------------------------------------------------
/src/lang/multishop/shop-user-account/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | email: '邮箱',
3 | phone: '手机号',
4 | username: '用户名',
5 | password: '密码',
6 | status: '状态'
7 | }
8 |
--------------------------------------------------------------------------------
/src/lang/product/attr/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | attrId: 'attr id',
3 | name: 'name',
4 | desc: 'desc',
5 | searchType: 'search type',
6 | attrType: 'attr type'
7 | }
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 | [*]
3 | charset = utf-8
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | insert_final_newline = true
8 | trim_trailing_whitespace = true
9 |
--------------------------------------------------------------------------------
/src/lang/multishop/shop-user-account/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | email: 'email',
3 | phone: 'phone',
4 | username: 'username',
5 | password: 'password',
6 | status: 'status'
7 | }
8 |
--------------------------------------------------------------------------------
/src/lang/product/attr/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | attrId: 'attr id',
3 | name: '属性名称',
4 | desc: '属性描述',
5 | searchType: '是否搜索',
6 | attrType: '属性类型',
7 | attrValue: '属性值'
8 | }
9 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | /build/
2 | /config/
3 | /dist/
4 | /*.js
5 | /src/components/verifition
6 | /test/unit/coverage/
7 | /src/icons/iconfont.js
8 | /components.d.ts
9 | /src/auto-import
10 |
--------------------------------------------------------------------------------
/src/stores/index.js:
--------------------------------------------------------------------------------
1 | import { createPinia } from 'pinia'
2 | const store = createPinia()
3 | // 全局注册 store
4 | export function setupStore (app) {
5 | app.use(store)
6 | }
7 |
8 | export { store }
9 |
--------------------------------------------------------------------------------
/src/lang/rbac/role/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | roleId: '角色id',
3 | roleName: '角色名称',
4 | remark: '备注',
5 | createUserId: '创建者ID',
6 | bizType: '业务类型 0平台菜单 1 店铺菜单',
7 | tenantId: '所属租户'
8 | }
9 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/langs/README.md:
--------------------------------------------------------------------------------
1 | This is where language files should be placed.
2 |
3 | Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/
4 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/public/static/js/tinymce/js/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff
--------------------------------------------------------------------------------
/src/lang/rbac/role/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | roleId: 'role id',
3 | roleName: 'role name',
4 | remark: 'remark',
5 | createUserId: 'create user id',
6 | bizType: 'biz type',
7 | tenantId: 'tenant id'
8 | }
9 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/skins/ui/oxide-dark/fonts/tinymce-mobile.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gz-yami/mall4cloud-multishop/HEAD/public/static/js/tinymce/js/tinymce/skins/ui/oxide-dark/fonts/tinymce-mobile.woff
--------------------------------------------------------------------------------
/src/lang/multishop/hot-search/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | hotSearchId: '主键',
3 | shopId: '店铺ID',
4 | content: '热搜内容',
5 | createDate: '创建时间',
6 | seq: '顺序',
7 | status: '状态',
8 | title: '热搜标题'
9 | }
10 |
--------------------------------------------------------------------------------
/src/api/delivery/delivery-company.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function list () {
4 | return request({
5 | url: '/mall4cloud_delivery/m/delivery_company/list',
6 | method: 'get'
7 | })
8 | }
9 |
--------------------------------------------------------------------------------
/src/lang/multishop/notice/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | id: '公告id',
3 | shopId: '店铺id',
4 | title: '公告标题',
5 | content: '公告内容',
6 | type: '类型',
7 | status: '状态',
8 | isTop: '是否置顶',
9 | publishTime: '发布时间'
10 | }
11 |
--------------------------------------------------------------------------------
/src/lang/multishop/shop-user/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | shopUserId: '商家用户id',
3 | shopId: '关联店铺id',
4 | nickName: '昵称',
5 | avatar: '头像',
6 | code: '员工编号',
7 | phoneNum: '联系方式',
8 | hasAccount: '是否已经设置账号'
9 | }
10 |
--------------------------------------------------------------------------------
/src/components/icons-select/svg-icons.js:
--------------------------------------------------------------------------------
1 | const files = import.meta.glob('../../icons/svg/*.svg')
2 |
3 | const svgIcons = Object.keys(files).map((path) => {
4 | return path.match(/\/([^/]+)\.svg$/)[1]
5 | })
6 | export default svgIcons
7 |
--------------------------------------------------------------------------------
/src/lang/address/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | receiverTelephone: '公司座机',
3 | postalCode: '邮政编码',
4 | province: '省份',
5 | city: '城市',
6 | area: '区/县',
7 | detailed: '详细地址',
8 | addr: '地址',
9 | defaultAddr: '默认'
10 | }
11 |
--------------------------------------------------------------------------------
/src/lang/multishop/hot-search/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | hotSearchId: 'hot search id',
3 | shopId: 'shop id',
4 | content: 'content',
5 | createDate: 'create date',
6 | seq: 'seq',
7 | status: 'status',
8 | title: 'title'
9 | }
10 |
--------------------------------------------------------------------------------
/src/lang/multishop/notice/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | id: 'id',
3 | shopId: 'shop id',
4 | title: 'title',
5 | content: 'content',
6 | type: 'type',
7 | status: 'status',
8 | isTop: 'is top',
9 | publishTime: 'publish time'
10 | }
11 |
--------------------------------------------------------------------------------
/src/api/order/order-refund.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function page (pageParam) {
4 | return request({
5 | url: '/mall4cloud_order/m/order/refund/page',
6 | method: 'get',
7 | params: pageParam
8 | })
9 | }
10 |
--------------------------------------------------------------------------------
/src/lang/multishop/shop-user/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | shopUserId: 'shop user id',
3 | shopId: 'shop id',
4 | nickName: 'nick name',
5 | avatar: 'avatar',
6 | code: 'code',
7 | phoneNum: 'phone num',
8 | hasAccount: 'has account'
9 | }
10 |
--------------------------------------------------------------------------------
/src/lang/rbac/menu-permission/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | menuPermissionId: '菜单资源用户id',
3 | menuTitle: '资源关联菜单',
4 | bizType: '业务类型 0平台菜单 1 店铺菜单',
5 | permission: '权限对应的编码',
6 | name: '资源名称',
7 | uri: '资源对应服务器路径',
8 | method: '请求方法'
9 | }
10 |
--------------------------------------------------------------------------------
/src/lang/rbac/menu-permission/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | menuPermissionId: 'menu permission id',
3 | menuTitle: 'menu title',
4 | bizType: 'biz type',
5 | permission: 'permission',
6 | name: 'name',
7 | uri: 'uri',
8 | method: 'method'
9 | }
10 |
--------------------------------------------------------------------------------
/src/lang/components/category-selector/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | categorySelector: '分类选择器',
3 | chooseProdCateg: '选择商品分类',
4 | currCho: '你当前的选择是',
5 | isItAComtionPro: '是否为组合商品',
6 | generalMerchandise: '普通商品',
7 | combinationGoods: '组合商品',
8 | haveReadFol: '确认选择'
9 | }
10 |
--------------------------------------------------------------------------------
/src/lang/address/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | receiverTelephone: 'Receiver telephone',
3 | postalCode: 'Postal code',
4 | province: 'Province',
5 | city: 'City',
6 | area: 'Area',
7 | detailed: 'Detailed address',
8 | addr: 'Address',
9 | defaultAddr: 'Default addr'
10 | }
11 |
--------------------------------------------------------------------------------
/src/icons/svg/link.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/lang/admin/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | carouselImg: '轮播图片',
3 | recommImgSize: '建议图片尺寸为',
4 | carouselImgNoNull: '轮播图片不能为空',
5 | sortNONull: '排序值不能为空',
6 | weChatPay: '微信支付',
7 | aliPay: '支付宝支付',
8 | balancePay: '余额支付',
9 | add: '添加',
10 | remove: '移除',
11 | dollar: '元'
12 | }
13 |
--------------------------------------------------------------------------------
/src/lang/constant/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | noNull: '不能为空',
3 | product: '商品',
4 | shop: '店铺',
5 | contactName: '联系人',
6 | contactTel: '联系电话',
7 | consignee: '收货人',
8 | mobilePhone: '手机号码',
9 | deliveryAddr: '收货地址',
10 | name: '名称',
11 | dollar: '元',
12 | piece: '件',
13 | normal: '正常'
14 | }
15 |
--------------------------------------------------------------------------------
/src/lang/product/spu/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | spuId: 'spu id',
3 | brandId: '品牌ID',
4 | categoryId: '分类ID',
5 | name: 'spu名称',
6 | sellingPoint: '卖点',
7 | imgUrls: '商品介绍主图',
8 | priceFee: '售价',
9 | priceScale: '售价',
10 | marketPriceFee: '市场价',
11 | marketPriceScale: '市场价',
12 | status: '状态'
13 | }
14 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es5",
5 | "sourceMap": true,
6 | "skipLibCheck": true
7 | },
8 | "exclude": [
9 | "node_modules"
10 | ],
11 | "include": [
12 | "src/auto-import/components.d.ts",
13 | "src/auto-import/imports.d.ts"
14 | ]
15 | }
--------------------------------------------------------------------------------
/src/styles/element-variables.scss:
--------------------------------------------------------------------------------
1 | // element-plus
2 | :root {
3 | --el-color-primary: #155BD4;
4 | --el-color-primary-light-3: #447cdd;
5 | --el-menu-item-height: 40px !important;
6 | --el-menu-sub-item-height: 40px !important;
7 | --el-button-hover-link-text-color: #155BD4;
8 | --el-color-primary-light-5: #155BD4;
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/api/auth/auth.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function login (data) {
4 | return request({
5 | url: '/mall4cloud_auth/ua/login',
6 | method: 'post',
7 | data
8 | })
9 | }
10 |
11 | export function logout () {
12 | return request({
13 | url: '/mall4cloud_auth/login_out',
14 | method: 'post'
15 | })
16 | }
17 |
--------------------------------------------------------------------------------
/platform.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | server_name cloud-platform.mall4j.com;
4 |
5 | location / {
6 | root /usr/share/nginx/html/platform;
7 | }
8 |
9 | error_page 404 /404.html;
10 | location = /404-light.html {
11 | }
12 |
13 | error_page 500 502 503 504 /50x.html;
14 | location = /50x.html {
15 | }
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/src/views/common/redirect/index.vue:
--------------------------------------------------------------------------------
1 |
10 |
18 |
--------------------------------------------------------------------------------
/src/lang/components/category-selector/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | categorySelector: 'Category selector',
3 | chooseProdCateg: 'Select product category',
4 | currCho: 'Your current choice is',
5 | isItAComtionPro: 'Is it a combination product ',
6 | generalMerchandise: 'General Product',
7 | combinationGoods: 'Combined product',
8 | haveReadFol: 'Confirm selection'
9 | }
10 |
--------------------------------------------------------------------------------
/src/lang/constant/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | noNull: 'No null',
3 | product: 'Product',
4 | shop: 'Shop',
5 | contactName: 'Contact person',
6 | contactTel: 'Contact number',
7 | consignee: 'consignee',
8 | mobilePhone: 'Mobile phone',
9 | deliveryAddr: ' delivery address',
10 | name: 'Name',
11 | dollar: ' Dollar ',
12 | piece: 'Pieces',
13 | normal: 'Normal'
14 | }
15 |
--------------------------------------------------------------------------------
/src/lang/product/spu/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | spuId: 'spu id',
3 | brandId: 'brand id',
4 | categoryId: 'category id',
5 | name: 'name',
6 | sellingPoint: 'selling point',
7 | imgUrls: 'img urls',
8 | priceFee: 'price fee',
9 | priceScale: 'price scale',
10 | marketPriceFee: 'market price fee',
11 | marketPriceScale: 'market price scale',
12 | status: 'status'
13 | }
14 |
--------------------------------------------------------------------------------
/src/lang/admin/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | carouselImg: 'Carousel pictures',
3 | recommImgSize: 'Carousel pictures',
4 | carouselImgNoNull: 'Carousel picture cannot be empty',
5 | sortNONull: 'Sort value cannot be empty',
6 | weChatPay: 'WeChat Pay',
7 | aliPay: 'Pay with Ali-Pay',
8 | balancePay: 'Balance Pay',
9 | add: 'Add',
10 | remove: 'Remove',
11 | dollar: ' dollar '
12 | }
13 |
--------------------------------------------------------------------------------
/nginx.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | server_name cloud-platform.mall4j.com;
4 |
5 | location / {
6 | try_files $uri $uri/ /;
7 | root /usr/share/nginx/html/dist;
8 | }
9 |
10 | error_page 404 /404.html;
11 | location = /404-light.html {
12 | }
13 |
14 | error_page 500 502 503 504 /50x.html;
15 | location = /50x.html {
16 | }
17 | }
18 |
19 |
--------------------------------------------------------------------------------
/.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 | pnpm-lock.yaml
25 |
26 | /src/auto-import
27 |
--------------------------------------------------------------------------------
/.env.production:
--------------------------------------------------------------------------------
1 | # just a flag
2 | VITE_APP_ENV = 'production'
3 |
4 | # 环境变量必须以VITE_APP_为开头。如:VITE_APP_API、VITE_APP_TITLE
5 | # 你在代码中可以通过如下方式获取:
6 | # import.meta.env.VITE_APP_XXX
7 |
8 | # base api
9 | VITE_APP_BASE_API = 'http://192.168.1.80:8000'
10 |
11 | # 访问文件存储资源的url 对应阿里云的Bucket域名
12 | VITE_APP_RESOURCES_URL = 'http://192.168.1.80:9000/mall4cloud'
13 |
14 | # 文件上传类型 0.阿里云 1.minIo
15 | VITE_APP_RESOURCES_TYPE = '1'
16 |
--------------------------------------------------------------------------------
/.env.development:
--------------------------------------------------------------------------------
1 | # just a flag
2 | VITE_APP_ENV = 'development'
3 |
4 | # 环境变量必须以VITE_APP_为开头。如:VITE_APP_API、VITE_APP_TITLE
5 | # 你在代码中可以通过如下方式获取:
6 | # import.meta.env.VITE_APP_XXX
7 |
8 | # base api
9 | VITE_APP_BASE_API = 'http://192.168.1.80:8000'
10 |
11 | # 访问文件存储资源的url 对应阿里云的Bucket域名
12 | VITE_APP_RESOURCES_URL = 'http://192.168.1.80:9000/mall4cloud'
13 |
14 | # 文件上传类型 0.阿里云 1.minIo
15 | VITE_APP_RESOURCES_TYPE = '1'
16 |
--------------------------------------------------------------------------------
/src/utils/debounce.js:
--------------------------------------------------------------------------------
1 | // 防抖 防止表单重复提交
2 | export const Debounce = (fn, t) => {
3 | const delay = t || 1000
4 | let timer
5 | return function () {
6 | const args = arguments
7 | if (timer) {
8 | clearTimeout(timer)
9 | }
10 |
11 | const callNow = !timer
12 |
13 | timer = setTimeout(() => {
14 | timer = null
15 | }, delay)
16 |
17 | if (callNow) fn.apply(this, args)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/components/tiny-mce/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 = ['paste preview anchor autolink codesample emoticons image link lists media searchreplace table visualblocks wordcount pagebreak insertdatetime fullscreen code']
6 |
7 | export default plugins
8 |
--------------------------------------------------------------------------------
/src/directive/index.js:
--------------------------------------------------------------------------------
1 | import { checkPermission } from './permission'
2 | import { cancelFocus } from './cancelFocus'
3 | import { richDirective } from './rich'
4 |
5 | // 全局注册 directive
6 | export function setupDirective (app) {
7 | // v-permission 挂载到全局
8 | app.directive('permission', checkPermission)
9 | // v-cancel-focus 挂载到全局
10 | app.directive('cancelFocus', cancelFocus)
11 | app.directive('rich', richDirective)
12 | }
13 |
--------------------------------------------------------------------------------
/src/icons/svg/user.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/Verifition/utils/ase.js:
--------------------------------------------------------------------------------
1 | import CryptoJS from 'crypto-js'
2 | /**
3 | * @word 要加密的内容
4 | * @keyWord String 服务器随机返回的关键字
5 | * */
6 | export function aesEncrypt (word, keyWord = 'XwKsGlMcdPMEhR1B') {
7 | const key = CryptoJS.enc.Utf8.parse(keyWord)
8 | const srcs = CryptoJS.enc.Utf8.parse(word)
9 | const encrypted = CryptoJS.AES.encrypt(srcs, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 })
10 | return encrypted.toString()
11 | }
12 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/colorpicker/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("colorpicker",function(){})}();
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/contextmenu/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("contextmenu",function(){})}();
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/textcolor/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("textcolor",function(){})}();
--------------------------------------------------------------------------------
/src/lang/rbac/menu/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | menuId: 'menu id',
3 | parentId: 'parent id',
4 | bizType: 'biz type',
5 | permission: 'permission',
6 | path: 'path',
7 | component: 'component',
8 | redirect: 'redirect',
9 | alwaysShow: 'always show',
10 | hidden: 'hidden',
11 | name: 'name',
12 | title: 'title',
13 | icon: 'icon',
14 | noCache: 'no cache',
15 | breadcrumb: 'breadcrumb',
16 | affix: 'affix',
17 | activeMenu: 'active menu',
18 | seq: 'seq'
19 | }
20 |
--------------------------------------------------------------------------------
/src/icons/svg/example.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/tiny-mce/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 numlist link image preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen']
5 |
6 | export default toolbar
7 |
--------------------------------------------------------------------------------
/src/api/product/brand.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | // 获取平台品牌信息列表
4 | export function page (pageParam) {
5 | return request({
6 | url: '/mall4cloud_product/platform/brand/page',
7 | method: 'get',
8 | params: pageParam
9 | })
10 | }
11 |
12 | // 根据分类,获取品牌列表(发布商品请求品牌)
13 | export function getBrandByCategoryId (pageParam) {
14 | return request({
15 | url: '/mall4cloud_product/admin/brand/get_brand_by_category_id',
16 | method: 'get',
17 | params: pageParam
18 | })
19 | }
20 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/lang/product/category/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | categoryId: '分类ID',
3 | shopId: '店铺ID',
4 | parentId: '父分类ID',
5 | name: '分类名称',
6 | desc: '分类描述',
7 | path: '分类地址',
8 | status: '状态', // 1:enable, 0:disable, -1:deleted
9 | icon: '分类图标',
10 | imgUrl: '分类图片',
11 | level: '分类层级',
12 | seq: '排序',
13 | normal: '正常',
14 | offline: '下架',
15 | recommImgSize: '建议图片尺寸为',
16 | categoryParent: '上级分类',
17 | categoryNoNull: '分类名称不能为空',
18 | imageNoNull: '图片不能为空',
19 | enterCateName: '请输入分类名称'
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/utils/auth.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
3 | *
4 | * https://www.mall4j.com/
5 | *
6 | * 未经允许,不可做商业用途!
7 | *
8 | * 版权所有,侵权必究!
9 | */
10 | import Cookies from 'vue-cookies'
11 |
12 | const TokenKey = 'Luck-platform-Token'
13 |
14 | export function getToken () {
15 | return Cookies.get(TokenKey)
16 | }
17 |
18 | export function setToken (token) {
19 | return Cookies.set(TokenKey, token, { sameSite: 'Lax' })
20 | }
21 |
22 | export function removeToken () {
23 | return Cookies.remove(TokenKey)
24 | }
25 |
--------------------------------------------------------------------------------
/src/utils/i18n.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
3 | *
4 | * https://www.mall4j.com/
5 | *
6 | * 未经允许,不可做商业用途!
7 | *
8 | * 版权所有,侵权必究!
9 | */
10 |
11 | import { i18n } from '@/lang'
12 |
13 | // translate router.meta.title, be used in breadcrumb sidebar tagsview
14 | export function generateTitle (title) {
15 | const hasKey = i18n.global.te('route.' + title)
16 | if (hasKey) {
17 | // $t :this method from vue-i18n, inject in @/lang/index.js
18 | return $t('route.' + title)
19 | }
20 | return title
21 | }
22 |
--------------------------------------------------------------------------------
/src/components/Verifition/api/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 此处可直接引用自己项目封装好的 axios 配合后端联调
3 | */
4 |
5 | import request from './../utils/axios' // 组件内部封装的axios
6 | // import request from "@/api/axios.js" //调用项目封装的axios
7 |
8 | // 获取验证图片 以及token
9 | export function reqGet (data) {
10 | return request({
11 | url: '/mall4cloud_auth/ua/captcha/get',
12 | method: 'post',
13 | data
14 | })
15 | }
16 |
17 | // 滑动或者点选验证
18 | export function reqCheck (data) {
19 | return request({
20 | url: '/mall4cloud_auth/ua/captcha/check',
21 | method: 'post',
22 | data
23 | })
24 | }
25 |
--------------------------------------------------------------------------------
/src/icons/svg/table.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/lang/product/category/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | categoryId: 'category id',
3 | shopId: 'shop id',
4 | parentId: 'parent id',
5 | name: 'name',
6 | desc: 'desc',
7 | path: 'path',
8 | status: 'status',
9 | icon: 'icon',
10 | imgUrl: 'img url',
11 | level: 'level',
12 | seq: 'seq',
13 | normal: 'normal',
14 | offline: 'Off shelf',
15 | recommImgSize: 'Carousel pictures',
16 | categoryParent: 'Category parent',
17 | categoryNoNull: 'Category name cannot be empty',
18 | imageNoNull: 'Image cannot be empty',
19 | enterCateName: 'Please enter the category name'
20 | }
21 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/skins/ui/oxide/content.mobile.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | */
7 | .tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{background-color:green;display:inline-block;opacity:.5;position:absolute}body{-webkit-text-size-adjust:none}body img{max-width:96vw}body table img{max-width:95%}body{font-family:sans-serif}table{border-collapse:collapse}
8 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/skins/ui/oxide-dark/content.mobile.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | */
7 | .tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{background-color:green;display:inline-block;opacity:.5;position:absolute}body{-webkit-text-size-adjust:none}body img{max-width:96vw}body table img{max-width:95%}body{font-family:sans-serif}table{border-collapse:collapse}
8 |
--------------------------------------------------------------------------------
/src/icons/svg/password.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/api/multishop/shop-user-account.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function get (shopUserId) {
4 | return request({
5 | url: '/mall4cloud_multishop/shop_user/account',
6 | method: 'get',
7 | params: {
8 | shopUserId
9 | }
10 | })
11 | }
12 |
13 | export function save (data) {
14 | return request({
15 | url: '/mall4cloud_multishop/shop_user/account',
16 | method: 'post',
17 | data
18 | })
19 | }
20 |
21 | export function update (data) {
22 | return request({
23 | url: '/mall4cloud_multishop/shop_user/account',
24 | method: 'put',
25 | data
26 | })
27 | }
28 |
--------------------------------------------------------------------------------
/src/components/Verifition/utils/axios.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 |
3 | axios.defaults.baseURL = import.meta.env.VITE_APP_BASE_API
4 |
5 | const service = axios.create({
6 | timeout: 40000,
7 | headers: {
8 | 'X-Requested-With': 'XMLHttpRequest',
9 | 'Content-Type': 'application/json; charset=UTF-8'
10 | }
11 | })
12 | service.interceptors.request.use(
13 | config => {
14 | return config
15 | },
16 | error => {
17 | Promise.reject(error)
18 | }
19 | )
20 |
21 | // response interceptor
22 | service.interceptors.response.use(
23 | response => {
24 | return response.data
25 | }
26 | )
27 | export default service
28 |
--------------------------------------------------------------------------------
/src/layout/components/Sidebar/Item.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
9 |
10 |
14 | {{ title }}
15 |
16 |
17 |
31 |
36 |
--------------------------------------------------------------------------------
/src/lang/biz/imgbox/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | picManager: '图片管理器',
3 | choosePic: '选择图片',
4 | picName: '图片名称',
5 | query: '查询',
6 | uploadPic: '上传图片',
7 | selectLocalPic: '请选择本地图片上传:',
8 | confirmUpload: '确定上传',
9 | revisePicName: '修改图片名称与分组',
10 | oldName: '原名称',
11 | revName: '新名称',
12 | inputNewName: '请输入新的图片名称',
13 | superiorLimit: '可选择照片数量已达上限',
14 | onlyPictures: '只能上传图片,其他文件已清除',
15 | onlySupported: '仅支持',
16 | pic: '图片',
17 | notExceed: '大小不能超过',
18 | alreadyExist: '已有',
19 | soonUpload: '即将上传',
20 | unit: '张图片',
21 | upload: '上传',
22 | remainder: '还可以选择',
23 | maxSelect: '当前最多只能选择',
24 | requestError: '服务器打了个盹^_^',
25 | PicMaxQuantity: '图片最大数量为:'
26 | }
27 |
--------------------------------------------------------------------------------
/src/directive/rich/index.js:
--------------------------------------------------------------------------------
1 | import DOMPurify from 'dompurify'
2 | // 记录旧数据
3 | let oldInnerHTML = ''
4 |
5 | function setHTML (el, value) {
6 | let innerHTML = value
7 | innerHTML = DOMPurify.sanitize(innerHTML, { ADD_ATTR: ['target'] })
8 | el.innerHTML = innerHTML
9 | }
10 |
11 | export const richDirective = {
12 | mounted (el, binding) {
13 | if (binding.value) {
14 | setHTML(el, binding.value)
15 | }
16 | },
17 | updated (el, binding) {
18 | // 如果旧数据跟新数据一样 直接 return
19 | if (binding.value === oldInnerHTML && !binding.value) {
20 | return
21 | }
22 | oldInnerHTML = binding.value
23 | if (binding.value) {
24 | setHTML(el, binding.value)
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/icons/svg/index-select.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
15 |
--------------------------------------------------------------------------------
/src/directive/cancelFocus/index.js:
--------------------------------------------------------------------------------
1 | import { useCancelFocusIntervalStore } from '@/stores/modules/cancel-focus-interval.js'
2 |
3 | /**
4 | * 元素被点击后一段时间自动取消聚焦
5 | * 主要用于解决 element-ui 按钮点击后高亮显示不会复原问题
6 | * binding.value 设定几秒后取消,尽可能不低于1000,防止定时器内存占用过大(单位:毫秒)
7 | */
8 | export const cancelFocus = {
9 | mounted: (el, binding) => {
10 | const btnInterval = useCancelFocusIntervalStore()
11 | let time = binding.value
12 | if (time < 1000 || !time) time = 1500
13 | el.addEventListener('click', ($event) => {
14 | btnInterval.createInterval($event, time)
15 | })
16 | },
17 | beforeUnmount: (el) => {
18 | const btnInterval = useCancelFocusIntervalStore()
19 | btnInterval.clearInterval()
20 | el.removeEventListener('click', () => {})
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/icons/svg/report.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
16 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/hr/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("hr",function(n){var o,t;function e(){return t.execCommand("InsertHorizontalRule")}(o=n).addCommand("InsertHorizontalRule",function(){o.execCommand("mceInsertContent",!1,"
")}),(t=n).ui.registry.addButton("hr",{icon:"horizontal-rule",tooltip:"Horizontal line",onAction:e}),t.ui.registry.addMenuItem("hr",{icon:"horizontal-rule",text:"Horizontal line",onAction:e})})}();
--------------------------------------------------------------------------------
/src/directive/permission/index.js:
--------------------------------------------------------------------------------
1 | import { useUserStore } from '@/stores/modules/user'
2 |
3 | /**
4 | * 按钮权限
5 | */
6 | export const checkPermission = {
7 | mounted (el, binding) {
8 | const { roles, isAdmin } = useUserStore()
9 | if (isAdmin) {
10 | return true
11 | }
12 | // 「其他角色」按钮权限校验
13 | const { value } = binding
14 | if (value) {
15 | const requiredPerms = value // DOM绑定需要的按钮权限标识
16 | const hasPerm = roles?.some(perm => {
17 | return requiredPerms.includes(perm)
18 | })
19 |
20 | if (!hasPerm) {
21 | el.parentNode && el.parentNode.removeChild(el)
22 | }
23 | } else {
24 | throw new Error(
25 | "need perms! Like v-has-perm=\"['sys:user:add','sys:user:edit']\""
26 | )
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/icons/svg/nested.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/stores/modules/cancel-focus-interval.js:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia'
2 |
3 | /**
4 | * 为解决element-ui按钮点击后,聚焦不会自动消失问题,
5 | * 定义统一定时器进行清除聚焦操作
6 | */
7 | export const useCancelFocusIntervalStore = defineStore('cancelFocus', {
8 | state: () => {
9 | return {
10 | value: null
11 | }
12 | },
13 | actions: {
14 | clearInterval () {
15 | clearInterval(this.value)
16 | },
17 | createInterval ($event, time) {
18 | if (this.value) {
19 | clearInterval(this.value)
20 | this.value = null
21 | }
22 | this.value = setInterval(() => {
23 | let target = $event.target
24 | if (target.nodeName === 'SPAN') {
25 | target = $event.target.parentNode
26 | }
27 | target.blur()
28 | }, time)
29 | }
30 | }
31 | })
32 |
--------------------------------------------------------------------------------
/src/icons/svg/order.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
17 |
--------------------------------------------------------------------------------
/src/lang/rbac/menu/zh.js:
--------------------------------------------------------------------------------
1 | export default {
2 | menuId: '菜单id',
3 | parentId: '父菜单ID,一级菜单为0',
4 | bizType: '业务类型 0平台菜单 1 店铺菜单',
5 | permission: '权限,需要有哪个权限才能访问该菜单',
6 | path: '路径 就像uri',
7 | component: '组件如:1.layout/Layout 为布局,不会跳页面 2.views/components-demo/tinymce 跳转到该页面',
8 | redirect: '当设置 noRedirect 的时候该路由在面包屑导航中不可被点击',
9 | alwaysShow: '一直显示根路由',
10 | hidden: '当设置 true 的时候该路由不会在侧边栏出现 如401,login等页面,或者如一些编辑页面/edit/1',
11 | name: '设定路由的名字,一定要填写不然使用时会出现各种问题',
12 | title: '设置该路由在侧边栏和面包屑中展示的名字',
13 | icon: '设置该路由的图标,支持 svg-class,也支持 el-icon-x element-ui 的 icon',
14 | noCache: '如果设置为true,则不会被 缓存(默认 false)',
15 | breadcrumb: '如果设置为false,则不会在breadcrumb面包屑中显示(默认 true)',
16 | affix: '若果设置为true,它则会固定在tags-view中(默认 false)',
17 | activeMenu: '当路由设置了该属性,则会高亮相对应的侧边栏。',
18 | seq: '排序,越小越靠前'
19 | }
20 |
--------------------------------------------------------------------------------
/src/api/biz/attach-file.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | // 保存上传文件记录
4 | export function save (data) {
5 | return request({
6 | url: '/mall4cloud_biz/m/attach_file',
7 | method: 'post',
8 | data
9 | })
10 | }
11 |
12 | // 获取上传文件记录表列表
13 | export function page (pageParam) {
14 | return request({
15 | url: '/mall4cloud_biz/m/attach_file/page',
16 | method: 'get',
17 | params: pageParam
18 | })
19 | }
20 |
21 | // 更新文件记录
22 | export function updateFileName (data) {
23 | return request({
24 | url: '/mall4cloud_biz/m/attach_file/update_file',
25 | method: 'put',
26 | data
27 | })
28 | }
29 |
30 | // 删除上传文件记录
31 | export function deleteFile (param) {
32 | return request({
33 | url: '/mall4cloud_biz/m/attach_file',
34 | method: 'delete',
35 | params: param
36 | })
37 | }
38 |
--------------------------------------------------------------------------------
/src/components/product-details/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
14 |
37 |
38 |
40 |
--------------------------------------------------------------------------------
/src/icons/svg/index.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
17 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/skins/ui/oxide/skin.shadowdom.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | */
7 | body.tox-dialog__disable-scroll{overflow:hidden}.tox-fullscreen{border:0;height:100%;margin:0;overflow:hidden;-ms-scroll-chaining:none;overscroll-behavior:none;padding:0;touch-action:pinch-zoom;width:100%}.tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display:none}.tox-shadowhost.tox-fullscreen,.tox.tox-tinymce.tox-fullscreen{left:0;position:fixed;top:0;z-index:1200}.tox.tox-tinymce.tox-fullscreen{background-color:transparent}.tox-fullscreen .tox.tox-tinymce-aux,.tox-fullscreen~.tox.tox-tinymce-aux{z-index:1201}
8 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/skins/ui/oxide-dark/skin.shadowdom.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | */
7 | body.tox-dialog__disable-scroll{overflow:hidden}.tox-fullscreen{border:0;height:100%;margin:0;overflow:hidden;-ms-scroll-chaining:none;overscroll-behavior:none;padding:0;touch-action:pinch-zoom;width:100%}.tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display:none}.tox-shadowhost.tox-fullscreen,.tox.tox-tinymce.tox-fullscreen{left:0;position:fixed;top:0;z-index:1200}.tox.tox-tinymce.tox-fullscreen{background-color:transparent}.tox-fullscreen .tox.tox-tinymce-aux,.tox-fullscreen~.tox.tox-tinymce-aux{z-index:1201}
8 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/print/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),r=tinymce.util.Tools.resolve("tinymce.Env");n.add("print",function(n){var t,i;function e(){return i.execCommand("mcePrint")}(t=n).addCommand("mcePrint",function(){r.browser.isIE()?t.getDoc().execCommand("print",!1,null):t.getWin().print()}),(i=n).ui.registry.addButton("print",{icon:"print",tooltip:"Print",onAction:e}),i.ui.registry.addMenuItem("print",{text:"Print...",icon:"print",onAction:e}),n.addShortcut("Meta+P","","mcePrint")})}();
--------------------------------------------------------------------------------
/src/icons/svg/distribution.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
18 |
--------------------------------------------------------------------------------
/src/icons/svg/live.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
19 |
--------------------------------------------------------------------------------
/src/icons/svg/group.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
18 |
--------------------------------------------------------------------------------
/src/stores/modules/common.js:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia'
2 |
3 | export const useCommonStore = defineStore('common', {
4 | state: () => {
5 | return {
6 | // 侧边栏, 折叠状态
7 | sidebarFold: true,
8 | menuIds: [],
9 | selectLeftId: '',
10 | selectRightId: '',
11 | pathHeader: '',
12 | // 当前选择的标签
13 | selectMenu: [],
14 | routeList: []
15 | }
16 | },
17 | actions: {
18 | updateRouteList (list) {
19 | this.routeList = list
20 | },
21 | updatePathHeader (val) {
22 | this.pathHeader = val
23 | },
24 | updateSelectLeftId (id) {
25 | this.selectLeftId = id
26 | },
27 | updateSelectRightId (id) {
28 | this.selectRightId = id
29 | },
30 | updateSelectMenu (list) {
31 | this.selectMenu = list
32 | },
33 | updateSidebarFold (fold) {
34 | this.sidebarFold = fold
35 | }
36 | }
37 | })
38 |
--------------------------------------------------------------------------------
/src/api/system/addr-manage.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function page () {
4 | return request({
5 | url: '/mall4cloud_delivery/m/area/list',
6 | method: 'get'
7 | })
8 | }
9 |
10 | export function get (areaId) {
11 | return request({
12 | url: '/mall4cloud_delivery/m/area',
13 | method: 'get',
14 | params: {
15 | areaId
16 | }
17 | })
18 | }
19 |
20 | export function save (data) {
21 | return request({
22 | url: '/mall4cloud_delivery/m/area',
23 | method: 'post',
24 | data
25 | })
26 | }
27 |
28 | export function update (data) {
29 | return request({
30 | url: '/mall4cloud_delivery/m/area',
31 | method: 'put',
32 | data
33 | })
34 | }
35 |
36 | export function deleteById (areaId) {
37 | return request({
38 | url: '/mall4cloud_delivery/m/area',
39 | method: 'delete',
40 | params: {
41 | areaId
42 | }
43 | })
44 | }
45 |
--------------------------------------------------------------------------------
/src/icons/svg/eye.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/common/error-page/401.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | 返回
8 |
9 |
10 |
11 |
12 | 你没有权限去该页面 !
13 |
14 |
15 |
16 |
17 |
18 |
19 |
26 |
27 |
44 |
--------------------------------------------------------------------------------
/src/api/product/spu.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function page (pageParam) {
4 | return request({
5 | url: '/mall4cloud_product/m/spu/page',
6 | method: 'get',
7 | params: pageParam
8 | })
9 | }
10 |
11 | export function get (spuId) {
12 | return request({
13 | url: '/mall4cloud_product/m/spu',
14 | method: 'get',
15 | params: {
16 | spuId
17 | }
18 | })
19 | }
20 |
21 | export function save (data) {
22 | return request({
23 | url: '/mall4cloud_product/m/spu',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
29 | export function update (data) {
30 | return request({
31 | url: '/mall4cloud_product/m/spu',
32 | method: 'put',
33 | data
34 | })
35 | }
36 |
37 | export function deleteById (spuId) {
38 | return request({
39 | url: '/mall4cloud_product/m/spu',
40 | method: 'delete',
41 | params: {
42 | spuId
43 | }
44 | })
45 | }
46 |
--------------------------------------------------------------------------------
/src/icons/svg/shop.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
19 |
--------------------------------------------------------------------------------
/src/icons/svg-icon.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
30 |
31 |
48 |
--------------------------------------------------------------------------------
/src/api/product/attr.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function page (pageParam) {
4 | return request({
5 | url: '/mall4cloud_product/admin/attr/page',
6 | method: 'get',
7 | params: pageParam
8 | })
9 | }
10 |
11 | export function get (attrId) {
12 | return request({
13 | url: '/mall4cloud_product/admin/attr',
14 | method: 'get',
15 | params: {
16 | attrId
17 | }
18 | })
19 | }
20 |
21 | export function save (data) {
22 | return request({
23 | url: '/mall4cloud_product/admin/attr',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
29 | export function update (data) {
30 | return request({
31 | url: '/mall4cloud_product/admin/attr',
32 | method: 'put',
33 | data
34 | })
35 | }
36 |
37 | export function deleteById (attrId) {
38 | return request({
39 | url: '/mall4cloud_product/admin/attr',
40 | method: 'delete',
41 | params: {
42 | attrId
43 | }
44 | })
45 | }
46 |
--------------------------------------------------------------------------------
/src/api/multishop/notice.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function page (pageParam) {
4 | return request({
5 | url: '/mall4cloud_multishop/admin/notice/page',
6 | method: 'get',
7 | params: pageParam
8 | })
9 | }
10 |
11 | export function get (id) {
12 | return request({
13 | url: '/mall4cloud_multishop/admin/notice',
14 | method: 'get',
15 | params: {
16 | id
17 | }
18 | })
19 | }
20 |
21 | export function save (data) {
22 | return request({
23 | url: '/mall4cloud_multishop/admin/notice',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
29 | export function update (data) {
30 | return request({
31 | url: '/mall4cloud_multishop/admin/notice',
32 | method: 'put',
33 | data
34 | })
35 | }
36 |
37 | export function deleteById (id) {
38 | return request({
39 | url: '/mall4cloud_multishop/admin/notice',
40 | method: 'delete',
41 | params: {
42 | id
43 | }
44 | })
45 | }
46 |
--------------------------------------------------------------------------------
/src/api/product/spu-detail.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function page (pageParam) {
4 | return request({
5 | url: '/mall4cloud_product/m/spu_detail/page',
6 | method: 'get',
7 | params: pageParam
8 | })
9 | }
10 |
11 | export function get (spuId) {
12 | return request({
13 | url: '/mall4cloud_product/m/spu_detail',
14 | method: 'get',
15 | params: {
16 | spuId
17 | }
18 | })
19 | }
20 |
21 | export function save (data) {
22 | return request({
23 | url: '/mall4cloud_product/m/spu_detail',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
29 | export function update (data) {
30 | return request({
31 | url: '/mall4cloud_product/m/spu_detail',
32 | method: 'put',
33 | data
34 | })
35 | }
36 |
37 | export function deleteById (spuId) {
38 | return request({
39 | url: '/mall4cloud_product/m/spu_detail',
40 | method: 'delete',
41 | params: {
42 | spuId
43 | }
44 | })
45 | }
46 |
--------------------------------------------------------------------------------
/src/api/multishop/index-img.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function page (pageParam) {
4 | return request({
5 | url: '/mall4cloud_multishop/admin/index_img/page',
6 | method: 'get',
7 | params: pageParam
8 | })
9 | }
10 |
11 | export function get (imgId) {
12 | return request({
13 | url: '/mall4cloud_multishop/admin/index_img',
14 | method: 'get',
15 | params: {
16 | imgId
17 | }
18 | })
19 | }
20 |
21 | export function save (data) {
22 | return request({
23 | url: '/mall4cloud_multishop/admin/index_img',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
29 | export function update (data) {
30 | return request({
31 | url: '/mall4cloud_multishop/admin/index_img',
32 | method: 'put',
33 | data
34 | })
35 | }
36 |
37 | export function deleteById (imgId) {
38 | return request({
39 | url: '/mall4cloud_multishop/admin/index_img',
40 | method: 'delete',
41 | params: {
42 | imgId
43 | }
44 | })
45 | }
46 |
--------------------------------------------------------------------------------
/src/api/order/order.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function page (pageParam) {
4 | return request({
5 | url: '/mall4cloud_order/m/order/page',
6 | method: 'get',
7 | params: pageParam
8 | })
9 | }
10 |
11 | export function changeAmount (data) {
12 | return request({
13 | url: '/mall4cloud_order/m/order/change_amount',
14 | method: 'put',
15 | data
16 | })
17 | }
18 |
19 | export function orderInfo (orderId) {
20 | return request({
21 | url: '/mall4cloud_order/m/order/order_info/' + orderId,
22 | method: 'get'
23 | })
24 | }
25 |
26 | // 原/order/delivery/getOrderItemUnDelivery
27 | export function getOrderItemAndAddress (orderId) {
28 | return request({
29 | url: '/mall4cloud_order/m/order/order_item_and_address/' + orderId,
30 | method: 'get'
31 | })
32 | }
33 |
34 | //
35 | export function delivery (data) {
36 | return request({
37 | url: '/mall4cloud_order/m/order/delivery',
38 | method: 'post',
39 | data
40 | })
41 | }
42 |
--------------------------------------------------------------------------------
/src/stores/modules/app.js:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia'
2 | import { getLanguage } from '@/lang'
3 | import Cookies from 'vue-cookies'
4 |
5 | export const useAppStore = defineStore('app', {
6 | state: () => {
7 | return {
8 | sidebar: {
9 | opened: Cookies.get('cloudSidebarStatus') ? !!+Cookies.get('cloudSidebarStatus') : true,
10 | withoutAnimation: false
11 | },
12 | language: getLanguage()
13 | }
14 | },
15 | actions: {
16 | toggleSideBar () {
17 | this.sidebar.opened = !this.sidebar.opened
18 | this.sidebar.withoutAnimation = false
19 | Cookies.set('cloudSidebarStatus', Number(this.sidebar.opened))
20 | },
21 | closeSideBar ({ withoutAnimation }) {
22 | Cookies.set('cloudSidebarStatus', 0)
23 | this.sidebar.opened = false
24 | this.sidebar.withoutAnimation = withoutAnimation
25 | },
26 | setLanguage (language) {
27 | this.language = language
28 | Cookies.set('cloudLanguage', language)
29 | }
30 | }
31 | })
32 |
--------------------------------------------------------------------------------
/src/api/multishop/hot-search.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function page (pageParam) {
4 | return request({
5 | url: '/mall4cloud_multishop/admin/hot_search/page',
6 | method: 'get',
7 | params: pageParam
8 | })
9 | }
10 |
11 | export function get (hotSearchId) {
12 | return request({
13 | url: '/mall4cloud_multishop/admin/hot_search',
14 | method: 'get',
15 | params: {
16 | hotSearchId
17 | }
18 | })
19 | }
20 |
21 | export function save (data) {
22 | return request({
23 | url: '/mall4cloud_multishop/admin/hot_search',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
29 | export function update (data) {
30 | return request({
31 | url: '/mall4cloud_multishop/admin/hot_search',
32 | method: 'put',
33 | data
34 | })
35 | }
36 |
37 | export function deleteById (hotSearchId) {
38 | return request({
39 | url: '/mall4cloud_multishop/admin/hot_search',
40 | method: 'delete',
41 | params: {
42 | hotSearchId
43 | }
44 | })
45 | }
46 |
--------------------------------------------------------------------------------
/src/lang/biz/imgbox/en.js:
--------------------------------------------------------------------------------
1 | export default {
2 | picManager: 'Picture Manager',
3 | choosePic: 'Select Picture',
4 | picName: 'Picture name',
5 | query: 'query',
6 | uploadPic: 'Upload pictures',
7 | selectLocalPic: 'Please select a local image to upload:',
8 | confirmUpload: 'Confirm upload',
9 | revisePicName: 'Modify picture name',
10 | oldName: 'Old name',
11 | revName: 'Edit name',
12 | inputNewName: 'Please enter a new picture name',
13 | superiorLimit: 'The number of selectable photos has reached the upper limit',
14 | onlyPictures: 'Only images can be uploaded, other files have been cleared',
15 | onlySupported: 'Only supports',
16 | pic: 'picture',
17 | notExceed: 'Size cannot exceed',
18 | alreadyExist: 'Already existing',
19 | soonUpload: 'About to upload',
20 | unit: 'picture',
21 | upload: 'Upload',
22 | remainder: 'There are also options',
23 | maxSelect: 'At present, you can only select at most',
24 | requestError: 'The server is dozing off^_^',
25 | PicMaxQuantity: 'The maximum number of pictures is:'
26 | }
27 |
--------------------------------------------------------------------------------
/src/api/rbac/role.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function page (pageParam) {
4 | return request({
5 | url: '/mall4cloud_rbac/role/page',
6 | method: 'get',
7 | params: pageParam
8 | })
9 | }
10 |
11 | export function list () {
12 | return request({
13 | url: '/mall4cloud_rbac/role/list',
14 | method: 'get'
15 | })
16 | }
17 |
18 | export function get (roleId) {
19 | return request({
20 | url: '/mall4cloud_rbac/role',
21 | method: 'get',
22 | params: {
23 | roleId
24 | }
25 | })
26 | }
27 |
28 | export function save (data) {
29 | return request({
30 | url: '/mall4cloud_rbac/role',
31 | method: 'post',
32 | data
33 | })
34 | }
35 |
36 | export function update (data) {
37 | return request({
38 | url: '/mall4cloud_rbac/role',
39 | method: 'put',
40 | data
41 | })
42 | }
43 |
44 | export function deleteById (roleId) {
45 | return request({
46 | url: '/mall4cloud_rbac/role',
47 | method: 'delete',
48 | params: {
49 | roleId
50 | }
51 | })
52 | }
53 |
--------------------------------------------------------------------------------
/src/styles/variables.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
3 | *
4 | * https://www.mall4j.com/
5 | *
6 | * 未经允许,不可做商业用途!
7 | *
8 | * 版权所有,侵权必究!
9 | */
10 | // base color
11 | $blue:#324157;
12 | $light-blue:#3A71A8;
13 | $red:#C03639;
14 | $pink: #E65D6E;
15 | $green: #30B08F;
16 | $tiffany: #4AB7BD;
17 | $yellow:#FEC171;
18 | $panGreen: #30B08F;
19 |
20 | // sidebar
21 | $menuText:#333333;
22 | $menuActiveText:#409EFF;
23 | $subMenuActiveText:#333333; // https://github.com/ElemeFE/element/issues/12951
24 |
25 | $menuBg:#ffffff;
26 | $menuHover:#e7eefb;
27 |
28 | $subMenuBg:#ffffff;
29 | $subMenuHover:#e7eefb;
30 |
31 | $sideBarWidth: 230px;
32 |
33 | // the :export directive is the magic sauce for webpack
34 | // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
35 | :export {
36 | menuText: $menuText;
37 | menuActiveText: $menuActiveText;
38 | subMenuActiveText: $subMenuActiveText;
39 | menuBg: $menuBg;
40 | menuHover: $menuHover;
41 | subMenuBg: $subMenuBg;
42 | subMenuHover: $subMenuHover;
43 | sideBarWidth: $sideBarWidth;
44 | }
45 |
--------------------------------------------------------------------------------
/src/styles/transition.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
3 | *
4 | * https://www.mall4j.com/
5 | *
6 | * 未经允许,不可做商业用途!
7 | *
8 | * 版权所有,侵权必究!
9 | */
10 | // global transition css
11 |
12 | /* fade */
13 | .fade-enter-active,
14 | .fade-leave-active {
15 | transition: opacity 0.28s;
16 | }
17 |
18 | .fade-enter,
19 | .fade-leave-active {
20 | opacity: 0;
21 | }
22 |
23 | /* fade-transform */
24 | .fade-transform-leave-active,
25 | .fade-transform-enter-active {
26 | transition: all .5s;
27 | }
28 |
29 | .fade-transform-enter {
30 | opacity: 0;
31 | transform: translateX(-30px);
32 | }
33 |
34 | .fade-transform-leave-to {
35 | opacity: 0;
36 | transform: translateX(30px);
37 | }
38 |
39 | /* breadcrumb transition */
40 | .breadcrumb-enter-active,
41 | .breadcrumb-leave-active {
42 | transition: all .5s;
43 | }
44 |
45 | .breadcrumb-enter,
46 | .breadcrumb-leave-active {
47 | opacity: 0;
48 | transform: translateX(20px);
49 | }
50 |
51 | .breadcrumb-move {
52 | transition: all .5s;
53 | }
54 |
55 | .breadcrumb-leave-active {
56 | position: absolute;
57 | }
58 |
--------------------------------------------------------------------------------
/src/icons/svg/analysis.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
22 |
--------------------------------------------------------------------------------
/src/icons/svg/icon-zhedie.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/src/lang/index.js:
--------------------------------------------------------------------------------
1 | import { createI18n } from 'vue-i18n'
2 | import en from './en'
3 | import zhCn from './zhCn'
4 | import Cookies from 'vue-cookies'
5 | const messages = {
6 | en: {
7 | ...en
8 | },
9 | zh: {
10 | ...zhCn
11 | }
12 | }
13 | export function getLanguage () {
14 | const chooseLanguage = Cookies.get('cloudLanguage')
15 | if (chooseLanguage) return chooseLanguage
16 | // if has not choose language
17 | const language = (navigator.language || navigator.browserLanguage).toLowerCase()
18 | const locales = Object.keys(messages)
19 | for (const locale of locales) {
20 | if (language.indexOf(locale) > -1) {
21 | return locale
22 | }
23 | }
24 | return 'zh'
25 | }
26 |
27 | const localeData = {
28 | globalInjection: true, // 如果设置true, $t() 函数将注册到全局
29 | legacy: false, // 如果想在composition api中使用需要设置为false
30 | // 默认语言
31 | // locale: settings.defaultLanguage,
32 | locale: localStorage.getItem('cloudLanguage') || 'zh',
33 | messages // set locale messages
34 | }
35 |
36 | export const i18n = createI18n(localeData)
37 | export const setupI18n = {
38 | install (app) {
39 | app.use(i18n)
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/api/multishop/shop-user.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function shopUserInfo () {
4 | return request({
5 | url: '/mall4cloud_multishop/m/shop_user/info',
6 | method: 'get'
7 | })
8 | }
9 |
10 | export function page (pageParam) {
11 | return request({
12 | url: '/mall4cloud_multishop/m/shop_user/page',
13 | method: 'get',
14 | params: pageParam
15 | })
16 | }
17 |
18 | export function get (shopUserId) {
19 | return request({
20 | url: '/mall4cloud_multishop/m/shop_user',
21 | method: 'get',
22 | params: {
23 | shopUserId
24 | }
25 | })
26 | }
27 |
28 | export function save (data) {
29 | return request({
30 | url: '/mall4cloud_multishop/m/shop_user',
31 | method: 'post',
32 | data
33 | })
34 | }
35 |
36 | export function update (data) {
37 | return request({
38 | url: '/mall4cloud_multishop/m/shop_user',
39 | method: 'put',
40 | data
41 | })
42 | }
43 |
44 | export function deleteById (shopUserId) {
45 | return request({
46 | url: '/mall4cloud_multishop/m/shop_user',
47 | method: 'delete',
48 | params: {
49 | shopUserId
50 | }
51 | })
52 | }
53 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/code/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("code",function(e){var t,o;function n(){return o.execCommand("mceCodeEditor")}return(t=e).addCommand("mceCodeEditor",function(){var n,e;e=(n=t).getContent({source_view:!0}),n.windowManager.open({title:"Source Code",size:"large",body:{type:"panel",items:[{type:"textarea",name:"code"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{code:e},onSubmit:function(e){var t=n,o=e.getData().code;t.focus(),t.undoManager.transact(function(){t.setContent(o)}),t.selection.setCursorLocation(),t.nodeChanged(),e.close()}})}),(o=e).ui.registry.addButton("code",{icon:"sourcecode",tooltip:"Source code",onAction:n}),o.ui.registry.addMenuItem("code",{icon:"sourcecode",text:"Source code",onAction:n}),{}})}();
--------------------------------------------------------------------------------
/src/api/product/prod-info.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function page (pageParam) {
4 | return request({
5 | url: '/mall4cloud_product/m/spu/page',
6 | method: 'get',
7 | params: pageParam
8 | })
9 | }
10 |
11 | export function getProdInfoPage (spuId) {
12 | return request({
13 | url: '/mall4cloud_product/admin/spu',
14 | method: 'get',
15 | params: {
16 | spuId
17 | }
18 | })
19 | }
20 |
21 | export function save (data) {
22 | return request({
23 | url: '/mall4cloud_product/admin/spu',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
29 | export function update (data) {
30 | return request({
31 | url: '/mall4cloud_product/admin/spu',
32 | method: 'put',
33 | data
34 | })
35 | }
36 |
37 | export function deleteById (spuId) {
38 | return request({
39 | url: '/mall4cloud_product/admin/spu',
40 | method: 'delete',
41 | params: {
42 | spuId
43 | }
44 | })
45 | }
46 |
47 | export function getAttrsByCategoryId (param) {
48 | return request({
49 | url: '/mall4cloud_product/admin/attr/get_attrs_by_category_id',
50 | method: 'get',
51 | params: param
52 | })
53 | }
54 |
--------------------------------------------------------------------------------
/src/api/rbac/menu-permission.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function page (pageParam) {
4 | return request({
5 | url: '/mall4cloud_rbac/menu_permission/page',
6 | method: 'get',
7 | params: pageParam
8 | })
9 | }
10 |
11 | export function get (menuPermissionId) {
12 | return request({
13 | url: '/mall4cloud_rbac/menu_permission',
14 | method: 'get',
15 | params: {
16 | menuPermissionId
17 | }
18 | })
19 | }
20 |
21 | export function save (data) {
22 | return request({
23 | url: '/mall4cloud_rbac/menu_permission',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
29 | export function update (data) {
30 | return request({
31 | url: '/mall4cloud_rbac/menu_permission',
32 | method: 'put',
33 | data
34 | })
35 | }
36 |
37 | export function deleteById (menuPermissionId) {
38 | return request({
39 | url: '/mall4cloud_rbac/menu_permission',
40 | method: 'delete',
41 | params: {
42 | menuPermissionId
43 | }
44 | })
45 | }
46 |
47 | export function menuPermissionsList () {
48 | return request({
49 | url: '/mall4cloud_rbac/menu_permission/list',
50 | method: 'get'
51 | })
52 | }
53 |
--------------------------------------------------------------------------------
/src/icons/svg/language.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/svg/promotion.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
--------------------------------------------------------------------------------
/src/icons/svg/product.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
15 |
--------------------------------------------------------------------------------
/src/icons/svg/eye-open.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/layout/components/Sidebar/main-sidebar-sub-menu.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
26 |
27 |
28 |
29 |
41 |
53 |
--------------------------------------------------------------------------------
/src/api/delivery/transport.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function page (pageParam) {
4 | return request({
5 | url: '/mall4cloud_delivery/m/transport/page',
6 | method: 'get',
7 | params: pageParam
8 | })
9 | }
10 |
11 | export function get (transportId) {
12 | return request({
13 | url: '/mall4cloud_delivery/m/transport',
14 | method: 'get',
15 | params: {
16 | transportId
17 | }
18 | })
19 | }
20 |
21 | export function save (data) {
22 | return request({
23 | url: '/mall4cloud_delivery/m/transport',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
29 | export function update (data) {
30 | return request({
31 | url: '/mall4cloud_delivery/m/transport',
32 | method: 'put',
33 | data
34 | })
35 | }
36 |
37 | export function deleteById (transportId) {
38 | return request({
39 | url: '/mall4cloud_delivery/m/transport',
40 | method: 'delete',
41 | params: {
42 | transportId
43 | }
44 | })
45 | }
46 |
47 | export function listArea () {
48 | return request({
49 | url: '/mall4cloud_delivery/m/area/list',
50 | method: 'get',
51 | params: {}
52 | })
53 | }
54 |
55 | export function listAreaInfo () {
56 | return request({
57 | url: '/mall4cloud_delivery/m/area/areaListInfo',
58 | method: 'get',
59 | params: {}
60 | })
61 | }
62 |
--------------------------------------------------------------------------------
/src/utils/excelRequest.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import { getToken } from '@/utils/auth'
3 |
4 | // create an axios instance
5 | const service = axios.create({
6 | baseURL: import.meta.env.VITE_APP_BASE_API, // url = base url + request url
7 | responseType: 'blob',
8 | // withCredentials: true, // send cookies when cross-domain requests
9 | timeout: 500000 // request timeout
10 | })
11 |
12 | // request interceptor
13 | service.interceptors.request.use(
14 | config => {
15 | const token = useUserStore().token
16 | // do something before request is sent
17 | if (token) {
18 | config.headers.Authorization = getToken()
19 | }
20 | return config
21 | },
22 | error => {
23 | // do something with request error
24 | // eslint-disable-next-line no-console
25 | console.log(error) // for debug
26 | return Promise.reject(error)
27 | }
28 | )
29 |
30 | // response interceptor
31 | service.interceptors.response.use(
32 | /**
33 | * If you want to get http information such as headers or status
34 | * Please return response => response
35 | */
36 |
37 | /**
38 | * Determine the request status by custom code
39 | * Here is just an example
40 | * You can also judge the status by HTTP Status Code
41 | */
42 | response => {
43 | return response.data
44 | }
45 | )
46 |
47 | export default service
48 |
--------------------------------------------------------------------------------
/src/api/rbac/menu.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function page (pageParam) {
4 | return request({
5 | url: '/mall4cloud_rbac/menu/page',
6 | method: 'get',
7 | params: pageParam
8 | })
9 | }
10 |
11 | export function get (menuId) {
12 | return request({
13 | url: '/mall4cloud_rbac/menu',
14 | method: 'get',
15 | params: {
16 | menuId
17 | }
18 | })
19 | }
20 |
21 | export function save (data) {
22 | return request({
23 | url: '/mall4cloud_rbac/menu',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
29 | export function update (data) {
30 | return request({
31 | url: '/mall4cloud_rbac/menu',
32 | method: 'put',
33 | data
34 | })
35 | }
36 |
37 | export function deleteById (menuId) {
38 | return request({
39 | url: '/mall4cloud_rbac/menu',
40 | method: 'delete',
41 | params: {
42 | menuId
43 | }
44 | })
45 | }
46 |
47 | export function menuList () {
48 | return request({
49 | url: '/mall4cloud_rbac/menu/route',
50 | method: 'get'
51 | })
52 | }
53 |
54 | export function listWithPermissions () {
55 | return request({
56 | url: '/mall4cloud_rbac/menu/list_with_permissions',
57 | method: 'get'
58 | })
59 | }
60 |
61 | export function listMenuIds () {
62 | return request({
63 | url: '/mall4cloud_rbac/menu/list_menu_ids',
64 | method: 'get'
65 | })
66 | }
67 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/visualblocks/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";function f(t,o,e){var n,i;t.dom.toggleClass(t.getBody(),"mce-visualblocks"),e.set(!e.get()),n=t,i=e.get(),n.fire("VisualBlocks",{state:i})}function g(e,n){return function(o){function t(t){return o.setActive(t.state)}return o.setActive(n.get()),e.on("VisualBlocks",t),function(){return e.off("VisualBlocks",t)}}}tinymce.util.Tools.resolve("tinymce.PluginManager").add("visualblocks",function(t,o){var e,n,i,s,c,u,l,a=(e=!1,{get:function(){return e},set:function(t){e=t}});function r(){return s.execCommand("mceVisualBlocks")}i=a,(n=t).addCommand("mceVisualBlocks",function(){f(n,0,i)}),(s=t).ui.registry.addToggleButton("visualblocks",{icon:"visualblocks",tooltip:"Show blocks",onAction:r,onSetup:g(s,c=a)}),s.ui.registry.addToggleMenuItem("visualblocks",{text:"Show blocks",icon:"visualblocks",onAction:r,onSetup:g(s,c)}),l=a,(u=t).on("PreviewFormats AfterPreviewFormats",function(t){l.get()&&u.dom.toggleClass(u.getBody(),"mce-visualblocks","afterpreviewformats"===t.type)}),u.on("init",function(){u.getParam("visualblocks_default_state",!1,"boolean")&&f(u,0,l)})})}();
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/nonbreaking/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";function o(n,e){for(var a="",o=0;o'+o(" ",e)+"":o(" ",e);n.undoManager.transact(function(){return n.insertContent(a)})}var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),c=tinymce.util.Tools.resolve("tinymce.util.VK");n.add("nonbreaking",function(n){var e,a,o,t,i;function r(){return a.execCommand("mceNonBreaking")}(e=n).addCommand("mceNonBreaking",function(){s(e,1)}),(a=n).ui.registry.addButton("nonbreaking",{icon:"non-breaking",tooltip:"Nonbreaking space",onAction:r}),a.ui.registry.addMenuItem("nonbreaking",{icon:"non-breaking",text:"Nonbreaking space",onAction:r}),0<(i="boolean"==typeof(t=(o=n).getParam("nonbreaking_force_tab",0))?!0===t?3:0:t)&&o.on("keydown",function(n){n.keyCode!==c.TAB||n.isDefaultPrevented()||n.shiftKey||(n.preventDefault(),n.stopImmediatePropagation(),s(o,i))})})}();
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/skins/content/default/content.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | */
7 | body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#ccc}figure{display:table;margin:1rem auto}figure figcaption{color:#999;display:block;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}code{background-color:#e8e8e8;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem}
8 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/skins/content/writer/content.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | */
7 | body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem auto;max-width:900px}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#ccc}figure{display:table;margin:1rem auto}figure figcaption{color:#999;display:block;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}code{background-color:#e8e8e8;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem}
8 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import { setupStore } from '@/stores'
3 | import App from './App.vue'
4 | import router from '@/router'
5 | // i18n
6 | import { setupI18n } from '@/lang'
7 | import 'virtual:svg-icons-register'
8 | import svgIcon from '@/icons/svg-icon.vue'
9 | import * as ElementPlusIconsVue from '@element-plus/icons-vue'
10 | import ElementPlus from 'element-plus'
11 | import 'element-plus/dist/index.css'
12 |
13 | // import 'default-passive-events'
14 | // 全局样式
15 | import '@/styles/index.scss'
16 | // 权限路由、菜单
17 | import '@/permission.js'
18 | // 自定义指令
19 | import { setupDirective } from '@/directive'
20 | import moment from 'moment'
21 |
22 | // element-plus 图标
23 | const app = createApp(App)
24 | for (const [key, component] of Object.entries(
25 | ElementPlusIconsVue)) {
26 | app.component(key, component)
27 | }
28 |
29 | // i18n
30 | app.use(setupI18n)
31 | // router
32 | app.use(router)
33 | // 状态管理
34 | setupStore(app)
35 | // 注册指令(directive)
36 | setupDirective(app)
37 |
38 | // svg
39 | app.component('SvgIcon', svgIcon)
40 |
41 | app.mount('#app')
42 |
43 | // element-plus
44 | app.use(ElementPlus)
45 |
46 | // 自定义moment(js时间组件)
47 | moment.locale('zh-cn', {
48 | longDateFormat: {
49 | LT: 'HH:mm',
50 | LTS: 'HH:mm:ss',
51 | L: 'YYYY-MM-DD',
52 | LL: 'YYYY-MM-DD HH:mm:ss'
53 | },
54 | week: {
55 | // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
56 | dow: 1, // 星期一, 是一个星期的第一天
57 | doy: 4 // 1月4日所在的的一周是一年的第一周
58 | }
59 | })
60 |
--------------------------------------------------------------------------------
/src/stores/modules/web-config.js:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia'
2 | export const useWebConfigStore = defineStore('webConfigStore', {
3 | state: () => {
4 | return {
5 | webConfig: {
6 | loginLogoImg: null,
7 | loginBgImg: null,
8 | copyrightCn: null,
9 | copyrightEn: null,
10 | titleContentCn: null,
11 | titleContentEn: null,
12 | titleImg: null,
13 | bsMenuTitleOpenCn: null,
14 | bsMenuTitleOpenEn: null,
15 | bsMenuTitleCloseCn: null,
16 | bsMenuTitleCloseEn: null
17 | }
18 | }
19 | },
20 | actions: {
21 | addData (webConfigDataForm) {
22 | localStorage.setItem('cloudPlatformWebConfigData', JSON.stringify(webConfigDataForm || '{}'))
23 | this.webConfig = webConfigDataForm
24 | const lang = localStorage.getItem('cloudLang')
25 | if (lang !== 'en') {
26 | document.title = webConfigDataForm.titleContentCn || 'Mall4j白洞版-平台端'
27 | } else {
28 | document.title = webConfigDataForm.titleContentEn || 'Mall4j White hole version Supplier side'
29 | }
30 |
31 | let facicon = document.querySelector('link[rel="icon"]')
32 | if (facicon !== null) {
33 | facicon.href = webConfigDataForm.titleImg
34 | } else {
35 | facicon = document.createElement('link')
36 | facicon.rel = 'icon'
37 | facicon.href = webConfigDataForm.titleImg
38 | document.head.appendChild(facicon)
39 | }
40 | }
41 | }
42 | })
43 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/skins/content/dark/content.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | */
7 | body{background-color:#2f3742;color:#dfe0e4;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem}a{color:#4099ff}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#6d737b}figure{display:table;margin:1rem auto}figure figcaption{color:#8a8f97;display:block;margin-top:.25rem;text-align:center}hr{border-color:#6d737b;border-style:solid;border-width:1px 0 0 0}code{background-color:#6d737b;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #6d737b;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #6d737b;margin-right:1.5rem;padding-right:1rem}
8 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/skins/content/document/content.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | */
7 | @media screen{html{background:#f4f4f4;min-height:100%}}body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif}@media screen{body{background-color:#fff;box-shadow:0 0 4px rgba(0,0,0,.15);box-sizing:border-box;margin:1rem auto 0;max-width:820px;min-height:calc(100vh - 1rem);padding:4rem 6rem 6rem 6rem}}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#ccc}figure figcaption{color:#999;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem}
8 |
--------------------------------------------------------------------------------
/src/components/picture-preview/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
![]()
17 |
18 |
19 |
20 |
21 |
41 |
42 |
73 |
--------------------------------------------------------------------------------
/src/api/biz/oss.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function ossInfo (fileNum) {
4 | return request({
5 | url: '/mall4cloud_biz/oss/info',
6 | method: 'get',
7 | params: { fileNum }
8 | })
9 | }
10 |
11 | export function pageFileGroup () {
12 | return request({
13 | url: '/mall4cloud_biz/m/attach_file_group/list',
14 | method: 'get'
15 | })
16 | }
17 |
18 | export function getFileGroup (param) {
19 | return request({
20 | url: '/mall4cloud_biz/m/attach_file_group',
21 | method: 'get',
22 | params: param
23 | })
24 | }
25 |
26 | export function saveFileGroup (data) {
27 | return request({
28 | url: '/mall4cloud_biz/m/attach_file_group',
29 | method: 'post',
30 | data
31 | })
32 | }
33 |
34 | export function updateFileGroup (data) {
35 | return request({
36 | url: '/mall4cloud_biz/m/attach_file_group',
37 | method: 'put',
38 | data
39 | })
40 | }
41 |
42 | export function deleteFileGroup (param) {
43 | return request({
44 | url: '/mall4cloud_biz/m/attach_file_group',
45 | method: 'delete',
46 | params: param
47 | })
48 | }
49 |
50 | // minIo上传文件
51 | export function minIoImgUpdate (url, data) {
52 | return request({
53 | headers: {
54 | 'Content-Type': data.type
55 | },
56 | url,
57 | method: 'put',
58 | data
59 | })
60 | }
61 |
62 | // aliOss上传文件
63 | export function aliImgUpdate (url, data) {
64 | return request({
65 | headers: {
66 | 'Content-Type': data.type
67 | },
68 | url,
69 | method: 'post',
70 | data
71 | })
72 | }
73 |
--------------------------------------------------------------------------------
/src/components/Verifition/utils/util.js:
--------------------------------------------------------------------------------
1 | export function resetSize (vm) {
2 | let img_width, img_height, bar_width, bar_height // 图片的宽度、高度,移动条的宽度、高度
3 |
4 | const parentWidth = vm.$el.parentNode.offsetWidth || window.offsetWidth
5 | const parentHeight = vm.$el.parentNode.offsetHeight || window.offsetHeight
6 | if (vm.imgSize.width.indexOf('%') != -1) {
7 | img_width = parseInt(vm.imgSize.width) / 100 * parentWidth + 'px'
8 | } else {
9 | img_width = vm.imgSize.width
10 | }
11 |
12 | if (vm.imgSize.height.indexOf('%') != -1) {
13 | img_height = parseInt(vm.imgSize.height) / 100 * parentHeight + 'px'
14 | } else {
15 | img_height = vm.imgSize.height
16 | }
17 |
18 | if (vm.barSize.width.indexOf('%') != -1) {
19 | bar_width = parseInt(vm.barSize.width) / 100 * parentWidth + 'px'
20 | } else {
21 | bar_width = vm.barSize.width
22 | }
23 |
24 | if (vm.barSize.height.indexOf('%') != -1) {
25 | bar_height = parseInt(vm.barSize.height) / 100 * parentHeight + 'px'
26 | } else {
27 | bar_height = vm.barSize.height
28 | }
29 |
30 | return { imgWidth: img_width, imgHeight: img_height, barWidth: bar_width, barHeight: bar_height }
31 | }
32 |
33 | export const _code_chars = [1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
34 | export const _code_color1 = ['#fffff0', '#f0ffff', '#f0fff0', '#fff0f0']
35 | export const _code_color2 = ['#FF0033', '#006699', '#993366', '#FF9900', '#66CC66', '#FF33CC']
36 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/pagebreak/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";function u(e){return e.getParam("pagebreak_split_block",!1)}function l(e){var a='
';return e?""+a+"
":a}var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),n=tinymce.util.Tools.resolve("tinymce.Env"),m="mce-pagebreak";e.add("pagebreak",function(e){var a,n,o,i,t,r;function c(){return n.execCommand("mcePageBreak")}function g(){return u(o)}(a=e).addCommand("mcePageBreak",function(){a.insertContent(l(u(a)))}),(n=e).ui.registry.addButton("pagebreak",{icon:"page-break",tooltip:"Page break",onAction:c}),n.ui.registry.addMenuItem("pagebreak",{text:"Page break",icon:"page-break",onAction:c}),i=(o=e).getParam("pagebreak_separator","\x3c!-- pagebreak --\x3e"),t=new RegExp(i.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(e){return"\\"+e}),"gi"),o.on("BeforeSetContent",function(e){e.content=e.content.replace(t,l(g()))}),o.on("PreInit",function(){o.serializer.addNodeFilter("img",function(e){for(var a,n,t,r=e.length;r--;)(t=(n=e[r]).attr("class"))&&-1!==t.indexOf(m)&&(a=n.parent,o.schema.getBlockElements()[a.name]&&g()?(a.type=3,a.value=i,a.raw=!0,n.remove()):(n.type=3,n.value=i,n.raw=!0))})}),(r=e).on("ResolveName",function(e){"IMG"===e.target.nodeName&&r.dom.hasClass(e.target,m)&&(e.name="pagebreak")})})}();
--------------------------------------------------------------------------------
/src/api/product/category.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | // 获取店铺所有的分类信息
4 | export function shopCategoryPage () {
5 | return request({
6 | url: '/mall4cloud_product/admin/category/shop_categories',
7 | method: 'get',
8 | params: {}
9 | })
10 | }
11 |
12 | // 获取平台所有的分类信息
13 | export function platformCategoryPage () {
14 | return request({
15 | url: '/mall4cloud_product/admin/category/platform_categories',
16 | method: 'get',
17 | params: {}
18 | })
19 | }
20 |
21 | // 获取店铺中的销售属性
22 | export function getShopAttrs () {
23 | return request({
24 | url: '/mall4cloud_product/admin/attr/get_shop_attrs',
25 | method: 'get',
26 | params: {}
27 | })
28 | }
29 |
30 | export function get (categoryId) {
31 | return request({
32 | url: '/mall4cloud_product/admin/category',
33 | method: 'get',
34 | params: {
35 | categoryId
36 | }
37 | })
38 | }
39 |
40 | export function save (data) {
41 | return request({
42 | url: '/mall4cloud_product/admin/category',
43 | method: 'post',
44 | data
45 | })
46 | }
47 |
48 | export function update (data) {
49 | return request({
50 | url: '/mall4cloud_product/admin/category',
51 | method: 'put',
52 | data
53 | })
54 | }
55 |
56 | export function deleteById (categoryId) {
57 | return request({
58 | url: '/mall4cloud_product/admin/category',
59 | method: 'delete',
60 | params: {
61 | categoryId
62 | }
63 | })
64 | }
65 |
66 | export function enableOrDisable (data) {
67 | return request({
68 | url: '/mall4cloud_product/admin/category/category_enable_or_disable',
69 | method: 'put',
70 | data
71 | })
72 | }
73 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/save/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";function o(e){return e.getParam("save_enablewhendirty",!0)}function a(e,n){e.notificationManager.open({text:n,type:"error"})}function t(t){t.addCommand("mceSave",function(){!function(e){var n=c.DOM.getParent(e.id,"form");if(!o(e)||e.isDirty()){if(e.save(),e.getParam("save_onsavecallback"))return e.execCallback("save_onsavecallback",e),e.nodeChanged();n?(e.setDirty(!1),n.onsubmit&&!n.onsubmit()||("function"==typeof n.submit?n.submit():a(e,"Error: Form submit field collision.")),e.nodeChanged()):a(e,"Error: No form element found.")}}(t)}),t.addCommand("mceCancel",function(){var e=t,n=r.trim(e.startContent);e.getParam("save_oncancelcallback")?e.execCallback("save_oncancelcallback",e):e.resetContent(n)})}function i(t){return function(e){function n(){e.setDisabled(o(t)&&!t.isDirty())}return n(),t.on("NodeChange dirty",n),function(){return t.off("NodeChange dirty",n)}}}var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),c=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),r=tinymce.util.Tools.resolve("tinymce.util.Tools");e.add("save",function(e){var n;(n=e).ui.registry.addButton("save",{icon:"save",tooltip:"Save",disabled:!0,onAction:function(){return n.execCommand("mceSave")},onSetup:i(n)}),n.ui.registry.addButton("cancel",{icon:"cancel",tooltip:"Cancel",disabled:!0,onAction:function(){return n.execCommand("mceCancel")},onSetup:i(n)}),n.addShortcut("Meta+S","","mceSave"),t(e)})}();
--------------------------------------------------------------------------------
/src/icons/svg/tree.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/styles/mixin.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
3 | *
4 | * https://www.mall4j.com/
5 | *
6 | * 未经允许,不可做商业用途!
7 | *
8 | * 版权所有,侵权必究!
9 | */
10 | @mixin clearfix {
11 | &:after {
12 | content: "";
13 | display: table;
14 | clear: both;
15 | }
16 | }
17 |
18 | @mixin scrollBar {
19 | &::-webkit-scrollbar-track-piece {
20 | background: #d3dce6;
21 | }
22 |
23 | &::-webkit-scrollbar {
24 | width: 6px;
25 | }
26 |
27 | &::-webkit-scrollbar-thumb {
28 | background: #99a9bf;
29 | border-radius: 20px;
30 | }
31 | }
32 |
33 | @mixin relative {
34 | position: relative;
35 | width: 100%;
36 | height: 100%;
37 | }
38 |
39 | @mixin pct($pct) {
40 | width: #{$pct};
41 | position: relative;
42 | margin: 0 auto;
43 | }
44 |
45 | @mixin triangle($width, $height, $color, $direction) {
46 | $width: $width/2;
47 | $color-border-style: $height solid $color;
48 | $transparent-border-style: $width solid transparent;
49 | height: 0;
50 | width: 100px;
51 |
52 | @if $direction==up {
53 | border-bottom: $color-border-style;
54 | border-left: $transparent-border-style;
55 | border-right: $transparent-border-style;
56 | }
57 |
58 | @else if $direction==right {
59 | border-left: $color-border-style;
60 | border-top: $transparent-border-style;
61 | border-bottom: $transparent-border-style;
62 | }
63 |
64 | @else if $direction==down {
65 | border-top: $color-border-style;
66 | border-left: $transparent-border-style;
67 | border-right: $transparent-border-style;
68 | }
69 |
70 | @else if $direction==left {
71 | border-right: $color-border-style;
72 | border-top: $transparent-border-style;
73 | border-bottom: $transparent-border-style;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/noneditable/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";function l(t){return t.getParam("noneditable_noneditable_class","mceNonEditable")}function u(e){return function(t){return-1!==(" "+t.attr("class")+" ").indexOf(e)}}function e(e){var t,r="contenteditable",n=" "+f.trim(e.getParam("noneditable_editable_class","mceEditable"))+" ",a=" "+f.trim(l(e))+" ",i=u(n),o=u(a),c=(t=e.getParam("noneditable_regexp",[]))&&t.constructor===RegExp?[t]:t;e.on("PreInit",function(){0"===r){var a=o.lastIndexOf("<",n);if(-1!==a&&-1!==o.substring(a,n).indexOf('contenteditable="false"'))return t}return''+i.dom.encode("string"==typeof e[1]?e[1]:e[0])+""}}(t,a,l(t)));n.content=a}}(e,c,t)}),e.parser.addAttributeFilter("class",function(t){for(var e,n=t.length;n--;)e=t[n],i(e)?e.attr(r,"true"):o(e)&&e.attr(r,"false")}),e.serializer.addAttributeFilter(r,function(t){for(var e,n=t.length;n--;)e=t[n],(i(e)||o(e))&&(0 import('@/layout/index.vue')
4 |
5 | /**
6 | * constantRoutes
7 | * a base page that does not have permission requirements
8 | * all roles can be accessed
9 | */
10 | export const constantRoutes = [
11 | { path: '/', redirect: '/order/order' },
12 | {
13 | path: '/redirect',
14 | component: Layout,
15 | hidden: true,
16 | children: [
17 | {
18 | path: '/redirect/:path(.*)',
19 | component: () => import('@/views/common/redirect/index.vue')
20 | }
21 | ]
22 | },
23 | {
24 | path: '/login',
25 | component: () => import('@/views/common/login/index.vue'),
26 | hidden: true
27 | },
28 | {
29 | path: '/401',
30 | component: () => import('@/views/common/error-page/401.vue'),
31 | hidden: true
32 | },
33 | {
34 | path: '/404',
35 | component: () => import('@/views/common/error-page/404.vue'),
36 | hidden: true
37 | }
38 | // {
39 | // path: '/',
40 | // component: Layout,
41 | // redirect: '/dashboard',
42 | // children: [
43 | // {
44 | // path: 'dashboard',
45 | // component: () => import('@/views/common/dashboard/index.vue'),
46 | // name: 'Dashboard',
47 | // meta: { title: 'dashboard', icon: 'index', affix: true }
48 | // }
49 | // ]
50 | // }
51 | ]
52 |
53 | const router = createRouter({
54 | history: createWebHistory(),
55 | isAddDynamicMenuRoutes: false,
56 | // 刷新时,滚动条位置还原
57 | scrollBehavior: () => ({ left: 0, top: 0 }),
58 | routes: constantRoutes
59 | })
60 |
61 | /**
62 | * 重置路由
63 | */
64 | export async function resetRouter () {
65 | router.options.isAddDynamicMenuRoutes = false
66 | await router.replace({ path: '/login' })
67 | }
68 | export default router
69 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/tabfocus/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";function n(e){e.keyCode!==y.TAB||e.ctrlKey||e.altKey||e.metaKey||e.preventDefault()}var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),s=tinymce.util.Tools.resolve("tinymce.EditorManager"),o=tinymce.util.Tools.resolve("tinymce.Env"),a=tinymce.util.Tools.resolve("tinymce.util.Delay"),c=tinymce.util.Tools.resolve("tinymce.util.Tools"),y=tinymce.util.Tools.resolve("tinymce.util.VK"),d=t.DOM;e.add("tabfocus",function(e){function t(l){var r,e,t,n,i;l.keyCode!==y.TAB||l.ctrlKey||l.altKey||l.metaKey||l.isDefaultPrevented()||(e=function(e){function t(e){return/INPUT|TEXTAREA|BUTTON/.test(e.tagName)&&s.get(l.id)&&-1!==e.tabIndex&&i(e)}var n=d.select(":input:enabled,*[tabindex]:not(iframe)"),i=function(e){return"BODY"===e.nodeName||"hidden"!==e.type&&"none"!==e.style.display&&"hidden"!==e.style.visibility&&i(e.parentNode)};if(c.each(n,function(e,t){if(e.id===u.id)return r=t,!1}),0
10 |
11 |
15 |
16 |
17 |
18 |
22 |
27 |
28 |
29 |
30 |
47 |
48 |
80 |
--------------------------------------------------------------------------------
/src/components/tiny-mce/dynamicLoadScript.js:
--------------------------------------------------------------------------------
1 | let callbacks = []
2 |
3 | function loadedTinymce () {
4 | // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2144
5 | // check is successfully downloaded script
6 | return window.tinymce
7 | }
8 |
9 | const dynamicLoadScript = (src, callback) => {
10 | const existingScript = document.getElementById(src)
11 | const cb = callback || function () {}
12 |
13 | if (!existingScript) {
14 | const script = document.createElement('script')
15 | script.src = src // src url for the third-party library being loaded.
16 | script.id = src
17 | document.body.appendChild(script)
18 | callbacks.push(cb)
19 | const onEnd = 'onload' in script ? stdOnEnd : ieOnEnd
20 | onEnd(script)
21 | }
22 |
23 | if (existingScript && cb) {
24 | if (loadedTinymce()) {
25 | cb(null, existingScript)
26 | } else {
27 | callbacks.push(cb)
28 | }
29 | }
30 |
31 | function stdOnEnd (script) {
32 | script.onload = function () {
33 | // this.onload = null here is necessary
34 | // because even IE9 works not like others
35 | this.onerror = this.onload = null
36 | for (const cb of callbacks) {
37 | cb(null, script)
38 | }
39 | callbacks = null
40 | }
41 | script.onerror = function () {
42 | document.body.removeChild(script)
43 | this.onerror = this.onload = null
44 | cb(new Error('Failed to load ' + src), script)
45 | }
46 | }
47 |
48 | function ieOnEnd (script) {
49 | script.onreadystatechange = function () {
50 | if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
51 | this.onreadystatechange = null
52 | for (const cb of callbacks) {
53 | cb(null, script) // there is no way to catch loading errors in IE8
54 | }
55 | callbacks = null
56 | }
57 | }
58 | }
59 |
60 | export default dynamicLoadScript
61 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mall4cloud-platform",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "preinstall": "npx only-allow pnpm",
8 | "dev": "vite",
9 | "build": "vite build",
10 | "preview": "vite preview",
11 | "lint": "eslint --ext .js,.vue src",
12 | "lint:fix": "eslint --fix --ext .js,.vue src",
13 | "lint:staged": "lint-staged"
14 | },
15 | "dependencies": {
16 | "@element-plus/icons-vue": "2.1.0",
17 | "axios": "1.4.0",
18 | "big.js": "6.2.1",
19 | "browser-image-compression": "2.0.2",
20 | "clipboard": "2.0.11",
21 | "crypto-js": "4.1.1",
22 | "default-passive-events": "2.0.0",
23 | "dompurify": "3.0.3",
24 | "echarts": "5.4.2",
25 | "element-plus": "2.3.6",
26 | "js-base64": "3.7.5",
27 | "moment": "2.29.4",
28 | "pinia": "2.0.33",
29 | "pinia-plugin-persistedstate": "3.1.0",
30 | "qs": "6.11.2",
31 | "vue": "3.2.47",
32 | "vue-cookies": "1.8.3",
33 | "vue-draggable-next": "2.2.1",
34 | "vue-i18n": "9.2.2",
35 | "vue-router": "4.2.1",
36 | "vue-slicksort": "2.0.5",
37 | "vuedraggable": "2.24.3"
38 | },
39 | "devDependencies": {
40 | "@iconify-json/ep": "1.1.10",
41 | "@vitejs/plugin-vue": "4.1.0",
42 | "eslint": "8.38.0",
43 | "eslint-config-standard": "17.0.0",
44 | "eslint-plugin-import": "2.25.2",
45 | "eslint-plugin-n": "15.0.0",
46 | "eslint-plugin-promise": "6.0.0",
47 | "eslint-plugin-vue": "9.14.0",
48 | "eslint-plugin-vue-scoped-css": "2.4.0",
49 | "lint-staged": "13.2.2",
50 | "sass": "1.62.1",
51 | "unplugin-auto-import": "0.16.2",
52 | "unplugin-vue-components": "0.24.1",
53 | "vite": "4.3.9",
54 | "vite-plugin-compression": "0.5.1",
55 | "vite-plugin-eslint": "1.8.1",
56 | "vite-plugin-svg-icons": "2.0.1"
57 | },
58 | "engines": {
59 | "node": ">=16",
60 | "pnpm": ">7"
61 | },
62 | "lint-staged": {
63 | "*.{js,vue}": [
64 | "eslint --fix"
65 | ]
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/components/tiny-mce/add-or-upload.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
12 |
13 | 上传图片
14 |
15 |
16 |
17 |
23 |
24 | 上传图片
25 |
26 |
27 |
32 |
33 |
34 |
77 |
82 |
--------------------------------------------------------------------------------
/src/api/product/list.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | export function page (pageParam) {
4 | return request({
5 | url: '/mall4cloud_search/m/search/page',
6 | method: 'get',
7 | params: pageParam
8 | })
9 | }
10 |
11 | export function get (spuId) {
12 | return request({
13 | url: '/mall4cloud_product/admin/spu',
14 | method: 'get',
15 | params: {
16 | spuId
17 | }
18 | })
19 | }
20 |
21 | export function save (data) {
22 | return request({
23 | url: '/mall4cloud_product/admin/spu',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
29 | export function update (data) {
30 | return request({
31 | url: '/mall4cloud_product/admin/spu',
32 | method: 'put',
33 | data
34 | })
35 | }
36 |
37 | export function deleteById (spuId) {
38 | return request({
39 | url: '/mall4cloud_product/admin/spu',
40 | method: 'delete',
41 | params: {
42 | spuId
43 | }
44 | })
45 | }
46 |
47 | // 商品上下架
48 | export function updateProdStatus (data) {
49 | return request({
50 | url: '/mall4cloud_product/admin/spu/prod_status',
51 | method: 'put',
52 | data
53 | })
54 | }
55 |
56 | // 修改spu(名称、价格、库存、序号)信息
57 | export function updatePartProdStatus (data) {
58 | return request({
59 | url: '/mall4cloud_product/admin/spu/update_spu_data',
60 | method: 'put',
61 | data
62 | })
63 | }
64 |
65 | export function examineProdOnShelfApply (data) {
66 | return request({
67 | url: '/mall4cloud_product/admin/product_offline_handle_event/spu_audit',
68 | method: 'POST',
69 | data
70 | })
71 | }
72 |
73 | // 获取最新下线活动详情
74 | export function getOfflineDetailById (prodId) {
75 | return request({
76 | url: `/mall4cloud_product/admin/product_offline_handle_event/get_offline_handle_event_by_prodId/${prodId}`,
77 | method: 'GET'
78 | })
79 | }
80 |
81 | // 申请上线
82 | export function rereapplyOnlineById (data) {
83 | return request({
84 | url: '/mall4cloud_product/admin/product_offline_handle_event/audit_apply',
85 | method: 'POST',
86 | data
87 | })
88 | }
89 |
--------------------------------------------------------------------------------
/src/components/icons-select/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
13 |
14 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
28 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
56 |
57 |
83 |
--------------------------------------------------------------------------------
/src/styles/btn.scss:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
3 | *
4 | * https://www.mall4j.com/
5 | *
6 | * 未经允许,不可做商业用途!
7 | *
8 | * 版权所有,侵权必究!
9 | */
10 | @import './variables.scss';
11 |
12 | @mixin colorBtn($color) {
13 | background: $color;
14 |
15 | &:hover {
16 | color: $color;
17 |
18 | &:before,
19 | &:after {
20 | background: $color;
21 | }
22 | }
23 | }
24 |
25 | .blue-btn {
26 | @include colorBtn($blue)
27 | }
28 |
29 | .light-blue-btn {
30 | @include colorBtn($light-blue)
31 | }
32 |
33 | .red-btn {
34 | @include colorBtn($red)
35 | }
36 |
37 | .pink-btn {
38 | @include colorBtn($pink)
39 | }
40 |
41 | .green-btn {
42 | @include colorBtn($green)
43 | }
44 |
45 | .tiffany-btn {
46 | @include colorBtn($tiffany)
47 | }
48 |
49 | .yellow-btn {
50 | @include colorBtn($yellow)
51 | }
52 |
53 | .pan-btn {
54 | font-size: 14px;
55 | color: #fff;
56 | padding: 14px 36px;
57 | border-radius: 8px;
58 | border: none;
59 | outline: none;
60 | transition: 600ms ease all;
61 | position: relative;
62 | display: inline-block;
63 |
64 | &:hover {
65 | background: #fff;
66 |
67 | &:before,
68 | &:after {
69 | width: 100%;
70 | transition: 600ms ease all;
71 | }
72 | }
73 |
74 | &:before,
75 | &:after {
76 | content: '';
77 | position: absolute;
78 | top: 0;
79 | right: 0;
80 | height: 2px;
81 | width: 0;
82 | transition: 400ms ease all;
83 | }
84 |
85 | &::after {
86 | right: inherit;
87 | top: inherit;
88 | left: 0;
89 | bottom: 0;
90 | }
91 | }
92 |
93 | .custom-button {
94 | display: inline-block;
95 | line-height: 1;
96 | white-space: nowrap;
97 | cursor: pointer;
98 | background: #fff;
99 | color: #fff;
100 | -webkit-appearance: none;
101 | text-align: center;
102 | box-sizing: border-box;
103 | outline: 0;
104 | margin: 0;
105 | padding: 10px 15px;
106 | font-size: 14px;
107 | border-radius: 4px;
108 | }
109 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/preview/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),f=tinymce.util.Tools.resolve("tinymce.Env"),w=tinymce.util.Tools.resolve("tinymce.util.Tools");e.add("preview",function(e){var n,t;function i(){return t.execCommand("mcePreview")}(n=e).addCommand("mcePreview",function(){var e,t;t=function(t){var n="",i=t.dom.encode,e=t.getParam("content_style","","string");n+='';var o=t.getParam("content_css_cors",!1,"boolean")?' crossorigin="anonymous"':"";w.each(t.contentCSS,function(e){n+='"}),e&&(n+='");var a,r,s,c,d,l,m,y=-1===(c=(a=t).getParam("body_id","tinymce","string")).indexOf("=")?c:(s=(r=a).getParam("body_id","","hash"))[r.id]||s,u=-1===(m=(d=t).getParam("body_class","","string")).indexOf("=")?m:(l=d).getParam("body_class","","hash")[l.id]||"",v='
53 |
54 |
88 |
--------------------------------------------------------------------------------
/src/icons/svg/dashboard.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | browser: true,
4 | es2021: true
5 | },
6 | extends: [
7 | 'standard',
8 | './.eslintrc-auto-import.json',
9 | 'plugin:vue/vue3-recommended',
10 | 'plugin:vue-scoped-css/vue3-recommended'
11 | ],
12 | overrides: [
13 | ],
14 | parserOptions: {
15 | ecmaVersion: 'latest',
16 | sourceType: 'module'
17 | },
18 | plugins: [
19 | 'vue'
20 | ],
21 | rules: {
22 | // Possible Errors
23 | // 要求使用 let 或 const 而不是 var
24 | 'no-var': 'error',
25 | // 强制 "for" 循环中更新子句的计数器朝着正确的方向移动
26 | 'for-direction': 'error',
27 | // 强制 getter 函数中出现 return 语句
28 | 'getter-return': 'error',
29 | // 禁止在嵌套的块中出现变量声明或 function 声明
30 | 'no-inner-declarations': 'error',
31 | // 禁止由于 await 或 yield的使用而可能导致出现竞态条件的赋值
32 | 'require-atomic-updates': 'error',
33 | // console 警告
34 | 'no-console': 'warn',
35 | // 禁止出现未使用过的变量
36 | 'no-unused-vars': [
37 | 'warn',
38 | {
39 | args: 'all',
40 | caughtErrors: 'none',
41 | ignoreRestSiblings: true,
42 | vars: 'all',
43 | // 符合规则的参数名将会忽略
44 | argsIgnorePattern: '^[rule, value, i, to, from]'
45 | }
46 | ],
47 | // 关闭名称校验
48 | 'vue/multi-word-component-names': 'off',
49 | // 非生产环境启用 debugger
50 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
51 |
52 | // Best Practices
53 | eqeqeq: 'off',
54 |
55 | // Stylistic Issues
56 | // 强制可嵌套的块的最大深度
57 | 'max-depth': ['error', 5],
58 | // 强制函数最大代码行数
59 | 'max-lines-per-function': [
60 | 'error',
61 | {
62 | max: 150,
63 | skipBlankLines: true
64 | }
65 | ],
66 | // 强制回调函数最大嵌套深度
67 | 'max-nested-callbacks': ['error', { max: 10 }],
68 | // 强制函数定义中最多允许的参数数量
69 | 'max-params': ['error', { max: 5 }],
70 | // 强制每一行中所允许的最大语句数量
71 | 'max-statements-per-line': ['error', { max: 1 }],
72 | // 三目运算符换行
73 | 'multiline-ternary': ['error', 'never'],
74 | // 传值给组件时的使用 kebab-case
75 | 'vue/v-on-event-hyphenation': ['warn', 'always', {
76 | autofix: true,
77 | ignore: []
78 | }],
79 | // 允许 promise.reject()
80 | 'prefer-promise-reject-errors': ['error', {
81 | allowEmptyReject: true
82 | }]
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/autoresize/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";function y(e){return e.getParam("min_height",e.getElement().offsetHeight,"number")}function p(e,t){var n=e.getBody();n&&(n.style.overflowY=t?"":"hidden",t||(n.scrollTop=0))}function v(e,t,n,i){var o=parseInt(e.getStyle(t,n,i),10);return isNaN(o)?0:o}var l=Object.hasOwnProperty,e=tinymce.util.Tools.resolve("tinymce.PluginManager"),b=tinymce.util.Tools.resolve("tinymce.Env"),r=tinymce.util.Tools.resolve("tinymce.util.Delay"),u=function(e,t,n,i,o){r.setEditorTimeout(e,function(){C(e,t),n--?u(e,t,n,i,o):o&&o()},i)},C=function(e,t,n){var i,o,r,s,a,l,u,g,c,m,f,d=e.dom,h=e.getDoc();h&&(e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen()?p(e,!0):(i=h.documentElement,o=e.getParam("autoresize_bottom_margin",50,"number"),r=y(e),s=v(d,i,"margin-top",!0),a=v(d,i,"margin-bottom",!0),(l=(l=i.offsetHeight+s+a+o)<0?0:l)+(u=e.getContainer().offsetHeight-e.getContentAreaContainer().offsetHeight)>y(e)&&(r=l+u),(g=e.getParam("max_height",0,"number"))&&g
2 |
18 |
19 |
20 |
94 |
95 |
105 |
--------------------------------------------------------------------------------
/src/icons/svg/form.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/utils/website-config.js:
--------------------------------------------------------------------------------
1 | // 网站配置默认信息
2 |
3 | // bsLoginLogoImg: require('@/assets/img/website-config/login-logo.png'),
4 | // bsLoginLogoImg: new URL('@/assets/img/website-config/login-logo.png', import.meta.url).href,
5 | // 网站配置默认信息
6 | const configDefInfo = {
7 | // 登录logo
8 | loginBgImg: new URL('@/assets/website-config/login-bg.jpg', import.meta.url).href,
9 | // 版权声明-中文
10 | copyrightCn: 'Copyright © 2018-2022 广州市蓝海创新科技有限公司 版权所有 | 粤ICP备18115813号-1',
11 | // 版权声明-英文
12 | copyrightEn: 'Copyright © 2018-2022 广州市蓝海创新科技有限公司 版权所有 | 粤ICP备18115813号-1',
13 | // 标题文本-中文
14 | titleContentCn: '白洞版-供应商端',
15 | // 标题文本-英文
16 | titleContentEn: '白洞版-供应商端',
17 | // 网站标题图标
18 | titleImg: new URL('@/assets/website-config/title-icon.png', import.meta.url).href,
19 | // 菜单栏顶部图标
20 | bsTopBarIcon: new URL('@/assets/website-config/menu-top-icon.png', import.meta.url).href,
21 | // 菜单展开文本-中文
22 | bsMenuTitleOpenCn: '白洞版-供应商端',
23 | // 菜单展开文本-英文
24 | bsMenuTitleOpenEn: '白洞版-供应商端',
25 | // 菜单收缩文本-中文
26 | bsMenuTitleCloseCn: '供应商端',
27 | // 菜单收缩文本-英文
28 | bsMenuTitleCloseEn: '供应商端'
29 | }
30 |
31 | // 添加图片域名
32 | function addDomain (path) {
33 | const resourcesUrl = import.meta.env.VITE_APP_RESOURCES_URL
34 | if (!path || /^https?:\/\//.test(path)) {
35 | return path
36 | } else {
37 | return resourcesUrl + path
38 | }
39 | }
40 |
41 | // 格式化配置信息
42 | const formatConfigInfo = function (config) {
43 | const data = {}
44 | config = JSON.parse(JSON.stringify(config))
45 | // 检测图片是否携带域名
46 | config.loginBgImg = addDomain(config.loginBgImg)
47 | config.titleImg = addDomain(config.titleImg)
48 | config.bsTopBarIcon = addDomain(config.bsTopBarIcon)
49 |
50 | // 为空使用默认配置
51 | data.loginBgImg = config.loginBgImg || configDefInfo.loginBgImg
52 | data.copyrightCn = config.copyrightCn || configDefInfo.copyrightCn
53 | data.copyrightEn = config.copyrightEn || configDefInfo.copyrightEn
54 | data.titleContentCn = config.titleContentCn || configDefInfo.titleContentCn
55 | data.titleContentEn = config.titleContentEn || configDefInfo.titleContentEn
56 | data.titleImg = config.titleImg || configDefInfo.titleImg
57 | data.bsTopBarIcon = config.bsTopBarIcon || configDefInfo.bsTopBarIcon
58 | data.bsMenuTitleOpenCn = config.bsMenuTitleOpenCn || configDefInfo.bsMenuTitleOpenCn
59 | data.bsMenuTitleOpenEn = config.bsMenuTitleOpenEn || configDefInfo.bsMenuTitleOpenEn
60 | data.bsMenuTitleCloseCn = config.bsMenuTitleCloseCn || configDefInfo.bsMenuTitleCloseCn
61 | data.bsMenuTitleCloseEn = config.bsMenuTitleCloseEn || configDefInfo.bsMenuTitleCloseEn
62 | return Object.assign(config, data)
63 | }
64 |
65 | export { configDefInfo, formatConfigInfo }
66 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/anchor/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";function a(e){return e.getAttribute("id")||e.getAttribute("name")||""}function c(e){return e&&"a"===e.nodeName.toLowerCase()&&!e.getAttribute("href")&&""!==a(e)}function d(e){return e.dom.getParent(e.selection.getStart(),l)}function r(e,t){var o,a,n,r,i,l=d(e);l?(n=e,r=t,(i=l).removeAttribute("name"),i.id=r,n.addVisual(),n.undoManager.add()):(a=t,(o=e).undoManager.transact(function(){var e,n;o.getParam("allow_html_in_named_anchor",!1,"boolean")||o.selection.collapse(!0),o.selection.isCollapsed()?o.insertContent(o.dom.createHTML("a",{id:a})):(n=(e=o).dom,u(n).walk(e.selection.getRng(),function(e){s.each(e,function(e){var t;c(t=e)&&!t.firstChild&&n.remove(e,!1)})}),o.formatter.remove("namedAnchor",null,null,!0),o.formatter.apply("namedAnchor",{value:a}),o.addVisual())})),e.focus()}function i(r){return function(e){for(var t,n=0;n=(h="www.").length&&g.substr(0,0+h.length)===h?c=m+"://"+c:-1===c.indexOf("@")||/^([A-Za-z][A-Za-z\d.+-]*:\/\/)|mailto:/.test(c)||(c="mailto:"+c),o=e.selection.getBookmark(),e.selection.setRng(d),e.execCommand("createlink",!1,c),!1!==s&&e.dom.setAttrib(e.selection.getNode(),"target",s),e.selection.moveToBookmark(o),e.nodeChanged())}}var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=tinymce.util.Tools.resolve("tinymce.Env"),A=new RegExp("^"+/(?:[A-Za-z][A-Za-z\d.+-]{0,14}:\/\/(?:[-.~*+=!&;:'%@?^${}(),\w]+@)?|www\.|[-;:&=+$,.\w]+@)[A-Za-z\d-]+(?:\.[A-Za-z\d-]+)*(?::\d+)?(?:\/(?:[-+~=.,%()\/\w]*[-+~=%()\/\w])?)?(?:\?(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?(?:#(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?/g.source+"$","i");e.add("autolink",function(e){var t,n;(t=e).on("keydown",function(e){if(13===e.keyCode)return r(t,-1)}),a.browser.isIE()?t.on("focus",function(){if(!n){n=!0;try{t.execCommand("AutoUrlDetect",!1,!0)}catch(e){}}}):(t.on("keypress",function(e){if(41===e.keyCode||93===e.keyCode||125===e.keyCode)return r(t,-1)}),t.on("keyup",function(e){if(32===e.keyCode)return r(t,0)}))})}();
--------------------------------------------------------------------------------
/src/lang/zhCn.js:
--------------------------------------------------------------------------------
1 | import spu from './product/spu/zh'
2 | import attr from './product/attr/zh'
3 | import category from './product/category/zh'
4 | import notice from './multishop/notice/zh'
5 | import shopUser from './multishop/shop-user/zh'
6 | import hotSearch from './multishop/hot-search/zh'
7 | import imgbox from './biz/imgbox/zh'
8 | import role from './rbac/role/zh'
9 | import menu from './rbac/menu/zh'
10 | import menuPermission from './rbac/menu-permission/zh'
11 | import selector from './components/category-selector/zh'
12 | import shopUserAccount from './multishop/shop-user-account/zh'
13 | import order from './order/order/zh'
14 | import constant from './constant/zh'
15 | import admin from './admin/zh'
16 | import shop from './shop/zh'
17 | import address from './address/zh'
18 | import product from './product/zh'
19 |
20 | export default {
21 | language: '简体中文',
22 | route: {
23 | dashboard: '首页'
24 | },
25 | tip: {
26 | select: '请选择',
27 | input: '请输入'
28 | },
29 | navbar: {
30 | logOut: '退出登录'
31 | },
32 | tagsView: {
33 | refresh: '刷新',
34 | close: '关闭',
35 | closeOthers: '关闭其它',
36 | closeAll: '关闭所有'
37 | },
38 | date: {
39 | start: '开始日期',
40 | end: '结束日期',
41 | tip: '至',
42 | t: '今日',
43 | y: '昨日',
44 | n: '近7天',
45 | m: '近30天',
46 | a: '全部'
47 | },
48 | login: {
49 | title: '系统登录',
50 | logIn: '登录',
51 | username: '账号',
52 | password: '密码',
53 | any: '随便填',
54 | thirdparty: '第三方登录',
55 | thirdpartyTips: '本地不能模拟,请结合自己业务进行模拟!!!'
56 | },
57 | unit: {
58 | dollar: '元'
59 | },
60 | table: {
61 | search: '搜索',
62 | add: '添加',
63 | export: '导出',
64 | id: '序号',
65 | status: '状态',
66 | actions: '操作',
67 | edit: '编辑',
68 | create: '新建',
69 | clear: '清空',
70 | publish: '发布',
71 | delete: '删除',
72 | cancel: '取消',
73 | confirm: '确定',
74 | offline: '下线',
75 | seq: '排序号',
76 | actionSuccess: '操作成功',
77 | tips: '提示',
78 | noNull: '不能为空',
79 | sureToDelete: '确定进行删除操作?',
80 | createTime: '创建时间',
81 | updateTime: '更新时间'
82 | },
83 | action: {
84 | putOnShelf: '上架',
85 | offShelf: '下架'
86 | },
87 | rbac: {
88 | role,
89 | menu,
90 | menuPermission
91 | },
92 | multishop: {
93 | hotSearch,
94 | shopUser,
95 | notice,
96 | shopUserAccount
97 | },
98 | product: {
99 | ...product,
100 | attr,
101 | category,
102 | spu
103 | },
104 | biz: {
105 | imgbox
106 | },
107 | order: {
108 | order
109 | },
110 | constant: {
111 | ...constant
112 | },
113 | admin: {
114 | ...admin
115 | },
116 | shop: {
117 | ...shop
118 | },
119 | address: {
120 | ...address
121 | },
122 | components: {
123 | selector
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/stores/modules/permission.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
3 | *
4 | * https://www.mall4j.com/
5 | *
6 | * 未经允许,不可做商业用途!
7 | *
8 | * 版权所有,侵权必究!
9 | */
10 |
11 | import { defineStore } from 'pinia'
12 | import { constantRoutes } from '@/router/index.js'
13 | import { menuList } from '@/api/rbac/menu.js'
14 | import { useUserStore } from '@/stores/modules/user.js'
15 |
16 | const modules = import.meta.glob('../../views/modules/**/**.vue')
17 | const Layout = () => import('@/layout/index.vue')
18 |
19 | /**
20 | * 递归过滤有权限的异步(动态)路由
21 | *
22 | * @param routes 所有的菜单(路由)
23 | * @param menuIds 用户拥有的菜单id
24 | * @returns 返回用户有权限的异步(动态)路由
25 | */
26 | const filterAsyncRoutes = (routes, menuIds) => {
27 | const res = []
28 | routes.forEach(route => {
29 | if (menuIds.indexOf(route.id) > -1) {
30 | res.push(route)
31 | }
32 | })
33 | return res
34 | }
35 |
36 | const loadView = (view) => {
37 | return modules[`../../views/modules/${view}/index.vue`] || modules[`../../views/modules/${view}.vue`]
38 | }
39 |
40 | export const usePermissionStore = defineStore('permissionStore', {
41 | state: () => {
42 | return {
43 | routes: [],
44 | addRoutes: [],
45 | dashboard: '',
46 | menuIds: [],
47 | secondaryMenuList: []
48 | }
49 | },
50 | actions: {
51 | setRoutes (routes) {
52 | this.addRoutes = routes
53 | this.routes = constantRoutes.concat(routes)
54 | this.routes.forEach(item => {
55 | if (item.children) {
56 | item.children.forEach(res => {
57 | if (res.children) {
58 | this.menuIds.push(res.id + '')
59 | }
60 | if (res.children && res.children.length > 0) {
61 | this.secondaryMenuList.push(res)
62 | }
63 | })
64 | }
65 | })
66 | },
67 | /**
68 | * 生成动态路由
69 | *
70 | * @param menuIds
71 | * @returns
72 | */
73 | generateRoutes (menuIds) {
74 | return new Promise((resolve, reject) => {
75 | menuList().then(menuList => {
76 | for (const menu of menuList) {
77 | // menu.path = menu.path[0] === '/' ? menu.path[0] : '/' + menu.path
78 | if (menu.component === 'Layout') {
79 | menu.component = Layout
80 | } else {
81 | menu.component = loadView(menu.component)
82 | }
83 | }
84 | const isAdmin = useUserStore().isAdmin
85 | if (!isAdmin) {
86 | menuList = filterAsyncRoutes(menuList, menuIds)
87 | }
88 | const accessedRoutes = treeDataTranslate(menuList)
89 | this.setRoutes(accessedRoutes)
90 | useCommonStore().updateRouteList(accessedRoutes)
91 | resolve(accessedRoutes)
92 | }).catch(error => {
93 | reject(error)
94 | })
95 | })
96 | }
97 | }
98 | })
99 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 | import path from 'path'
4 | import AutoImport from 'unplugin-auto-import/vite'
5 | import Components from 'unplugin-vue-components/vite'
6 | import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
7 | import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
8 | import viteCompression from 'vite-plugin-compression'
9 |
10 | // eslint
11 | import eslintPlugin from 'vite-plugin-eslint'
12 |
13 | // https://vitejs.dev/config/
14 | export default defineConfig(({ command }) => {
15 | return {
16 | plugins: [
17 | vue(),
18 | createSvgIconsPlugin({
19 | iconDirs: [path.resolve(process.cwd(), 'src/icons/svg')],
20 | symbolId: 'icon-[dir]-[name]'
21 | }),
22 | // 自动引入内容
23 | AutoImport({
24 | imports: [
25 | 'vue',
26 | 'vue-router'
27 | ],
28 | dirs: [
29 | 'src/hooks/**',
30 | 'src/stores/**',
31 | 'src/utils/**'
32 | ],
33 | resolvers: command === 'build' ? [ElementPlusResolver()] : [],
34 | dts: 'src/auto-import/imports.d.ts',
35 | eslintrc: {
36 | enabled: false
37 | }
38 | }),
39 | // 自动引入组件
40 | Components({
41 | dirs: [
42 | 'src/components'
43 | ],
44 | resolvers: command === 'build' ? [ElementPlusResolver()] : [],
45 | dts: 'src/auto-import/components.d.ts'
46 | }),
47 | // eslint
48 | eslintPlugin({
49 | include: ['src/**/*.js', 'src/**/*.vue', 'src/*.js', 'src/*.vue']
50 | }),
51 | // 对大于 1k 的文件进行压缩
52 | viteCompression({
53 | threshold: 1000,
54 | })
55 | ],
56 | server: {
57 | host: true,
58 | port: 9527,
59 | open: true
60 | },
61 | resolve: {
62 | alias: {
63 | '@': path.resolve(__dirname, 'src'),
64 | 'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js'
65 | }
66 | },
67 | build: {
68 | base: './',
69 | rollupOptions: {
70 | // 静态资源分类打包
71 | output: {
72 | chunkFileNames: 'static/js/[name]-[hash].js',
73 | entryFileNames: 'static/js/[name]-[hash].js',
74 | assetFileNames: 'static/[ext]/[name]-[hash].[ext]',
75 | // 静态资源分拆打包
76 | manualChunks (id) {
77 | if (id.includes('node_modules')) {
78 | if (id.toString().indexOf('.pnpm/') !== -1) {
79 | return id.toString().split('.pnpm/')[1].split('/')[0].toString();
80 | } else if (id.toString().indexOf('node_modules/') !== -1) {
81 | return id.toString().split('node_modules/')[1].split('/')[0].toString();
82 | }
83 | }
84 | }
85 | }
86 | },
87 | sourcemap: false,
88 | target: 'es2015',
89 | reportCompressedSize: false
90 | }
91 | }
92 | })
93 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/autosave/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";function o(t,e){var r=t||e,n=/^(\d+)([ms]?)$/.exec(""+r);return(n[2]?{s:1e3,m:6e4}[n[2]]:1)*parseInt(r,10)}function n(t){var e=document.location;return t.getParam("autosave_prefix","tinymce-autosave-{path}{query}{hash}-{id}-").replace(/{path}/g,e.pathname).replace(/{query}/g,e.search).replace(/{hash}/g,e.hash).replace(/{id}/g,t.id)}function i(t,e){if(a(e))return t.dom.isEmpty(t.getBody());var r=d.trim(e);if(""===r)return!0;var n=(new DOMParser).parseFromString(r,"text/html");return t.dom.isEmpty(n)}function u(t){var e=parseInt(v.getItem(n(t)+"time"),10)||0;return!((new Date).getTime()-e>o(t.getParam("autosave_retention"),"20m")&&(g(t,!1),1))}function s(t){var e=n(t);!i(t)&&t.isDirty()&&(v.setItem(e+"draft",t.getContent({format:"raw",no_events:!0})),v.setItem(e+"time",(new Date).getTime().toString()),t.fire("StoreDraft"))}function f(t){var e=n(t);u(t)&&(t.setContent(v.getItem(e+"draft"),{format:"raw"}),t.fire("RestoreDraft"))}function c(t){t.undoManager.transact(function(){f(t),g(t)}),t.focus()}function m(r){return function(t){function e(){return t.setDisabled(!u(r))}return t.setDisabled(!u(r)),r.on("StoreDraft RestoreDraft RemoveDraft",e),function(){return r.off("StoreDraft RestoreDraft RemoveDraft",e)}}}var t=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=function(t){return void 0===t},l=tinymce.util.Tools.resolve("tinymce.util.Delay"),v=tinymce.util.Tools.resolve("tinymce.util.LocalStorage"),d=tinymce.util.Tools.resolve("tinymce.util.Tools"),g=function(t,e){var r=n(t);v.removeItem(r+"draft"),v.removeItem(r+"time"),!1!==e&&t.fire("RemoveDraft")},y=tinymce.util.Tools.resolve("tinymce.EditorManager");t.add("autosave",function(t){var e,r,n,a;return t.editorManager.on("BeforeUnload",function(t){var e;d.each(y.get(),function(t){t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&t.getParam("autosave_ask_before_unload",!0)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))}),e&&(t.preventDefault(),t.returnValue=e)}),n=e=t,a=o(n.getParam("autosave_interval"),"30s"),l.setEditorInterval(n,function(){s(n)},a),e.ui.registry.addButton("restoredraft",{tooltip:"Restore last draft",icon:"restore-draft",onAction:function(){c(e)},onSetup:m(e)}),e.ui.registry.addMenuItem("restoredraft",{text:"Restore last draft",icon:"restore-draft",onAction:function(){c(e)},onSetup:m(e)}),t.on("init",function(){t.getParam("autosave_restore_when_empty",!1)&&t.dom.isEmpty(t.getBody())&&f(t)}),r=t,{hasDraft:function(){return u(r)},storeDraft:function(){return s(r)},restoreDraft:function(){return f(r)},removeDraft:function(t){return g(r,t)},isEmpty:function(t){return i(r,t)}}})}();
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/legacyoutput/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),l=tinymce.util.Tools.resolve("tinymce.util.Tools");e.add("legacyoutput",function(e){var s,t;(t=s=e).settings.inline_styles=!1,t.getParam("fontsize_formats")||(t.settings.fontsize_formats="8pt=1 10pt=2 12pt=3 14pt=4 18pt=5 24pt=6 36pt=7"),t.getParam("font_formats")||(t.settings.font_formats="Andale Mono=andale mono,monospace;Arial=arial,helvetica,sans-serif;Arial Black=arial black,sans-serif;Book Antiqua=book antiqua,palatino,serif;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,palatino,serif;Helvetica=helvetica,arial,sans-serif;Impact=impact,sans-serif;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco,monospace;Times New Roman=times new roman,times,serif;Trebuchet MS=trebuchet ms,geneva,sans-serif;Verdana=verdana,geneva,sans-serif;Webdings=webdings;Wingdings=wingdings,zapf dingbats"),s.on("PreInit",function(){var e=s,t="p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table",i=l.explode(e.getParam("font_size_style_values","xx-small,x-small,small,medium,large,x-large,xx-large")),a=e.schema;e.formatter.register({alignleft:{selector:t,attributes:{align:"left"}},aligncenter:{selector:t,attributes:{align:"center"}},alignright:{selector:t,attributes:{align:"right"}},alignjustify:{selector:t,attributes:{align:"justify"}},bold:[{inline:"b",remove:"all",preserve_attributes:["class","style"]},{inline:"strong",remove:"all",preserve_attributes:["class","style"]},{inline:"span",styles:{fontWeight:"bold"}}],italic:[{inline:"i",remove:"all",preserve_attributes:["class","style"]},{inline:"em",remove:"all",preserve_attributes:["class","style"]},{inline:"span",styles:{fontStyle:"italic"}}],underline:[{inline:"u",remove:"all",preserve_attributes:["class","style"]},{inline:"span",styles:{textDecoration:"underline"},exact:!0}],strikethrough:[{inline:"strike",remove:"all",preserve_attributes:["class","style"]},{inline:"span",styles:{textDecoration:"line-through"},exact:!0}],fontname:{inline:"font",toggle:!1,attributes:{face:"%value"}},fontsize:{inline:"font",toggle:!1,attributes:{size:function(e){return String(l.inArray(i,e.value)+1)}}},forecolor:{inline:"font",attributes:{color:"%value"},links:!0,remove_similar:!0,clear_child_styles:!0},hilitecolor:{inline:"font",styles:{backgroundColor:"%value"},links:!0,remove_similar:!0,clear_child_styles:!0}}),l.each("b,i,u,strike".split(","),function(e){a.addValidElements(e+"[*]")}),a.getElementRule("font")||a.addValidElements("font[face|size|color|style]"),l.each(t.split(","),function(e){var t=a.getElementRule(e);t&&(t.attributes.align||(t.attributes.align={},t.attributesOrder.push("align")))})})})}();
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/insertdatetime/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";function l(e){return e.getParam("insertdatetime_timeformat",e.translate("%H:%M:%S"))}function s(e){return e.getParam("insertdatetime_formats",["%H:%M:%S","%Y-%m-%d","%I:%M:%S %p","%D"])}function r(e,t){if((e=""+e).length'+n+"")):e.insertContent(d(e,t))}var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),a="Sun Mon Tue Wed Thu Fri Sat Sun".split(" "),i="Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(" "),o="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),u="January February March April May June July August September October November December".split(" "),g=tinymce.util.Tools.resolve("tinymce.util.Tools");e.add("insertdatetime",function(e){var n,r,t,a,i,o,u,c;function m(e){return r.execCommand("mceInsertDate",!1,e)}(n=e).addCommand("mceInsertDate",function(e,t){p(n,null!=t?t:n.getParam("insertdatetime_dateformat",n.translate("%Y-%m-%d")))}),n.addCommand("mceInsertTime",function(e,t){p(n,null!=t?t:l(n))}),u=s(r=e),t=0<(o=s(i=r)).length?o[0]:l(i),a=t,c={get:function(){return a},set:function(e){a=e}},r.ui.registry.addSplitButton("insertdatetime",{icon:"insert-time",tooltip:"Insert date/time",select:function(e){return e===c.get()},fetch:function(e){e(g.map(u,function(e){return{type:"choiceitem",text:d(r,e),value:e}}))},onAction:function(e){m(c.get())},onItemAction:function(e,t){c.set(t),m(t)}}),r.ui.registry.addNestedMenuItem("insertdatetime",{icon:"insert-time",text:"Date/time",getSubmenuItems:function(){return g.map(u,function(e){return{type:"menuitem",text:d(r,e),onAction:(t=e,function(){c.set(t),m(t)})};var t})}})})}();
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/bbcode/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";function i(t){function o(o,e){t=t.replace(o,e)}return t=n.trim(t),o(/\n/gi,"
"),o(/\[b\]/gi,""),o(/\[\/b\]/gi,""),o(/\[i\]/gi,""),o(/\[\/i\]/gi,""),o(/\[u\]/gi,""),o(/\[\/u\]/gi,""),o(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'$2'),o(/\[url\](.*?)\[\/url\]/gi,'$1'),o(/\[img\](.*?)\[\/img\]/gi,'
'),o(/\[color=(.*?)\](.*?)\[\/color\]/gi,'$2'),o(/\[code\](.*?)\[\/code\]/gi,'$1 '),o(/\[quote.*?\](.*?)\[\/quote\]/gi,'$1 '),t}var o=tinymce.util.Tools.resolve("tinymce.PluginManager"),n=tinymce.util.Tools.resolve("tinymce.util.Tools");o.add("bbcode",function(o){o.on("BeforeSetContent",function(o){o.content=i(o.content)}),o.on("PostProcess",function(o){function e(o,e){t=t.replace(o,e)}var t;o.set&&(o.content=i(o.content)),o.get&&(o.content=(t=o.content,t=n.trim(t),e(/(.*?)<\/a>/gi,"[url=$1]$2[/url]"),e(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),e(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),e(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),e(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),e(/(.*?)<\/span>/gi,"[color=$1]$2[/color]"),e(/(.*?)<\/font>/gi,"[color=$1]$2[/color]"),e(/(.*?)<\/span>/gi,"[size=$1]$2[/size]"),e(/(.*?)<\/font>/gi,"$1"),e(//gi,"[img]$1[/img]"),e(/(.*?)<\/span>/gi,"[code]$1[/code]"),e(/(.*?)<\/span>/gi,"[quote]$1[/quote]"),e(/(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),e(/(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),e(/(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),e(/(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),e(/(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),e(/(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),e(/<\/(strong|b)>/gi,"[/b]"),e(/<(strong|b)>/gi,"[b]"),e(/<\/(em|i)>/gi,"[/i]"),e(/<(em|i)>/gi,"[i]"),e(/<\/u>/gi,"[/u]"),e(/(.*?)<\/span>/gi,"[u]$1[/u]"),e(//gi,"[u]"),e(/]*>/gi,"[quote]"),e(/<\/blockquote>/gi,"[/quote]"),e(/
/gi,"\n"),e(/
/gi,"\n"),e(/
/gi,"\n"),e(//gi,""),e(/<\/p>/gi,"\n"),e(/ |\u00a0/gi," "),e(/"/gi,'"'),e(/</gi,"<"),e(/>/gi,">"),e(/&/gi,"&"),t))})})}();
--------------------------------------------------------------------------------
/src/lang/en.js:
--------------------------------------------------------------------------------
1 | import spu from './product/spu/en'
2 | import attr from './product/attr/en'
3 | import category from './product/category/en'
4 | import notice from './multishop/notice/en'
5 | import shopUser from './multishop/shop-user/en'
6 | import hotSearch from './multishop/hot-search/en'
7 | import imgbox from './biz/imgbox/en'
8 | import role from './rbac/role/en'
9 | import menu from './rbac/menu/en'
10 | import menuPermission from './rbac/menu-permission/en'
11 | import selector from './components/category-selector/en'
12 | import shopUserAccount from './multishop/shop-user-account/en'
13 | import order from './order/order/en'
14 | import constant from './constant/en'
15 | import admin from './admin/en'
16 | import shop from './shop/en'
17 | import address from './address/en'
18 | import product from './product/en'
19 |
20 | export default {
21 | language: 'English',
22 | route: {
23 | dashboard: 'Dashboard'
24 | },
25 | navbar: {
26 | logOut: 'Log Out'
27 | },
28 | tip: {
29 | select: 'please select prod',
30 | input: 'please input'
31 | },
32 | tagsView: {
33 | refresh: 'Refresh',
34 | close: 'Close',
35 | closeOthers: 'Close Others',
36 | closeAll: 'Close All'
37 | },
38 | date: {
39 | start: 'Start date',
40 | end: 'End date',
41 | tip: 'to',
42 | t: 'today',
43 | y: 'yesterday',
44 | n: 'nearly 7',
45 | m: 'nearly 30',
46 | a: 'whole'
47 | },
48 | login: {
49 | title: 'Login Form',
50 | logIn: 'Login',
51 | username: 'Username',
52 | password: 'Password',
53 | any: 'any',
54 | thirdparty: 'Or connect with',
55 | thirdpartyTips: 'Can not be simulated on local, so please combine you own business simulation! ! !'
56 | },
57 | unit: {
58 | dollar: 'yuan'
59 | },
60 | table: {
61 | search: 'Search',
62 | add: 'Add',
63 | export: 'Export',
64 | id: 'ID',
65 | status: 'Status',
66 | actions: 'Actions',
67 | edit: 'Edit',
68 | create: 'Create',
69 | publish: 'Publish',
70 | delete: 'Delete',
71 | cancel: 'Cancel',
72 | offline: 'Offline',
73 | clear: 'Clear',
74 | confirm: 'Confirm',
75 | actionSuccess: 'Actions Success',
76 | tips: 'Tips',
77 | seq: 'Queue number',
78 | sureToDelete: 'Be sure to delete?',
79 | createTime: 'create time',
80 | updateTime: 'update time'
81 | },
82 | action: {
83 | putOnShelf: 'Put on the shelf',
84 | offShelf: 'off the shelf'
85 | },
86 | rbac: {
87 | role,
88 | menu,
89 | menuPermission
90 | },
91 | multishop: {
92 | notice,
93 | shopUser,
94 | hotSearch,
95 | shopUserAccount
96 | },
97 | product: {
98 | ...product,
99 | attr,
100 | category,
101 | spu
102 | },
103 | biz: {
104 | imgbox
105 | },
106 | order: {
107 | order
108 | },
109 | constant: {
110 | ...constant
111 | },
112 | admin: {
113 | ...admin
114 | },
115 | shop: {
116 | ...shop
117 | },
118 | address: {
119 | ...address
120 | },
121 | components: {
122 | selector
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/components/img-upload/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
![]()
14 |
18 |
19 |
20 |
21 |
22 |
23 |
28 |
32 |
37 |
38 |
39 |
40 |
41 |
99 |
100 |
135 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/toc/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";function a(t){return t.getParam("toc_class","mce-toc")}function s(t){var e=t.getParam("toc_header","h2");return/^h[1-6]$/.test(e)?e:"h2"}function u(n){return function(t){function e(){return t.setDisabled(n.mode.isReadOnly()||!(0","<"+e+' contenteditable="true">'+m.DOM.encode(n)+o);for(var l=0;l";else for(var d=c;d";if(i+=''+a.title+"",u!==a.level&&u)for(d=a.level;u":"";else i+="",u||(i+="");c=a.level}return i}function f(t){var e=a(t),n=t.$("."+e);n.length&&t.undoManager.transact(function(){n.html(d(t))})}var t,e=tinymce.util.Tools.resolve("tinymce.PluginManager"),m=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),v=tinymce.util.Tools.resolve("tinymce.util.I18n"),c=tinymce.util.Tools.resolve("tinymce.util.Tools"),l=(t=0,function(){return"mcetoc_"+(new Date).getTime().toString(32)+(t++).toString(32)}),g=function(n){var t,o=a(n),e=s(n),i=function(t){for(var e=[],n=1;n<=t;n++)e.push("h"+n);return e.join(",")}(1<=(t=parseInt(n.getParam("toc_depth","3"),10))&&t<=9?t:3),r=n.$(i);return r.length&&/^h[1-9]$/i.test(e)&&(r=r.filter(function(t,e){return!n.dom.hasClass(e.parentNode,o)})),c.map(r,function(t){return{id:t.id||l(),level:parseInt(t.nodeName.replace(/^H/i,""),10),title:n.$.text(t),element:t}})};e.add("toc",function(t){var c,e,n,o,i,r;function l(){return i.execCommand("mceInsertToc")}(c=t).addCommand("mceInsertToc",function(){var t,e,n,o,i,r;o=a(t=c),i=t.$("."+o),r=t,!i.length||0'+n+"")):f(t)}),c.addCommand("mceUpdateToc",function(){f(c)}),(i=t).ui.registry.addButton("toc",{icon:"toc",tooltip:"Table of contents",onAction:l,onSetup:u(i)}),i.ui.registry.addButton("tocupdate",{icon:"reload",tooltip:"Update",onAction:function(){return i.execCommand("mceUpdateToc")}}),i.ui.registry.addMenuItem("toc",{icon:"toc",text:"Table of contents",onAction:l,onSetup:u(i)}),i.ui.registry.addContextToolbar("toc",{items:"tocupdate",predicate:(r=i,function(t){return t&&r.dom.is(t,"."+a(r))&&r.getBody().contains(t)}),scope:"node",position:"node"}),n=(e=t).$,o=a(e),e.on("PreProcess",function(t){var e=n("."+o,t.node);e.length&&(e.removeAttr("contentEditable"),e.find("[contenteditable]").removeAttr("contentEditable"))}),e.on("SetContent",function(){var t=n("."+o);t.length&&(t.attr("contentEditable",!1),t.children(":first-child").attr("contentEditable",!0))})})}();
--------------------------------------------------------------------------------
/src/components/spu-category-attrs/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
15 | {{ attrs.name }}
16 |
17 |
24 |
30 |
31 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
62 |
63 |
114 |
--------------------------------------------------------------------------------
/src/stores/modules/user.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
3 | *
4 | * https://www.mall4j.com/
5 | *
6 | * 未经允许,不可做商业用途!
7 | *
8 | * 版权所有,侵权必究!
9 | */
10 | import { defineStore } from 'pinia'
11 | import { login, logout } from '@/api/auth/auth'
12 | import { shopUserInfo } from '@/api/multishop/shop-user'
13 | import { menuPermissionsList } from '@/api/rbac/menu-permission'
14 | import { listMenuIds } from '@/api/rbac/menu'
15 | import { getToken, setToken, removeToken } from '@/utils/auth'
16 | import { resetRouter } from '@/router'
17 |
18 | export const useUserStore = defineStore('user', {
19 | state: () => {
20 | return {
21 | token: getToken(),
22 | name: '',
23 | avatar: '',
24 | introduction: '',
25 | isAdmin: 0,
26 | roles: []
27 | }
28 | },
29 | actions: {
30 | // 登录
31 | login (loginData) {
32 | return new Promise((resolve, reject) => {
33 | const { username, password, captcha } = loginData
34 | login({ principal: username.trim(), credentials: password, captchaVerification: captcha, sysType: 1 }).then(response => {
35 | this.token = response.accessToken
36 | setToken(response.accessToken)
37 | resolve()
38 | }).catch(error => {
39 | reject(error)
40 | })
41 | })
42 | },
43 | // get userInfo
44 | getUserInfo () {
45 | return new Promise((resolve, reject) => {
46 | shopUserInfo().then(shopUser => {
47 | this.name = shopUser.nickName
48 | this.avatar = shopUser.avatar
49 | this.isAdmin = shopUser.isAdmin
50 | resolve(shopUser)
51 | }).catch(error => {
52 | reject(error)
53 | })
54 | })
55 | },
56 |
57 | // 获取权限列表
58 | listPermissions () {
59 | return new Promise((resolve, reject) => {
60 | if (this.isAdmin) {
61 | this.roles = ['']
62 | resolve([''])
63 | return
64 | }
65 | menuPermissionsList().then(permissions => {
66 | if (!permissions) {
67 | reject(new Error('Verification failed, please Login again.'))
68 | }
69 | // roles must be a non-empty array
70 | if (!permissions || permissions.length <= 0) {
71 | permissions = ['']
72 | }
73 | this.roles = permissions
74 | resolve(permissions)
75 | }).catch(error => {
76 | reject(error)
77 | })
78 | })
79 | },
80 | // 获取拥有的菜单id
81 | listMenuIds () {
82 | return new Promise((resolve, reject) => {
83 | listMenuIds().then(menuIds => {
84 | resolve(menuIds)
85 | }).catch(error => {
86 | reject(error)
87 | })
88 | })
89 | },
90 |
91 | // 登出
92 | logout () {
93 | return new Promise((resolve, reject) => {
94 | logout().then(() => {
95 | this.token = ''
96 | this.roles = []
97 | this.resetToken()
98 | resetRouter()
99 | resolve()
100 | }).catch(error => {
101 | reject(error)
102 | })
103 | })
104 | },
105 | // 重置token
106 | resetToken () {
107 | this.token = ''
108 | removeToken()
109 | this.roles = []
110 | }
111 | }
112 | })
113 |
--------------------------------------------------------------------------------
/public/static/js/tinymce/js/tinymce/plugins/advlist/plugin.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3 | * Licensed under the LGPL or a commercial license.
4 | * For LGPL see License.txt in the project root for license information.
5 | * For commercial licenses see https://www.tiny.cloud/
6 | *
7 | * Version: 5.10.1 (2021-11-03)
8 | */
9 | !function(){"use strict";function f(t,e,n){t.execCommand("UL"===e?"InsertUnorderedList":"InsertOrderedList",!1,!1===n?null:{"list-style-type":n})}function i(t){return function(){return t}}function t(t){return t}function e(){return s}var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),g=tinymce.util.Tools.resolve("tinymce.util.Tools"),u=i(!1),l=i(!0),s={fold:function(t,e){return t()},isSome:u,isNone:l,getOr:t,getOrThunk:r,getOrDie:function(t){throw new Error(t||"error: getOrDie called on none.")},getOrNull:i(null),getOrUndefined:i(void 0),or:t,orThunk:r,map:e,each:function(){},bind:e,exists:u,forall:l,filter:function(){return s},toArray:function(){return[]},toString:i("none()")};function r(t){return t()}function d(t){return t&&/^(TH|TD)$/.test(t.nodeName)}function m(c,a){return function(s){function t(t){var e,n,r,o,i,u,l;s.setActive((e=c,r=a,i=-1!==(o=function(t,e){for(var n=0;n