├── 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 | 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 | 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 | 7 | 8 | 10 | 12 | 13 | 14 | 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 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 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 | 7 | 8 | 10 | 13 | 14 | 15 | 16 | 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 | 13 | 14 | 37 | 38 | 40 | -------------------------------------------------------------------------------- /src/icons/svg/index.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 10 | 12 | 14 | 15 | 16 | 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 | 7 | 8 | 10 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/icons/svg/live.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 10 | 14 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/icons/svg/group.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 10 | 12 | 14 | 16 | 17 | 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 | 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 | 7 | 8 | 10 | 12 | 15 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/icons/svg-icon.vue: -------------------------------------------------------------------------------- 1 | 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 | 7 | 8 | 10 | 13 | 14 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/icons/svg/icon-zhedie.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 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 | 14 | 15 | -------------------------------------------------------------------------------- /src/icons/svg/product.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | 15 | -------------------------------------------------------------------------------- /src/icons/svg/eye-open.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/layout/components/Sidebar/main-sidebar-sub-menu.vue: -------------------------------------------------------------------------------- 1 | 2 | 11 | 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 | 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 | 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 | 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 | 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 |
6 | 17 |
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 | 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 | 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