Initial commit
5
promo-ui2/.browserslistrc
Normal file
@@ -0,0 +1,5 @@
|
||||
Android 4.1
|
||||
IOS 7.1
|
||||
Chrome > 31
|
||||
ff > 31
|
||||
ie >= 11
|
||||
23
promo-ui2/.env.base
Normal file
@@ -0,0 +1,23 @@
|
||||
# 环境
|
||||
VITE_NODE_ENV=development
|
||||
|
||||
# 接口前缀
|
||||
VITE_API_BASE_PATH=http://localhost:8081
|
||||
|
||||
# 打包路径
|
||||
VITE_BASE_PATH=/
|
||||
|
||||
# 标题
|
||||
VITE_APP_TITLE=推广后台
|
||||
|
||||
# 是否全量引入element-plus样式
|
||||
VITE_USE_ALL_ELEMENT_PLUS_STYLE=true
|
||||
|
||||
# 是否开启mock
|
||||
VITE_USE_MOCK=true
|
||||
|
||||
# 是否使用在线图标
|
||||
VITE_USE_ONLINE_ICON=true
|
||||
|
||||
# 是否隐藏全局设置按钮
|
||||
VITE_HIDE_GLOBAL_SETTING=false
|
||||
41
promo-ui2/.env.dev
Normal file
@@ -0,0 +1,41 @@
|
||||
# 环境
|
||||
VITE_NODE_ENV=production
|
||||
|
||||
# 接口前缀
|
||||
VITE_API_BASE_PATH=
|
||||
|
||||
# 打包路径
|
||||
VITE_BASE_PATH=/dist-dev/
|
||||
|
||||
# 是否删除debugger
|
||||
VITE_DROP_DEBUGGER=false
|
||||
|
||||
# 是否删除console.log
|
||||
VITE_DROP_CONSOLE=false
|
||||
|
||||
# 是否sourcemap
|
||||
VITE_SOURCEMAP=true
|
||||
|
||||
# 输出路径
|
||||
VITE_OUT_DIR=dist-dev
|
||||
|
||||
# 标题
|
||||
VITE_APP_TITLE=ElementAdmin
|
||||
|
||||
# 是否包分析
|
||||
VITE_USE_BUNDLE_ANALYZER=false
|
||||
|
||||
# 是否全量引入element-plus样式
|
||||
VITE_USE_ALL_ELEMENT_PLUS_STYLE=false
|
||||
|
||||
# 是否开启mock
|
||||
VITE_USE_MOCK=true
|
||||
|
||||
# 是否切割css
|
||||
VITE_USE_CSS_SPLIT=true
|
||||
|
||||
# 是否使用在线图标
|
||||
VITE_USE_ONLINE_ICON=true
|
||||
|
||||
# 是否隐藏全局设置按钮
|
||||
VITE_HIDE_GLOBAL_SETTING=false
|
||||
41
promo-ui2/.env.gitee
Normal file
@@ -0,0 +1,41 @@
|
||||
# 环境
|
||||
VITE_NODE_ENV=production
|
||||
|
||||
# 接口前缀
|
||||
VITE_API_BASE_PATH=
|
||||
|
||||
# 打包路径
|
||||
VITE_BASE_PATH=/vue-element-plus-admin/
|
||||
|
||||
# 是否删除debugger
|
||||
VITE_DROP_DEBUGGER=true
|
||||
|
||||
# 是否删除console.log
|
||||
VITE_DROP_CONSOLE=true
|
||||
|
||||
# 是否sourcemap
|
||||
VITE_SOURCEMAP=false
|
||||
|
||||
# 输出路径
|
||||
VITE_OUT_DIR=dist-pro
|
||||
|
||||
# 标题
|
||||
VITE_APP_TITLE=ElementAdmin
|
||||
|
||||
# 是否包分析
|
||||
VITE_USE_BUNDLE_ANALYZER=false
|
||||
|
||||
# 是否全量引入element-plus样式
|
||||
VITE_USE_ALL_ELEMENT_PLUS_STYLE=false
|
||||
|
||||
# 是否开启mock
|
||||
VITE_USE_MOCK=true
|
||||
|
||||
# 是否切割css
|
||||
VITE_USE_CSS_SPLIT=true
|
||||
|
||||
# 是否使用在线图标
|
||||
VITE_USE_ONLINE_ICON=true
|
||||
|
||||
# 是否隐藏全局设置按钮
|
||||
VITE_HIDE_GLOBAL_SETTING=false
|
||||
41
promo-ui2/.env.pro
Normal file
@@ -0,0 +1,41 @@
|
||||
# 环境
|
||||
VITE_NODE_ENV=production
|
||||
|
||||
# 接口前缀
|
||||
VITE_API_BASE_PATH=https://zb.wildcs2.com
|
||||
|
||||
# 打包路径
|
||||
VITE_BASE_PATH=/
|
||||
|
||||
# 是否删除debugger
|
||||
VITE_DROP_DEBUGGER=true
|
||||
|
||||
# 是否删除console.log
|
||||
VITE_DROP_CONSOLE=true
|
||||
|
||||
# 是否sourcemap
|
||||
VITE_SOURCEMAP=false
|
||||
|
||||
# 输出路径
|
||||
VITE_OUT_DIR=dist-pro
|
||||
|
||||
# 标题
|
||||
VITE_APP_TITLE=推广后台
|
||||
|
||||
# 是否包分析
|
||||
VITE_USE_BUNDLE_ANALYZER=true
|
||||
|
||||
# 是否全量引入element-plus样式
|
||||
VITE_USE_ALL_ELEMENT_PLUS_STYLE=false
|
||||
|
||||
# 是否开启mock
|
||||
VITE_USE_MOCK=false
|
||||
|
||||
# 是否切割css
|
||||
VITE_USE_CSS_SPLIT=true
|
||||
|
||||
# 是否使用在线图标
|
||||
VITE_USE_ONLINE_ICON=false
|
||||
|
||||
# 是否隐藏全局设置按钮
|
||||
VITE_HIDE_GLOBAL_SETTING=true
|
||||
41
promo-ui2/.env.test
Normal file
@@ -0,0 +1,41 @@
|
||||
# 环境
|
||||
VITE_NODE_ENV=production
|
||||
|
||||
# 接口前缀
|
||||
VITE_API_BASE_PATH=http://8.160.181.6:8081
|
||||
|
||||
# 打包路径
|
||||
VITE_BASE_PATH=/
|
||||
|
||||
# 是否删除debugger
|
||||
VITE_DROP_DEBUGGER=true
|
||||
|
||||
# 是否删除console.log
|
||||
VITE_DROP_CONSOLE=true
|
||||
|
||||
# 是否sourcemap
|
||||
VITE_SOURCEMAP=false
|
||||
|
||||
# 输出路径
|
||||
VITE_OUT_DIR=dist-pro
|
||||
|
||||
# 标题
|
||||
VITE_APP_TITLE=推广后台
|
||||
|
||||
# 是否包分析
|
||||
VITE_USE_BUNDLE_ANALYZER=true
|
||||
|
||||
# 是否全量引入element-plus样式
|
||||
VITE_USE_ALL_ELEMENT_PLUS_STYLE=false
|
||||
|
||||
# 是否开启mock
|
||||
VITE_USE_MOCK=false
|
||||
|
||||
# 是否切割css
|
||||
VITE_USE_CSS_SPLIT=true
|
||||
|
||||
# 是否使用在线图标
|
||||
VITE_USE_ONLINE_ICON=false
|
||||
|
||||
# 是否隐藏全局设置按钮
|
||||
VITE_HIDE_GLOBAL_SETTING=true
|
||||
131
promo-ui2/.github/workflows/auto-merge.yml
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
name: Automerge
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- labeled
|
||||
- unlabeled
|
||||
- synchronize
|
||||
- opened
|
||||
- edited
|
||||
- ready_for_review
|
||||
- reopened
|
||||
- unlocked
|
||||
pull_request_review:
|
||||
types:
|
||||
- submitted
|
||||
status: {}
|
||||
|
||||
jobs:
|
||||
# 合并发布版本的 pr 到 master
|
||||
auto-merge:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Automerge
|
||||
uses: 'pascalgn/automerge-action@v0.14.3'
|
||||
env:
|
||||
BASE_BRANCHES: 'release'
|
||||
GITHUB_TOKEN: '${{ secrets.TOKEN }}'
|
||||
MERGE_LABELS: ''
|
||||
MERGE_FILTER_AUTHOR: 'kailong321200875'
|
||||
|
||||
push-to-gh-pages:
|
||||
needs: [auto-merge]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: use Node.js 18
|
||||
uses: actions/setup-node@v2.1.2
|
||||
with:
|
||||
node-version: '18.x'
|
||||
|
||||
- name: Set SSH Environment
|
||||
env:
|
||||
DOCS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }}
|
||||
run: |
|
||||
mkdir -p ~/.ssh/
|
||||
echo "$ACTIONS_DEPLOY_KEY" > ~/.ssh/id_rsa
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
ssh-keyscan github.com > ~/.ssh/known_hosts
|
||||
chmod 700 ~/.ssh && chmod 600 ~/.ssh/*
|
||||
git config --local user.email "321200875@qq.com"
|
||||
git config --local user.name "kailong321200875"
|
||||
|
||||
# 发布到 github
|
||||
- name: Build Github
|
||||
run: |
|
||||
pnpm install --no-frozen-lockfile
|
||||
pnpm run build:pro
|
||||
|
||||
- name: Deploy Github
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
deploy_key: ${{secrets.ACTIONS_DEPLOY_KEY}}
|
||||
publish_branch: gh-pages
|
||||
publish_dir: ./dist-pro
|
||||
force_orphan: true
|
||||
cname: element-plus-admin.cn
|
||||
|
||||
push-to-gh-pages-gitee:
|
||||
needs: [auto-merge]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: latest
|
||||
|
||||
- name: use Node.js 18
|
||||
uses: actions/setup-node@v2.1.2
|
||||
with:
|
||||
node-version: '18.x'
|
||||
|
||||
- name: Set SSH Environment
|
||||
env:
|
||||
DOCS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEPLOY_KEY }}
|
||||
run: |
|
||||
mkdir -p ~/.ssh/
|
||||
echo "$ACTIONS_DEPLOY_KEY" > ~/.ssh/id_rsa
|
||||
chmod 600 ~/.ssh/id_rsa
|
||||
ssh-keyscan github.com > ~/.ssh/known_hosts
|
||||
chmod 700 ~/.ssh && chmod 600 ~/.ssh/*
|
||||
git config --local user.email "321200875@qq.com"
|
||||
git config --local user.name "kailong321200875"
|
||||
|
||||
- name: Build Gitee
|
||||
run: |
|
||||
pnpm install --no-frozen-lockfile
|
||||
pnpm run build:gitee
|
||||
|
||||
# 发布到 gitee
|
||||
- name: Deploy Gitee
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
deploy_key: ${{secrets.ACTIONS_DEPLOY_KEY}}
|
||||
publish_branch: gh-pages-gitee
|
||||
publish_dir: ./dist-pro
|
||||
force_orphan: true
|
||||
|
||||
- name: Sync Github Repos To Gitee # 名字随便起
|
||||
uses: Yikun/hub-mirror-action@v1.1 # 使用Yikun/hub-mirror-action
|
||||
with:
|
||||
src: github/kailong321200875 # 源端账户名(github)
|
||||
dst: gitee/kailong110120130 # 目的端账户名(gitee)
|
||||
dst_key: ${{ secrets.ACTIONS_DEPLOY_KEY }} # SSH密钥对中的私钥
|
||||
dst_token: ${{ secrets.GITEE_TOKEN }} # Gitee账户的私人令牌
|
||||
account_type: user # 账户类型
|
||||
clone_style: 'https' # 使用https方式进行clone,也可以使用ssh
|
||||
debug: true # 启用后会显示所有执行命令
|
||||
force_update: true # 启用后,强制同步,即强制覆盖目的端仓库
|
||||
static_list: 'vue-element-plus-admin' # 静态同步列表,在此填写需要同步的仓库名称,可填写多个
|
||||
timeout: '600s' # git超时设置,超时后会自动重试git操作
|
||||
19
promo-ui2/.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- release
|
||||
|
||||
name: Release
|
||||
|
||||
jobs:
|
||||
release-please:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: GoogleCloudPlatform/release-please-action@v3
|
||||
id: release
|
||||
with:
|
||||
token: ${{ secrets.TOKEN }}
|
||||
default-branch: release
|
||||
release-type: node
|
||||
package-name: standard-version
|
||||
changelog-types: '[{"type": "types", "section":"Types", "hidden": false},{"type": "revert", "section":"Reverts", "hidden": false},{"type": "feat", "section": "Features", "hidden": false},{"type": "fix", "section": "Bug Fixes", "hidden": false},{"type": "improvement", "section": "Feature Improvements", "hidden": false},{"type": "docs", "section":"Docs", "hidden": false},{"type": "style", "section":"Styling", "hidden": false},{"type": "refactor", "section":"Code Refactoring", "hidden": false},{"type": "perf", "section":"Performance Improvements", "hidden": false},{"type": "test", "section":"Tests", "hidden": false},{"type": "build", "section":"Build System", "hidden": false},{"type": "ci", "section":"CI", "hidden":false}]'
|
||||
9
promo-ui2/.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
/dist*
|
||||
pnpm-debug
|
||||
stats.html
|
||||
.idea
|
||||
1
promo-ui2/.husky/commit-msg
Normal file
@@ -0,0 +1 @@
|
||||
npx --no -- commitlint --edit $1
|
||||
9
promo-ui2/.husky/lintstagedrc.cjs
Normal file
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
'*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'],
|
||||
'{!(package)*.json,*.code-snippets,.!(browserslist)*rc}': ['prettier --parser json --write'],
|
||||
'package.json': ['prettier --write'],
|
||||
'*.vue': ['prettier --write', 'stylelint --fix'],
|
||||
'*.{scss,less,styl,css,html}': ['stylelint --fix', 'prettier --write'],
|
||||
'*.md': ['prettier --write'],
|
||||
'*.hbs': ['prettier --write']
|
||||
}
|
||||
2
promo-ui2/.husky/pre-commit
Normal file
@@ -0,0 +1,2 @@
|
||||
npm run ts:check
|
||||
npm run lint:lint-staged
|
||||
9
promo-ui2/.prettierignore
Normal file
@@ -0,0 +1,9 @@
|
||||
/node_modules/**
|
||||
/dist/
|
||||
/dist*
|
||||
/public/*
|
||||
/docs/*
|
||||
/src/types/env.d.ts
|
||||
/docs/**/*
|
||||
/plop/**/*
|
||||
CHANGELOG
|
||||
6
promo-ui2/.stylelintignore
Normal file
@@ -0,0 +1,6 @@
|
||||
/dist/*
|
||||
/public/*
|
||||
public/*
|
||||
/dist*
|
||||
/src/types/env.d.ts
|
||||
/docs/**/*
|
||||
1421
promo-ui2/CHANGELOG.md
Normal file
13
promo-ui2/Dockerfile.dev
Normal file
@@ -0,0 +1,13 @@
|
||||
FROM node:18.0.0
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN npm install -g pnpm@8.1.0
|
||||
|
||||
COPY package.json .
|
||||
|
||||
RUN pnpm install
|
||||
|
||||
COPY . .
|
||||
|
||||
CMD [ "pnpm", "run", "dev" ]
|
||||
21
promo-ui2/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021-present Archer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
148
promo-ui2/README.md
Normal file
@@ -0,0 +1,148 @@
|
||||
<div align="center"> <a href="https://github.com/kailong321200875/vue-element-plus-admin"> <img width="100" src="./public/logo.png"> </a> <br> <br>
|
||||
|
||||
[](LICENSE) [](repo-size) [](last-commit) [](stars) [](forks) [](release) [](watchers)
|
||||
|
||||
<h1>vue-element-plus-admin</h1>
|
||||
</div>
|
||||
|
||||
**English** | [中文](./README.zh-CN.md)
|
||||
|
||||
## Introduction
|
||||
|
||||
vue-element-plus-admin is a free and open source middle and background template based on `element-plus`. Developed using the latest mainstream technologies such as `vue3`, `vite` and `typescript`, the out of the box middle and background front-end solution can be used as the starting template of the project and learning reference. And always pay attention to the latest technological trends and update them as soon as possible.
|
||||
|
||||
vue-element-plus-admin is positioned as a background integration scheme, which is not suitable for secondary development as a basic template. Because it integrates many functions that you may not use, it will cause a lot of code redundancy. If your project doesn't pay attention to this problem, you can also directly carry out secondary development based on it.
|
||||
|
||||
If you need a basic template, please switch to the `mini` branch. `mini` simply integrates some common layout functions such as layout and dynamic menu, which is more suitable for developers to carry out secondary development.
|
||||
|
||||
## Feature
|
||||
|
||||
- **State of The Art Development**:Use front-end front-end technology development such as Vue3/vite4
|
||||
- **TypeScript**: Application-level JavaScript language
|
||||
- **Theming**: Configurable themes
|
||||
- **International**:Built-in complete internationalization program
|
||||
- **Mock Server** Built-in mock data scheme
|
||||
- **Authority** Built-in complete dynamic routing permission generation scheme.
|
||||
- **Component** Multiple commonly used components are encapsulated twice
|
||||
- **Examples** Built-in rich examples
|
||||
|
||||
## Preview
|
||||
|
||||
- [vue-element-plus-admin](https://element-plus-admin.cn/) - Full version of the github site
|
||||
- [vue-element-plus-admin](https://kailong110120130.gitee.io/vue-element-plus-admin) - Full version of the gitee site
|
||||
|
||||
account: **admin/admin**
|
||||
|
||||
Online examples do not apply to menu filtering by default, but directly use Static routing
|
||||
|
||||
## Documentation
|
||||
|
||||
[Document Github](https://element-plus-admin-doc.cn/)
|
||||
|
||||
[Document Gitee](https://kailong110120130.gitee.io/vue-element-plus-admin-doc)
|
||||
|
||||
## Preparation
|
||||
|
||||
- [node](http://nodejs.org/) and [git](https://git-scm.com/) - Project development environment
|
||||
- [Vite](https://vitejs.dev/) - Familiar with vite features
|
||||
- [Vue3](https://v3.vuejs.org/) - Familiar with Vue basic syntax
|
||||
- [TypeScript](https://www.typescriptlang.org/) - Familiar with the basic syntax of `TypeScript`
|
||||
- [Es6+](http://es6.ruanyifeng.com/) - Familiar with es6 basic syntax
|
||||
- [Vue-Router-Next](https://next.router.vuejs.org/) - Familiar with the basic use of vue-router
|
||||
- [Element-Plus](https://element-plus.org/) - Familiar with the basic use of element-plus
|
||||
- [Mock.js](https://github.com/nuysoft/Mock) - mockjs basic syntax
|
||||
|
||||
## Install and use
|
||||
|
||||
- Get the project code
|
||||
|
||||
```bash
|
||||
git clone https://github.com/kailong321200875/vue-element-plus-admin.git
|
||||
```
|
||||
|
||||
- Installation dependencies
|
||||
|
||||
```bash
|
||||
cd vue-element-plus-admin
|
||||
|
||||
pnpm install
|
||||
|
||||
```
|
||||
|
||||
- run
|
||||
|
||||
```bash
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
- build
|
||||
|
||||
```bash
|
||||
pnpm run build:pro
|
||||
```
|
||||
|
||||
## Change Log
|
||||
|
||||
[CHANGELOG](./CHANGELOG.md)
|
||||
|
||||
## How to contribute
|
||||
|
||||
<a href="https://github.com/kailong321200875/vue-element-plus-admin/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=kailong321200875/vue-element-plus-admin" />
|
||||
</a>
|
||||
|
||||
You can [Raise an issue](https://github.com/kailong321200875/vue-element-plus-admin/issues/new) Or submit a Pull Request.
|
||||
|
||||
**Pull Request:**
|
||||
|
||||
1. Fork code
|
||||
2. Create your own branch: `git checkout -b feat/xxxx`
|
||||
3. Submit your changes: `git commit -am 'feat(function): add xxxxx'`
|
||||
4. Push your branch: `git push origin feat/xxxx`
|
||||
5. submit `pull request`
|
||||
|
||||
## Git Contribution submission specification
|
||||
|
||||
- `feat` New features
|
||||
- `fix` Fix bugs
|
||||
- `docs` document
|
||||
- `style` Format and style (changes that do not affect code operation)
|
||||
- `refactor` Refactor
|
||||
- `perf` Optimize related, such as improving performance and experience
|
||||
- `test` Add test
|
||||
- `build` Compilation related modifications, changes to project construction or dependencies
|
||||
- `ci` Continuous integration modification
|
||||
- `chore` Changes in the construction process or auxiliary tools
|
||||
- `revert` Rollback to previous version
|
||||
- `workflow` Workflow improvement
|
||||
- `mod` Uncertain modification classification
|
||||
- `wip` Under development
|
||||
- `types` type
|
||||
|
||||
## Browser support
|
||||
|
||||
The `Chrome 80+` browser is recommended for local development
|
||||
|
||||
Support modern browsers, not IE
|
||||
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||
| :-: | :-: | :-: | :-: | :-: |
|
||||
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
|
||||
|
||||
## Donate
|
||||
|
||||
If you find this project helpful, welcome sponsorship to show your support~
|
||||
|
||||
[Paypal Me](https://www.paypal.com/paypalme/ckl94)
|
||||
|
||||
<img src="https://github.com/kailong321200875/my-image/raw/master/pay.jpg" />
|
||||
|
||||
### My QR code
|
||||
|
||||
If you have any project cooperation or outsourcing, please scan the code to add me as a friend and leave a note of your purpose.
|
||||
|
||||
<img src="https://github.com/kailong321200875/my-image/raw/master/me.jpg" />
|
||||
|
||||
## License
|
||||
|
||||
[MIT](./LICENSE)
|
||||
148
promo-ui2/README.zh-CN.md
Normal file
@@ -0,0 +1,148 @@
|
||||
<div align="center"> <a href="https://github.com/kailong321200875/vue-element-plus-admin"> <img width="100" src="./public/logo.png"> </a> <br> <br>
|
||||
|
||||
[](LICENSE) [](repo-size) [](last-commit) [](stars) [](forks) [](release) [](watchers)
|
||||
|
||||
<h1>vue-element-plus-admin</h1>
|
||||
</div>
|
||||
|
||||
[English](./README.md) | **中文**
|
||||
|
||||
## 介绍
|
||||
|
||||
vue-element-plus-admin 是一个基于 `element-plus` 免费开源的中后台模版。使用了最新的`vue3`,`vite`,`TypeScript`等主流技术开发,开箱即用的中后台前端解决方案,可以用来作为项目的启动模版,也可用于学习参考。并且时刻关注着最新技术动向,尽可能的第一时间更新。
|
||||
|
||||
vue-element-plus-admin 的定位是后台集成方案,不太适合当基础模板来进行二次开发。因为集成了很多你可能用不到的功能,会造成不少的代码冗余。如果你的项目不关注这方面的问题,也可以直接基于它进行二次开发。
|
||||
|
||||
如需要基础模版,请切换到 `mini` 分支,`mini` 只简单集成了一些如:布局、动态菜单等常用布局功能,更适合开发者进行二次开发。
|
||||
|
||||
## 特性
|
||||
|
||||
- **最新技术栈**:使用 Vue3/vite4 等前端前沿技术开发
|
||||
- **TypeScript**: 应用程序级 JavaScript 的语言
|
||||
- **主题**: 可配置的主题
|
||||
- **国际化**:内置完善的国际化方案
|
||||
- **自定义数据** 内置 Mock 数据方案
|
||||
- **权限** 内置完善的动态路由权限生成方案
|
||||
- **组件** 二次封装了多个常用的组件
|
||||
- **示例** 内置丰富的示例
|
||||
|
||||
## 预览
|
||||
|
||||
- [vue-element-plus-admin](https://element-plus-admin.cn/) - 完整版 github 站点
|
||||
- [vue-element-plus-admin](https://kailong110120130.gitee.io/vue-element-plus-admin) - 完整版 gitee 站点
|
||||
|
||||
帐号:**admin/admin**
|
||||
|
||||
在线例子默认不适用菜单过滤,而是直接使用静态路由表
|
||||
|
||||
## 文档
|
||||
|
||||
[文档地址 Github](https://element-plus-admin-doc.cn/)
|
||||
|
||||
[文档地址 Gitee](https://kailong110120130.gitee.io/vue-element-plus-admin-doc)
|
||||
|
||||
## 前序准备
|
||||
|
||||
- [node](http://nodejs.org/) 和 [git](https://git-scm.com/) - 项目开发环境
|
||||
- [Vite](https://vitejs.dev/) - 熟悉 vite 特性
|
||||
- [Vue3](https://v3.vuejs.org/) - 熟悉 Vue 基础语法
|
||||
- [TypeScript](https://www.typescriptlang.org/) - 熟悉 `TypeScript` 基本语法
|
||||
- [Es6+](http://es6.ruanyifeng.com/) - 熟悉 es6 基本语法
|
||||
- [Vue-Router-Next](https://next.router.vuejs.org/) - 熟悉 vue-router 基本使用
|
||||
- [Element-Plus](https://element-plus.org/) - element-plus 基本使用
|
||||
- [Mock.js](https://github.com/nuysoft/Mock) - mockjs 基本语法
|
||||
|
||||
## 安装和使用
|
||||
|
||||
- 获取代码
|
||||
|
||||
```bash
|
||||
git clone https://github.com/kailong321200875/vue-element-plus-admin.git
|
||||
```
|
||||
|
||||
- 安装依赖
|
||||
|
||||
```bash
|
||||
cd vue-element-plus-admin
|
||||
|
||||
pnpm install
|
||||
|
||||
```
|
||||
|
||||
- 运行
|
||||
|
||||
```bash
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
- 打包
|
||||
|
||||
```bash
|
||||
pnpm run build:pro
|
||||
```
|
||||
|
||||
## 更新日志
|
||||
|
||||
[更新日志](./CHANGELOG.md)
|
||||
|
||||
## 如何贡献
|
||||
|
||||
<a href="https://github.com/kailong321200875/vue-element-plus-admin/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=kailong321200875/vue-element-plus-admin" />
|
||||
</a>
|
||||
|
||||
你可以[提一个 issue](https://github.com/kailong321200875/vue-element-plus-admin/issues/new) 或者提交一个 Pull Request。
|
||||
|
||||
**Pull Request:**
|
||||
|
||||
1. Fork 代码
|
||||
2. 创建自己的分支: `git checkout -b feat/xxxx`
|
||||
3. 提交你的修改: `git commit -am 'feat(function): add xxxxx'`
|
||||
4. 推送您的分支: `git push origin feat/xxxx`
|
||||
5. 提交 `pull request`
|
||||
|
||||
## Git 贡献提交规范
|
||||
|
||||
- `feat` 新功能
|
||||
- `fix` 修补 bug
|
||||
- `docs` 文档
|
||||
- `style` 格式、样式(不影响代码运行的变动)
|
||||
- `refactor` 重构(即不是新增功能,也不是修改 BUG 的代码)
|
||||
- `perf` 优化相关,比如提升性能、体验
|
||||
- `test` 添加测试
|
||||
- `build` 编译相关的修改,对项目构建或者依赖的改动
|
||||
- `ci` 持续集成修改
|
||||
- `chore` 构建过程或辅助工具的变动
|
||||
- `revert` 回滚到上一个版本
|
||||
- `workflow` 工作流改进
|
||||
- `mod` 不确定分类的修改
|
||||
- `wip` 开发中
|
||||
- `types` 类型
|
||||
|
||||
## 浏览器支持
|
||||
|
||||
本地开发推荐使用 `Chrome 80+` 浏览器
|
||||
|
||||
支持现代浏览器, 不支持 IE
|
||||
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/archive/internet-explorer_9-11/internet-explorer_9-11_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||
| :-: | :-: | :-: | :-: | :-: |
|
||||
| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
|
||||
|
||||
## Donate
|
||||
|
||||
如果你觉得这个项目有帮助,欢迎赞助以示支持~
|
||||
|
||||
[Paypal Me](https://www.paypal.com/paypalme/ckl94)
|
||||
|
||||
<img src="https://gitee.com/kailong110120130/my-image/raw/master/pay.jpg" />
|
||||
|
||||
### 我的二维码
|
||||
|
||||
如有项目合作或项目外包,扫码加我好友,请备注来意。
|
||||
|
||||
<img src="https://gitee.com/kailong110120130/my-image/raw/master/me.jpg" />
|
||||
|
||||
## 许可证
|
||||
|
||||
[MIT](./LICENSE)
|
||||
17
promo-ui2/apidoc/redpack.http
Normal file
@@ -0,0 +1,17 @@
|
||||
POST http://localhost:8081/promo/login HTTP/1.1
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
|
||||
{"username":"15375298377","password":"123456"}
|
||||
|
||||
|
||||
### 获取卡密列表
|
||||
GET http://localhost:8081/promo/card/list
|
||||
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImQ4MWI5OTM5LTUwZWItNGFiNC05NGIxLTEwOWFiYzY5NzI5MCJ9.RHXzv6Ao6hUl0fwY-Zhszz1-Jda6ceZybjmFddKFLZQbjufYkZd167ZCmlU9SbcrZ3Ec8TIt4XqSS7zb7fVHtQ
|
||||
|
||||
|
||||
### 生成卡密
|
||||
|
||||
POST http://localhost:8081/promo/generateCard/6/1
|
||||
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImQ4MWI5OTM5LTUwZWItNGFiNC05NGIxLTEwOWFiYzY5NzI5MCJ9.RHXzv6Ao6hUl0fwY-Zhszz1-Jda6ceZybjmFddKFLZQbjufYkZd167ZCmlU9SbcrZ3Ec8TIt4XqSS7zb7fVHtQ
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
|
||||
4
promo-ui2/apidoc/user.http
Normal file
@@ -0,0 +1,4 @@
|
||||
POST http://localhost:8081/promo/register HTTP/1.1
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
|
||||
{"username":"17688554522","password":"123456", "contactInformation": "hello"}
|
||||
11
promo-ui2/apidoc/分享.http
Normal file
@@ -0,0 +1,11 @@
|
||||
POST http://localhost:8081/promo/login HTTP/1.1
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
|
||||
{"username":"15375298377","password":"123456"}
|
||||
|
||||
|
||||
### 分享域名
|
||||
|
||||
GET http://localhost:8081/promo/getsharedomain HTTP/1.1
|
||||
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImEwMmU0Y2MyLWM5MDctNGU4OS1iNTkxLTk1Mjk1MGI2NjRmNCJ9._imhNdbqREBrYv-Kx73VN0S5U7Pr1zMvvMLEMXHf77uKOLO1Y0NnWRuTvSQlYp1T1KMVcNxEChSLj7I-Xex2wA
|
||||
|
||||
13
promo-ui2/apidoc/普通用户.http
Normal file
@@ -0,0 +1,13 @@
|
||||
POST http://localhost:8081/api/login HTTP/1.1
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
|
||||
|
||||
{"username":"13545419205","password":"123456"}
|
||||
|
||||
|
||||
### 兑换红包卡密
|
||||
|
||||
GET http://localhost:8081/api/bonus/receiveRedPacket/A628920554234AFDB539398823835378
|
||||
Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjY1MjA4OTYwLTA3NDQtNDQxZS05YzA1LWJjNTc2ZTQyN2RiMyJ9.Ogqmm8iTgiPhc8b7iDxz_a2atBtAgbmwqzi1M5ogLEpAVFAv91N0Ygo-1_yUVioPVn0WTWVJvJnIW42-4CgIJg
|
||||
|
||||
|
||||
28
promo-ui2/commitlint.config.cjs
Normal file
@@ -0,0 +1,28 @@
|
||||
module.exports = {
|
||||
extends: ['@commitlint/config-conventional'],
|
||||
rules: {
|
||||
'type-enum': [
|
||||
2,
|
||||
'always',
|
||||
[
|
||||
'feat', // 新功能(feature)
|
||||
'fix', // 修补bug
|
||||
'docs', // 文档(documentation)
|
||||
'style', // 格式、样式(不影响代码运行的变动)
|
||||
'refactor', // 重构(即不是新增功能,也不是修改BUG的代码)
|
||||
'perf', // 优化相关,比如提升性能、体验
|
||||
'test', // 添加测试
|
||||
'ci', // 持续集成修改
|
||||
'chore', // 构建过程或辅助工具的变动
|
||||
'revert', // 回滚到上一个版本
|
||||
'workflow', // 工作流改进
|
||||
'mod', // 不确定分类的修改
|
||||
'wip', // 开发中
|
||||
'types', // 类型修改
|
||||
'release' // 版本发布
|
||||
]
|
||||
],
|
||||
'subject-full-stop': [0, 'never'],
|
||||
'subject-case': [0, 'never']
|
||||
}
|
||||
}
|
||||
10
promo-ui2/docker-compose.dev.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
services:
|
||||
vue-element-plus-admin:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.dev
|
||||
ports:
|
||||
- "4000:4000"
|
||||
volumes:
|
||||
- /app/node_modules
|
||||
- .:/app
|
||||
82
promo-ui2/eslint.config.mjs
Normal file
@@ -0,0 +1,82 @@
|
||||
// 引入vue模版的eslint
|
||||
import pluginVue from 'eslint-plugin-vue'
|
||||
import eslint from '@eslint/js'
|
||||
// ts-eslint解析器,使 eslint 可以解析 ts 语法
|
||||
import tseslint from 'typescript-eslint'
|
||||
// vue文件解析器
|
||||
import vueParser from 'vue-eslint-parser'
|
||||
import prettier from 'eslint-plugin-prettier'
|
||||
|
||||
export default tseslint.config({
|
||||
// ignores: ['node_modules', 'prettier.config.cjs', 'dist*'],
|
||||
files: ['src/**/*.ts', 'src/**/*.tsx', 'src/**/*.vue'],
|
||||
// tseslint.config添加了extends扁平函数,直接用。否则是eslint9.0版本是没有extends的
|
||||
extends: [
|
||||
eslint.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
...pluginVue.configs['flat/essential']
|
||||
],
|
||||
plugins: {
|
||||
prettier
|
||||
},
|
||||
languageOptions: {
|
||||
parser: vueParser, // 使用vue解析器,这个可以识别vue文件
|
||||
parserOptions: {
|
||||
parser: tseslint.parser, // 在vue文件上使用ts解析器
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020,
|
||||
ecmaFeatures: {
|
||||
jsx: true
|
||||
}
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
'prettier/prettier': 'error',
|
||||
'no-useless-escape': 0,
|
||||
'no-undef': 0,
|
||||
'@typescript-eslint/no-unused-expressions': 0,
|
||||
'@typescript-eslint/no-unsafe-function-type': 0,
|
||||
'vue/no-setup-props-destructure': 0,
|
||||
'vue/script-setup-uses-vars': 1,
|
||||
'vue/no-reserved-component-names': 0,
|
||||
'@typescript-eslint/ban-ts-ignore': 0,
|
||||
'@typescript-eslint/explicit-function-return-type': 0,
|
||||
'@typescript-eslint/no-explicit-any': 0,
|
||||
'@typescript-eslint/no-var-requires': 0,
|
||||
'@typescript-eslint/no-empty-function': 0,
|
||||
'vue/custom-event-name-casing': 0,
|
||||
'no-use-before-define': 0,
|
||||
'@typescript-eslint/no-use-before-define': 0,
|
||||
'@typescript-eslint/ban-ts-comment': 0,
|
||||
'@typescript-eslint/ban-types': 0,
|
||||
'@typescript-eslint/no-non-null-assertion': 0,
|
||||
'@typescript-eslint/explicit-module-boundary-types': 0,
|
||||
'@typescript-eslint/no-unused-vars': 0,
|
||||
'no-unused-vars': 0,
|
||||
'space-before-function-paren': 0,
|
||||
'vue/attributes-order': 0,
|
||||
'vue/one-component-per-file': 0,
|
||||
'vue/html-closing-bracket-newline': 0,
|
||||
'vue/max-attributes-per-line': 0,
|
||||
'vue/multiline-html-element-content-newline': 0,
|
||||
'vue/singleline-html-element-content-newline': 0,
|
||||
'vue/attribute-hyphenation': 0,
|
||||
'vue/require-default-prop': 0,
|
||||
'vue/require-explicit-emits': 0,
|
||||
'vue/html-self-closing': [
|
||||
1,
|
||||
{
|
||||
html: {
|
||||
void: 'always',
|
||||
normal: 'never',
|
||||
component: 'always'
|
||||
},
|
||||
svg: 'always',
|
||||
math: 'always'
|
||||
}
|
||||
],
|
||||
'vue/multi-word-component-names': 0,
|
||||
'vue/no-v-html': 0,
|
||||
'vue/require-toggle-inside-transition': 0
|
||||
}
|
||||
})
|
||||
142
promo-ui2/index.html
Normal file
@@ -0,0 +1,142 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title><%= title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
<style>
|
||||
.app-loading {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
background: #f0f2f5;
|
||||
}
|
||||
|
||||
.app-loading .app-loading-wrap {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
display: flex;
|
||||
-webkit-transform: translate3d(-50%, -50%, 0);
|
||||
transform: translate3d(-50%, -50%, 0);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.app-loading .app-loading-title {
|
||||
margin-bottom: 30px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.app-loading .app-loading-logo {
|
||||
width: 100px;
|
||||
margin: 0 auto 15px auto;
|
||||
}
|
||||
|
||||
.app-loading .app-loading-item {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
vertical-align: middle;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.app-loading .app-loading-outter {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 4px solid #2d8cf0;
|
||||
border-bottom: 0;
|
||||
border-left-color: transparent;
|
||||
border-radius: 50%;
|
||||
animation: loader-outter 1s cubic-bezier(0.42, 0.61, 0.58, 0.41) infinite;
|
||||
}
|
||||
|
||||
.app-loading .app-loading-inner {
|
||||
position: absolute;
|
||||
top: calc(50% - 20px);
|
||||
left: calc(50% - 20px);
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 4px solid #87bdff;
|
||||
border-right: 0;
|
||||
border-top-color: transparent;
|
||||
border-radius: 50%;
|
||||
animation: loader-inner 1s cubic-bezier(0.42, 0.61, 0.58, 0.41) infinite;
|
||||
}
|
||||
|
||||
@-webkit-keyframes loader-outter {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loader-outter {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes loader-inner {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(-360deg);
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loader-inner {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(-360deg);
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div class="app-loading">
|
||||
<div class="app-loading-wrap">
|
||||
<div class="app-loading-title">
|
||||
<img src="/logo.png" class="app-loading-logo" alt="Logo" />
|
||||
<div class="app-loading-title"><%= title %></div>
|
||||
</div>
|
||||
<div class="app-loading-item">
|
||||
<div class="app-loading-outter"></div>
|
||||
<div class="app-loading-inner"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
18
promo-ui2/mock/_createProductionServer.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer'
|
||||
|
||||
const modules = import.meta.glob('./**/*.mock.ts', {
|
||||
import: 'default',
|
||||
eager: true
|
||||
})
|
||||
|
||||
const mockModules: any[] = []
|
||||
Object.keys(modules).forEach(async (key) => {
|
||||
if (key.includes('_')) {
|
||||
return
|
||||
}
|
||||
mockModules.push(...(modules[key] as any))
|
||||
})
|
||||
|
||||
export function setupProdMockServer() {
|
||||
createProdMockServer(mockModules)
|
||||
}
|
||||
87
promo-ui2/mock/analysis/index.mock.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { SUCCESS_CODE } from '@/constants'
|
||||
import { MockMethod } from 'vite-plugin-mock'
|
||||
|
||||
const timeout = 1000
|
||||
|
||||
export default [
|
||||
// 分析页统计接口
|
||||
{
|
||||
url: '/mock/analysis/total',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: {
|
||||
users: 102400,
|
||||
messages: 81212,
|
||||
moneys: 9280,
|
||||
shoppings: 13600
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 用户来源
|
||||
{
|
||||
url: '/mock/analysis/userAccessSource',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: [
|
||||
{ value: 1000, name: 'analysis.directAccess' },
|
||||
{ value: 310, name: 'analysis.mailMarketing' },
|
||||
{ value: 234, name: 'analysis.allianceAdvertising' },
|
||||
{ value: 135, name: 'analysis.videoAdvertising' },
|
||||
{ value: 1548, name: 'analysis.searchEngines' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
// 每周用户活跃量
|
||||
{
|
||||
url: '/mock/analysis/weeklyUserActivity',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: [
|
||||
{ value: 13253, name: 'analysis.monday' },
|
||||
{ value: 34235, name: 'analysis.tuesday' },
|
||||
{ value: 26321, name: 'analysis.wednesday' },
|
||||
{ value: 12340, name: 'analysis.thursday' },
|
||||
{ value: 24643, name: 'analysis.friday' },
|
||||
{ value: 1322, name: 'analysis.saturday' },
|
||||
{ value: 1324, name: 'analysis.sunday' }
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
// 每月销售额
|
||||
{
|
||||
url: '/mock/analysis/monthlySales',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: [
|
||||
{ estimate: 100, actual: 120, name: 'analysis.january' },
|
||||
{ estimate: 120, actual: 82, name: 'analysis.february' },
|
||||
{ estimate: 161, actual: 91, name: 'analysis.march' },
|
||||
{ estimate: 134, actual: 154, name: 'analysis.april' },
|
||||
{ estimate: 105, actual: 162, name: 'analysis.may' },
|
||||
{ estimate: 160, actual: 140, name: 'analysis.june' },
|
||||
{ estimate: 165, actual: 145, name: 'analysis.july' },
|
||||
{ estimate: 114, actual: 250, name: 'analysis.august' },
|
||||
{ estimate: 163, actual: 134, name: 'analysis.september' },
|
||||
{ estimate: 185, actual: 56, name: 'analysis.october' },
|
||||
{ estimate: 118, actual: 99, name: 'analysis.november' },
|
||||
{ estimate: 123, actual: 123, name: 'analysis.december' }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
] as MockMethod[]
|
||||
206
promo-ui2/mock/department/index.mock.ts
Normal file
@@ -0,0 +1,206 @@
|
||||
import { toAnyString } from '@/utils'
|
||||
import Mock from 'mockjs'
|
||||
import { SUCCESS_CODE } from '@/constants'
|
||||
|
||||
const departmentList: any = []
|
||||
|
||||
const citys = ['厦门总公司', '北京分公司', '上海分公司', '福州分公司', '深圳分公司', '杭州分公司']
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
departmentList.push({
|
||||
// 部门名称
|
||||
departmentName: citys[i],
|
||||
id: toAnyString(),
|
||||
createTime: '@datetime',
|
||||
// 状态
|
||||
status: Mock.Random.integer(0, 1),
|
||||
// 备注
|
||||
remark: '@cword(10, 15)',
|
||||
children: [
|
||||
{
|
||||
// 部门名称
|
||||
departmentName: '研发部',
|
||||
id: toAnyString(),
|
||||
createTime: '@datetime',
|
||||
// 状态
|
||||
status: Mock.Random.integer(0, 1),
|
||||
// 备注
|
||||
remark: '@cword(10, 15)'
|
||||
},
|
||||
{
|
||||
// 部门名称
|
||||
departmentName: '产品部',
|
||||
id: toAnyString(),
|
||||
createTime: '@datetime',
|
||||
// 状态
|
||||
status: Mock.Random.integer(0, 1),
|
||||
// 备注
|
||||
remark: '@cword(10, 15)'
|
||||
},
|
||||
{
|
||||
// 部门名称
|
||||
departmentName: '运营部',
|
||||
id: toAnyString(),
|
||||
createTime: '@datetime',
|
||||
// 状态
|
||||
status: Mock.Random.integer(0, 1),
|
||||
// 备注
|
||||
remark: '@cword(10, 15)'
|
||||
},
|
||||
{
|
||||
// 部门名称
|
||||
departmentName: '市场部',
|
||||
id: toAnyString(),
|
||||
createTime: '@datetime',
|
||||
// 状态
|
||||
status: Mock.Random.integer(0, 1),
|
||||
// 备注
|
||||
remark: '@cword(10, 15)'
|
||||
},
|
||||
{
|
||||
// 部门名称
|
||||
departmentName: '销售部',
|
||||
id: toAnyString(),
|
||||
createTime: '@datetime',
|
||||
// 状态
|
||||
status: Mock.Random.integer(0, 1),
|
||||
// 备注
|
||||
remark: '@cword(10, 15)'
|
||||
},
|
||||
{
|
||||
// 部门名称
|
||||
departmentName: '客服部',
|
||||
id: toAnyString(),
|
||||
createTime: '@datetime',
|
||||
// 状态
|
||||
status: Mock.Random.integer(0, 1),
|
||||
// 备注
|
||||
remark: '@cword(10, 15)'
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
export default [
|
||||
// 列表接口
|
||||
{
|
||||
url: '/mock/department/list',
|
||||
method: 'get',
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: {
|
||||
list: departmentList
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/mock/department/table/list',
|
||||
method: 'get',
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: {
|
||||
list: departmentList,
|
||||
total: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/mock/department/users',
|
||||
method: 'get',
|
||||
timeout: 1000,
|
||||
response: ({ query }) => {
|
||||
const { pageSize } = query
|
||||
// 根据pageSize来创建数据
|
||||
const mockList: any = []
|
||||
for (let i = 0; i < pageSize; i++) {
|
||||
mockList.push(
|
||||
Mock.mock({
|
||||
// 用户名
|
||||
username: '@cname',
|
||||
// 账号
|
||||
account: '@first',
|
||||
// 邮箱
|
||||
email: '@EMAIL',
|
||||
// 创建时间
|
||||
createTime: '@datetime',
|
||||
// 用户id
|
||||
id: toAnyString()
|
||||
})
|
||||
)
|
||||
}
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: {
|
||||
total: 100,
|
||||
list: mockList
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 保存接口
|
||||
{
|
||||
url: '/mock/department/user/save',
|
||||
method: 'post',
|
||||
timeout: 1000,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: 'success'
|
||||
}
|
||||
}
|
||||
},
|
||||
// 删除接口
|
||||
{
|
||||
url: '/mock/department/user/delete',
|
||||
method: 'post',
|
||||
response: ({ body }) => {
|
||||
const ids = body.ids
|
||||
if (!ids) {
|
||||
return {
|
||||
code: 500,
|
||||
message: '请选择需要删除的数据'
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: 'success'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 保存接口
|
||||
{
|
||||
url: '/mock/department/save',
|
||||
method: 'post',
|
||||
timeout: 1000,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: 'success'
|
||||
}
|
||||
}
|
||||
},
|
||||
// 删除接口
|
||||
{
|
||||
url: '/mock/department/delete',
|
||||
method: 'post',
|
||||
response: ({ body }) => {
|
||||
const ids = body.ids
|
||||
if (!ids) {
|
||||
return {
|
||||
code: 500,
|
||||
message: '请选择需要删除的数据'
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: 'success'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
60
promo-ui2/mock/dict/index.mock.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { SUCCESS_CODE } from '@/constants'
|
||||
|
||||
const timeout = 1000
|
||||
|
||||
const dictObj: Recordable = {
|
||||
importance: [
|
||||
{
|
||||
value: 0,
|
||||
label: 'tableDemo.commonly'
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
label: 'tableDemo.good'
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
label: 'tableDemo.important'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export default [
|
||||
// 字典接口
|
||||
{
|
||||
url: '/mock/dict/list',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: dictObj
|
||||
}
|
||||
}
|
||||
},
|
||||
// 获取某个字典
|
||||
{
|
||||
url: '/mock/dict/one',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: [
|
||||
{
|
||||
label: 'test1',
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
label: 'test2',
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
label: 'test3',
|
||||
value: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
357
promo-ui2/mock/menu/index.mock.ts
Normal file
@@ -0,0 +1,357 @@
|
||||
import Mock from 'mockjs'
|
||||
import { SUCCESS_CODE } from '@/constants'
|
||||
|
||||
const timeout = 1000
|
||||
|
||||
export default [
|
||||
// 列表接口
|
||||
{
|
||||
url: '/mock/menu/list',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: {
|
||||
list: [
|
||||
{
|
||||
path: '/dashboard',
|
||||
component: '#',
|
||||
redirect: '/dashboard/analysis',
|
||||
name: 'Dashboard',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 1,
|
||||
type: 0,
|
||||
parentId: undefined,
|
||||
title: '首页',
|
||||
meta: {
|
||||
title: '首页',
|
||||
icon: 'vi-ant-design:dashboard-filled',
|
||||
alwaysShow: true
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'analysis',
|
||||
component: 'views/Dashboard/Analysis',
|
||||
name: 'Analysis',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 2,
|
||||
type: 1,
|
||||
parentId: 1,
|
||||
title: '分析页',
|
||||
permissionList: [
|
||||
{
|
||||
id: 1,
|
||||
label: '新增',
|
||||
value: 'add'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: '编辑',
|
||||
value: 'edit'
|
||||
}
|
||||
],
|
||||
meta: {
|
||||
title: '分析页',
|
||||
noCache: true,
|
||||
permission: ['add', 'edit']
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'workplace',
|
||||
component: 'views/Dashboard/Workplace',
|
||||
name: 'Workplace',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 3,
|
||||
type: 1,
|
||||
parentId: 1,
|
||||
title: '工作台',
|
||||
permissionList: [
|
||||
{
|
||||
id: 1,
|
||||
label: '新增',
|
||||
value: 'add'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: '编辑',
|
||||
value: 'edit'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
label: '删除',
|
||||
value: 'delete'
|
||||
}
|
||||
],
|
||||
meta: {
|
||||
title: '工作台',
|
||||
noCache: true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/external-link',
|
||||
component: '#',
|
||||
meta: {
|
||||
title: '文档',
|
||||
icon: 'vi-clarity:document-solid'
|
||||
},
|
||||
name: 'ExternalLink',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 4,
|
||||
type: 0,
|
||||
parentId: undefined,
|
||||
title: '文档',
|
||||
children: [
|
||||
{
|
||||
path: 'https://element-plus-admin-doc.cn/',
|
||||
name: 'DocumentLink',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 5,
|
||||
type: 1,
|
||||
parentId: 4,
|
||||
title: '文档',
|
||||
meta: {
|
||||
title: '文档'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/level',
|
||||
component: '#',
|
||||
redirect: '/level/menu1/menu1-1/menu1-1-1',
|
||||
name: 'Level',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 6,
|
||||
type: 0,
|
||||
parentId: undefined,
|
||||
title: '菜单',
|
||||
meta: {
|
||||
title: '菜单',
|
||||
icon: 'vi-carbon:skill-level-advanced'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'menu1',
|
||||
name: 'Menu1',
|
||||
component: '##',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 7,
|
||||
type: 0,
|
||||
parentId: 6,
|
||||
title: '菜单1',
|
||||
redirect: '/level/menu1/menu1-1/menu1-1-1',
|
||||
meta: {
|
||||
title: '菜单1'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'menu1-1',
|
||||
name: 'Menu11',
|
||||
component: '##',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 8,
|
||||
type: 0,
|
||||
parentId: 7,
|
||||
title: '菜单1-1',
|
||||
redirect: '/level/menu1/menu1-1/menu1-1-1',
|
||||
meta: {
|
||||
title: '菜单1-1',
|
||||
alwaysShow: true
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'menu1-1-1',
|
||||
name: 'Menu111',
|
||||
component: 'views/Level/Menu111',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 9,
|
||||
type: 1,
|
||||
parentId: 8,
|
||||
title: '菜单1-1-1',
|
||||
meta: {
|
||||
title: '菜单1-1-1'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'menu1-2',
|
||||
name: 'Menu12',
|
||||
component: 'views/Level/Menu12',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 10,
|
||||
type: 1,
|
||||
parentId: 7,
|
||||
title: '菜单1-2',
|
||||
meta: {
|
||||
title: '菜单1-2'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'menu2',
|
||||
name: 'Menu2Demo',
|
||||
component: 'views/Level/Menu2',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 11,
|
||||
type: 1,
|
||||
parentId: 6,
|
||||
title: '菜单2',
|
||||
meta: {
|
||||
title: '菜单2'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/example',
|
||||
component: '#',
|
||||
redirect: '/example/example-dialog',
|
||||
name: 'Example',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 12,
|
||||
type: 0,
|
||||
parentId: undefined,
|
||||
title: '综合示例',
|
||||
meta: {
|
||||
title: '综合示例',
|
||||
icon: 'vi-ep:management',
|
||||
alwaysShow: true
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'example-dialog',
|
||||
component: 'views/Example/Dialog/ExampleDialog',
|
||||
name: 'ExampleDialog',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 13,
|
||||
type: 1,
|
||||
parentId: 12,
|
||||
title: '综合示例-弹窗',
|
||||
permissionList: [
|
||||
{
|
||||
id: 1,
|
||||
label: '新增',
|
||||
value: 'add'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: '编辑',
|
||||
value: 'edit'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
label: '删除',
|
||||
value: 'delete'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
label: '查看',
|
||||
value: 'view'
|
||||
}
|
||||
],
|
||||
meta: {
|
||||
title: '综合示例-弹窗'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'example-page',
|
||||
component: 'views/Example/Page/ExamplePage',
|
||||
name: 'ExamplePage',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 14,
|
||||
type: 1,
|
||||
parentId: 12,
|
||||
title: '综合示例-页面',
|
||||
permissionList: [
|
||||
{
|
||||
id: 1,
|
||||
label: '新增',
|
||||
value: 'add'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: '编辑',
|
||||
value: 'edit'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
label: '删除',
|
||||
value: 'delete'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
label: '查看',
|
||||
value: 'view'
|
||||
}
|
||||
],
|
||||
meta: {
|
||||
title: '综合示例-页面'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'example-add',
|
||||
component: 'views/Example/Page/ExampleAdd',
|
||||
name: 'ExampleAdd',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 15,
|
||||
type: 1,
|
||||
parentId: 12,
|
||||
title: '综合示例-新增',
|
||||
meta: {
|
||||
title: '综合示例-新增',
|
||||
noTagsView: true,
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
showMainRoute: true,
|
||||
activeMenu: '/example/example-page'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'example-edit',
|
||||
component: 'views/Example/Page/ExampleEdit',
|
||||
name: 'ExampleEdit',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 16,
|
||||
type: 1,
|
||||
parentId: 12,
|
||||
title: '综合示例-编辑',
|
||||
meta: {
|
||||
title: '综合示例-编辑',
|
||||
noTagsView: true,
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
showMainRoute: true,
|
||||
activeMenu: '/example/example-page'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'example-detail',
|
||||
component: 'views/Example/Page/ExampleDetail',
|
||||
name: 'ExampleDetail',
|
||||
status: Mock.Random.integer(0, 1),
|
||||
id: 17,
|
||||
type: 1,
|
||||
parentId: 12,
|
||||
title: '综合示例-详情',
|
||||
meta: {
|
||||
title: '综合示例-详情',
|
||||
noTagsView: true,
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
showMainRoute: true,
|
||||
activeMenu: '/example/example-page'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
72
promo-ui2/mock/request/index.mock.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { SUCCESS_CODE } from '@/constants'
|
||||
|
||||
const timeout = 600000
|
||||
|
||||
export default [
|
||||
{
|
||||
url: '/mock/request/1',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: 'request-1'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/mock/request/2',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: 'request-2'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/mock/request/3',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: 'request-3'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/mock/request/4',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: 'request-4'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/mock/request/5',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: 'request-5'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/mock/request/expired',
|
||||
method: 'get',
|
||||
timeout: 0,
|
||||
response: () => {
|
||||
return {
|
||||
code: 401,
|
||||
message: 'token expired'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
1235
promo-ui2/mock/role/index.mock.ts
Normal file
319
promo-ui2/mock/table/index.mock.ts
Normal file
@@ -0,0 +1,319 @@
|
||||
import Mock from 'mockjs'
|
||||
import { SUCCESS_CODE } from '@/constants'
|
||||
import { toAnyString } from '@/utils'
|
||||
|
||||
const timeout = 1000
|
||||
const count = 100
|
||||
|
||||
const baseContent =
|
||||
'<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>'
|
||||
|
||||
interface ListProps {
|
||||
id: string
|
||||
author: string
|
||||
title: string
|
||||
content: string
|
||||
importance: number
|
||||
display_time: any
|
||||
pageviews: number
|
||||
image_uri: string
|
||||
video_uri?: string
|
||||
}
|
||||
|
||||
interface TreeListProps {
|
||||
id: string
|
||||
author: string
|
||||
title: string
|
||||
content: string
|
||||
importance: number
|
||||
display_time: any
|
||||
image_uri: string
|
||||
pageviews: number
|
||||
video_uri?: string
|
||||
children?: TreeListProps[]
|
||||
}
|
||||
|
||||
let List: ListProps[] = []
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
List.push(
|
||||
Mock.mock({
|
||||
id: toAnyString(),
|
||||
// timestamp: +Mock.Random.date('T'),
|
||||
author: '@first',
|
||||
title: '@title(5, 10)',
|
||||
content: baseContent,
|
||||
importance: '@integer(1, 3)',
|
||||
display_time: '@datetime',
|
||||
pageviews: '@integer(100, 500)',
|
||||
image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)'),
|
||||
video_uri:
|
||||
'//sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4'
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const treeList: TreeListProps[] = []
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
treeList.push(
|
||||
Mock.mock({
|
||||
id: toAnyString(),
|
||||
// timestamp: +Mock.Random.date('T'),
|
||||
author: '@first',
|
||||
title: '@title(5, 10)',
|
||||
content: baseContent,
|
||||
importance: '@integer(1, 3)',
|
||||
display_time: '@datetime',
|
||||
pageviews: '@integer(300, 5000)',
|
||||
image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)'),
|
||||
children: [
|
||||
{
|
||||
id: toAnyString(),
|
||||
// timestamp: +Mock.Random.date('T'),
|
||||
author: '@first',
|
||||
title: '@title(5, 10)',
|
||||
content: baseContent,
|
||||
importance: '@integer(1, 3)',
|
||||
display_time: '@datetime',
|
||||
pageviews: '@integer(300, 5000)',
|
||||
image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)'),
|
||||
children: [
|
||||
{
|
||||
id: toAnyString(),
|
||||
// timestamp: +Mock.Random.date('T'),
|
||||
author: '@first',
|
||||
title: '@title(5, 10)',
|
||||
content: baseContent,
|
||||
importance: '@integer(1, 3)',
|
||||
display_time: '@datetime',
|
||||
pageviews: '@integer(300, 5000)',
|
||||
image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)')
|
||||
},
|
||||
{
|
||||
id: toAnyString(),
|
||||
// timestamp: +Mock.Random.date('T'),
|
||||
author: '@first',
|
||||
title: '@title(5, 10)',
|
||||
content: baseContent,
|
||||
importance: '@integer(1, 3)',
|
||||
display_time: '@datetime',
|
||||
pageviews: '@integer(300, 5000)',
|
||||
image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: toAnyString(),
|
||||
// timestamp: +Mock.Random.date('T'),
|
||||
author: '@first',
|
||||
title: '@title(5, 10)',
|
||||
content: baseContent,
|
||||
importance: '@integer(1, 3)',
|
||||
display_time: '@datetime',
|
||||
pageviews: '@integer(300, 5000)',
|
||||
image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)')
|
||||
},
|
||||
{
|
||||
id: toAnyString(),
|
||||
// timestamp: +Mock.Random.date('T'),
|
||||
author: '@first',
|
||||
title: '@title(5, 10)',
|
||||
content: baseContent,
|
||||
importance: '@integer(1, 3)',
|
||||
display_time: '@datetime',
|
||||
pageviews: '@integer(300, 5000)',
|
||||
image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)')
|
||||
},
|
||||
{
|
||||
id: toAnyString(),
|
||||
// timestamp: +Mock.Random.date('T'),
|
||||
author: '@first',
|
||||
title: '@title(5, 10)',
|
||||
content: baseContent,
|
||||
importance: '@integer(1, 3)',
|
||||
display_time: '@datetime',
|
||||
pageviews: '@integer(300, 5000)',
|
||||
image_uri: Mock.Random.image('@integer(100, 500)x@integer(100, 500)')
|
||||
}
|
||||
]
|
||||
// image_uri
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const cardList = [
|
||||
{
|
||||
logo: 'https://gw.alipayobjects.com/zos/rmsportal/WdGqmHpayyMjiEhcKoVE.png',
|
||||
name: 'Alipay',
|
||||
desc: '在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。'
|
||||
},
|
||||
{
|
||||
logo: 'https://gw.alipayobjects.com/zos/rmsportal/zOsKZmFRdUtvpqCImOVY.png',
|
||||
name: 'Angular',
|
||||
desc: '在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。'
|
||||
},
|
||||
{
|
||||
logo: 'https://gw.alipayobjects.com/zos/rmsportal/siCrBXXhmvTQGWPNLBow.png',
|
||||
name: 'Bootstrap',
|
||||
desc: '在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。'
|
||||
},
|
||||
{
|
||||
logo: 'https://gw.alipayobjects.com/zos/rmsportal/kZzEzemZyKLKFsojXItE.png',
|
||||
name: 'React',
|
||||
desc: '在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。'
|
||||
},
|
||||
{
|
||||
logo: 'https://gw.alipayobjects.com/zos/rmsportal/ComBAopevLwENQdKWiIn.png',
|
||||
name: 'Vue',
|
||||
desc: '在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。'
|
||||
},
|
||||
{
|
||||
logo: 'https://gw.alipayobjects.com/zos/rmsportal/nxkuOJlFJuAUhzlMTCEe.png',
|
||||
name: 'Webpack',
|
||||
desc: '在中台产品的研发过程中,会出现不同的设计规范和实现方式,但其中往往存在很多类似的页面和组件,这些类似的组件会被抽离成一套标准规范。'
|
||||
}
|
||||
]
|
||||
|
||||
export default [
|
||||
// 树形列表接口
|
||||
{
|
||||
url: '/mock/example/treeList',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: ({ query }) => {
|
||||
const { title, pageIndex, pageSize } = query
|
||||
const mockList = treeList.filter((item) => {
|
||||
if (title && item.title.indexOf(title) < 0) return false
|
||||
return true
|
||||
})
|
||||
const pageList = mockList.filter(
|
||||
(_, index) => index < pageSize * pageIndex && index >= pageSize * (pageIndex - 1)
|
||||
)
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: {
|
||||
total: mockList.length,
|
||||
list: pageList
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 列表接口
|
||||
{
|
||||
url: '/mock/example/list',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: ({ query }) => {
|
||||
const { title, pageIndex, pageSize } = query
|
||||
const mockList = List.filter((item) => {
|
||||
if (title && item.title.indexOf(title) < 0) return false
|
||||
return true
|
||||
})
|
||||
const pageList = mockList.filter(
|
||||
(_, index) => index < pageSize * pageIndex && index >= pageSize * (pageIndex - 1)
|
||||
)
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: {
|
||||
total: mockList.length,
|
||||
list: pageList
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 保存接口
|
||||
{
|
||||
url: '/mock/example/save',
|
||||
method: 'post',
|
||||
timeout,
|
||||
response: ({ body }) => {
|
||||
if (!body.id) {
|
||||
List = [
|
||||
Object.assign(body, {
|
||||
id: toAnyString()
|
||||
})
|
||||
].concat(List)
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: 'success'
|
||||
}
|
||||
} else {
|
||||
List.map((item) => {
|
||||
if (item.id === body.id) {
|
||||
for (const key in item) {
|
||||
item[key] = body[key]
|
||||
}
|
||||
}
|
||||
})
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: 'success'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 详情接口
|
||||
{
|
||||
url: '/mock/example/detail',
|
||||
method: 'get',
|
||||
response: ({ query }) => {
|
||||
const { id } = query
|
||||
for (const example of List) {
|
||||
if (example.id === id) {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: example
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 删除接口
|
||||
{
|
||||
url: '/mock/example/delete',
|
||||
method: 'post',
|
||||
response: ({ body }) => {
|
||||
const ids = body.ids
|
||||
if (!ids) {
|
||||
return {
|
||||
code: 500,
|
||||
message: '请选择需要删除的数据'
|
||||
}
|
||||
} else {
|
||||
let i = List.length
|
||||
while (i--) {
|
||||
if (ids.indexOf(List[i].id) !== -1) {
|
||||
List.splice(i, 1)
|
||||
}
|
||||
}
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: 'success'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
url: '/mock/card/list',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: ({ query }) => {
|
||||
const { name, pageIndex, pageSize } = query
|
||||
const mockList = cardList.filter((item) => {
|
||||
if (name && item.name.indexOf(name) < 0) return false
|
||||
return true
|
||||
})
|
||||
const pageList = mockList.filter(
|
||||
(_, index) => index < pageSize * pageIndex && index >= pageSize * (pageIndex - 1)
|
||||
)
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: {
|
||||
total: mockList.length,
|
||||
list: pageList
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
90
promo-ui2/mock/user/index.mock.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import { SUCCESS_CODE } from '@/constants'
|
||||
|
||||
const timeout = 1000
|
||||
|
||||
const List: {
|
||||
username: string
|
||||
password: string
|
||||
role: string
|
||||
roleId: string
|
||||
permissions: string | string[]
|
||||
}[] = [
|
||||
{
|
||||
username: 'admin',
|
||||
password: 'admin',
|
||||
role: 'admin',
|
||||
roleId: '1',
|
||||
permissions: ['*.*.*']
|
||||
},
|
||||
{
|
||||
username: 'test',
|
||||
password: 'test',
|
||||
role: 'test',
|
||||
roleId: '2',
|
||||
permissions: ['example:dialog:create', 'example:dialog:delete']
|
||||
}
|
||||
]
|
||||
|
||||
export default [
|
||||
// 列表接口
|
||||
{
|
||||
url: '/mock/user/list',
|
||||
method: 'get',
|
||||
response: ({ query }) => {
|
||||
const { username, pageIndex, pageSize } = query
|
||||
|
||||
const mockList = List.filter((item) => {
|
||||
if (username && item.username.indexOf(username) < 0) return false
|
||||
return true
|
||||
})
|
||||
const pageList = mockList.filter(
|
||||
(_, index) => index < pageSize * pageIndex && index >= pageSize * (pageIndex - 1)
|
||||
)
|
||||
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: {
|
||||
total: mockList.length,
|
||||
list: pageList
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 登录接口
|
||||
{
|
||||
url: '/mock/user/login',
|
||||
method: 'post',
|
||||
timeout,
|
||||
response: ({ body }) => {
|
||||
const data = body
|
||||
let hasUser = false
|
||||
for (const user of List) {
|
||||
if (user.username === data.username && user.password === data.password) {
|
||||
hasUser = true
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: user
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasUser) {
|
||||
return {
|
||||
code: 500,
|
||||
message: '账号或密码错误'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 退出接口
|
||||
{
|
||||
url: '/mock/user/loginOut',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: null
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
169
promo-ui2/mock/workplace/index.mock.ts
Normal file
@@ -0,0 +1,169 @@
|
||||
import { SUCCESS_CODE } from '@/constants'
|
||||
|
||||
const timeout = 1000
|
||||
|
||||
export default [
|
||||
// 获取统计
|
||||
{
|
||||
url: '/mock/workplace/total',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: {
|
||||
project: 40,
|
||||
access: 2340,
|
||||
todo: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 获取项目
|
||||
{
|
||||
url: '/mock/workplace/project',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: [
|
||||
{
|
||||
name: 'Github',
|
||||
icon: 'akar-icons:github-fill',
|
||||
message: 'workplace.introduction',
|
||||
personal: 'Archer',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
name: 'Vue',
|
||||
icon: 'logos:vue',
|
||||
message: 'workplace.introduction',
|
||||
personal: 'Archer',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
name: 'Angular',
|
||||
icon: 'logos:angular-icon',
|
||||
message: 'workplace.introduction',
|
||||
personal: 'Archer',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
name: 'React',
|
||||
icon: 'logos:react',
|
||||
message: 'workplace.introduction',
|
||||
personal: 'Archer',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
name: 'Webpack',
|
||||
icon: 'logos:webpack',
|
||||
message: 'workplace.introduction',
|
||||
personal: 'Archer',
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
name: 'Vite',
|
||||
icon: 'vscode-icons:file-type-vite',
|
||||
message: 'workplace.introduction',
|
||||
personal: 'Archer',
|
||||
time: new Date()
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
// 获取动态
|
||||
{
|
||||
url: '/mock/workplace/dynamic',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: [
|
||||
{
|
||||
keys: ['workplace.push', 'Github'],
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
keys: ['workplace.push', 'Github'],
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
keys: ['workplace.push', 'Github'],
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
keys: ['workplace.push', 'Github'],
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
keys: ['workplace.push', 'Github'],
|
||||
time: new Date()
|
||||
},
|
||||
{
|
||||
keys: ['workplace.push', 'Github'],
|
||||
time: new Date()
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
// 获取团队信息
|
||||
{
|
||||
url: '/mock/workplace/team',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: [
|
||||
{
|
||||
name: 'Github',
|
||||
icon: 'akar-icons:github-fill'
|
||||
},
|
||||
{
|
||||
name: 'Vue',
|
||||
icon: 'logos:vue'
|
||||
},
|
||||
{
|
||||
name: 'Angular',
|
||||
icon: 'logos:angular-icon'
|
||||
},
|
||||
{
|
||||
name: 'React',
|
||||
icon: 'logos:react'
|
||||
},
|
||||
{
|
||||
name: 'Webpack',
|
||||
icon: 'logos:webpack'
|
||||
},
|
||||
{
|
||||
name: 'Vite',
|
||||
icon: 'vscode-icons:file-type-vite'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
// 获取指数
|
||||
{
|
||||
url: '/mock/workplace/radar',
|
||||
method: 'get',
|
||||
timeout,
|
||||
response: () => {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: [
|
||||
{ name: 'workplace.quote', max: 65, personal: 42, team: 50 },
|
||||
{ name: 'workplace.contribution', max: 160, personal: 30, team: 140 },
|
||||
{ name: 'workplace.hot', max: 300, personal: 20, team: 28 },
|
||||
{ name: 'workplace.yield', max: 130, personal: 35, team: 35 },
|
||||
{ name: 'workplace.follow', max: 100, personal: 80, team: 90 }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
139
promo-ui2/package.json
Normal file
@@ -0,0 +1,139 @@
|
||||
{
|
||||
"name": "vue-element-plus-admin",
|
||||
"version": "2.9.0",
|
||||
"description": "一套基于vue3、element-plus、typesScript、vite4的后台集成方案。",
|
||||
"author": "Archer <502431556@qq.com>",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"i": "pnpm install",
|
||||
"dev": "pnpm vite --mode base",
|
||||
"ts:check": "pnpm vue-tsc --noEmit --skipLibCheck",
|
||||
"build:pro": "pnpm vite build --mode pro",
|
||||
"build:gitee": "pnpm vite build --mode gitee",
|
||||
"build:dev": "pnpm vite build --mode dev",
|
||||
"build:test": "pnpm vite build --mode test",
|
||||
"serve:pro": "pnpm vite preview --mode pro",
|
||||
"serve:dev": "pnpm vite preview --mode dev",
|
||||
"serve:test": "pnpm vite preview --mode test",
|
||||
"npm:check": "pnpx npm-check-updates -u",
|
||||
"clean": "pnpx rimraf node_modules",
|
||||
"clean:cache": "pnpx rimraf node_modules/.cache",
|
||||
"lint:eslint": "eslint . --fix \"src/**/*.{js,ts,tsx,vue,html}\"",
|
||||
"lint:format": "prettier --write --loglevel warn \"src/**/*.{js,ts,json,tsx,css,less,vue,html,md}\"",
|
||||
"lint:style": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
|
||||
"lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.cjs",
|
||||
"prepare": "husky install",
|
||||
"p": "plop",
|
||||
"icon": "esno ./scripts/icon.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iconify/iconify": "^3.1.1",
|
||||
"@iconify/vue": "^4.3.0",
|
||||
"@vueuse/core": "^12.3.0",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.10",
|
||||
"@zxcvbn-ts/core": "^3.0.4",
|
||||
"animate.css": "^4.1.1",
|
||||
"axios": "^1.7.9",
|
||||
"cropperjs": "^1.6.2",
|
||||
"dayjs": "^1.11.13",
|
||||
"driver.js": "^1.3.1",
|
||||
"echarts": "^5.6.0",
|
||||
"echarts-wordcloud": "^2.1.0",
|
||||
"element-plus": "2.9.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mitt": "^3.0.1",
|
||||
"monaco-editor": "^0.52.2",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.3.0",
|
||||
"pinia-plugin-persistedstate": "^4.2.0",
|
||||
"qrcode": "^1.5.4",
|
||||
"qs": "^6.13.1",
|
||||
"url": "^0.11.4",
|
||||
"vue": "3.5.13",
|
||||
"vue-draggable-plus": "^0.6.0",
|
||||
"vue-i18n": "11.0.1",
|
||||
"vue-json-pretty": "^2.4.0",
|
||||
"vue-router": "^4.5.0",
|
||||
"vue-types": "^5.1.3",
|
||||
"xgplayer": "^3.0.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^19.6.1",
|
||||
"@commitlint/config-conventional": "^19.6.0",
|
||||
"@iconify/json": "^2.2.293",
|
||||
"@intlify/unplugin-vue-i18n": "^6.0.3",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/inquirer": "^9.0.7",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/mockjs": "^1.0.10",
|
||||
"@types/node": "^22.10.5",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@types/qs": "^6.9.17",
|
||||
"@types/sortablejs": "^1.15.8",
|
||||
"@typescript-eslint/eslint-plugin": "^8.19.1",
|
||||
"@typescript-eslint/parser": "^8.19.1",
|
||||
"@unocss/transformer-variant-group": "^0.65.4",
|
||||
"@vitejs/plugin-legacy": "^6.0.0",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vitejs/plugin-vue-jsx": "^4.1.1",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"chalk": "^5.4.1",
|
||||
"consola": "^3.3.3",
|
||||
"eslint": "^9.17.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-define-config": "^2.1.0",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"eslint-plugin-vue": "^9.32.0",
|
||||
"esno": "^4.8.0",
|
||||
"fs-extra": "^11.2.0",
|
||||
"husky": "^9.1.7",
|
||||
"inquirer": "^12.3.0",
|
||||
"less": "^4.2.1",
|
||||
"lint-staged": "^15.3.0",
|
||||
"mockjs": "^1.1.0",
|
||||
"plop": "^4.0.1",
|
||||
"postcss": "^8.4.49",
|
||||
"postcss-html": "^1.7.0",
|
||||
"postcss-less": "^6.0.0",
|
||||
"prettier": "^3.4.2",
|
||||
"rimraf": "^6.0.1",
|
||||
"rollup": "^4.30.1",
|
||||
"rollup-plugin-visualizer": "^5.14.0",
|
||||
"stylelint": "^16.12.0",
|
||||
"stylelint-config-html": "^1.1.0",
|
||||
"stylelint-config-recommended": "^14.0.1",
|
||||
"stylelint-config-standard": "^36.0.1",
|
||||
"stylelint-order": "^6.0.4",
|
||||
"terser": "^5.37.0",
|
||||
"typescript": "5.7.3",
|
||||
"typescript-eslint": "^8.19.1",
|
||||
"unocss": "^0.65.4",
|
||||
"vite": "6.0.7",
|
||||
"vite-plugin-ejs": "^1.7.0",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vite-plugin-mock": "2.9.6",
|
||||
"vite-plugin-progress": "^0.0.7",
|
||||
"vite-plugin-purge-icons": "^0.10.0",
|
||||
"vite-plugin-style-import": "2.0.0",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vite-plugin-url-copy": "^1.1.4",
|
||||
"vue-tsc": "^2.2.0"
|
||||
},
|
||||
"packageManager": "pnpm@9.15.3",
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"pnpm": ">=8.1.0"
|
||||
},
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/kailong321200875/vue-element-plus-admin.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/kailong321200875/vue-element-plus-admin/issues"
|
||||
},
|
||||
"homepage": "https://github.com/kailong321200875/vue-element-plus-admin"
|
||||
}
|
||||
11
promo-ui2/plop/component/component.hbs
Normal file
@@ -0,0 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
const { getPrefixCls } = useDesign()
|
||||
|
||||
const prefixCls = getPrefixCls('{{ name }}')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="`${prefixCls}-{{ name }}`">{{ upperFirstName }}</div>
|
||||
</template>
|
||||
3
promo-ui2/plop/component/index.hbs
Normal file
@@ -0,0 +1,3 @@
|
||||
import {{ upperFirstName }} from './src/{{ upperFirstName }}.vue'
|
||||
|
||||
export { {{ upperFirstName }} }
|
||||
38
promo-ui2/plop/component/prompt.cjs
Normal file
@@ -0,0 +1,38 @@
|
||||
const toUpperCase = (str) => str.charAt(0).toUpperCase() + str.slice(1)
|
||||
|
||||
module.exports = {
|
||||
description: 'Create vue component',
|
||||
prompts: [
|
||||
{
|
||||
type: 'input',
|
||||
name: 'name',
|
||||
message: '请输入组件名称(Please enter the component name)'
|
||||
}
|
||||
],
|
||||
actions: (data) => {
|
||||
const { name } = data
|
||||
const upperFirstName = toUpperCase(name)
|
||||
|
||||
const actions = []
|
||||
if (name) {
|
||||
actions.push({
|
||||
type: 'add',
|
||||
path: `./src/components/${upperFirstName}/src/${upperFirstName}.vue`,
|
||||
templateFile: './plop/component/component.hbs',
|
||||
data: {
|
||||
name,
|
||||
upperFirstName
|
||||
}
|
||||
}, {
|
||||
type: 'add',
|
||||
path: `./src/components/${upperFirstName}/index.ts`,
|
||||
templateFile: './plop/component/index.hbs',
|
||||
data: {
|
||||
upperFirstName
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return actions
|
||||
}
|
||||
}
|
||||
37
promo-ui2/plop/view/prompt.cjs
Normal file
@@ -0,0 +1,37 @@
|
||||
const toUpperCase = (str) => str.charAt(0).toUpperCase() + str.slice(1)
|
||||
|
||||
module.exports = {
|
||||
description: 'Create vue view',
|
||||
prompts: [
|
||||
{
|
||||
type: 'input',
|
||||
name: 'path',
|
||||
message: '请输入路径(Please enter a path)',
|
||||
default: 'views'
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
name: 'name',
|
||||
message: '请输入模块名称(Please enter module name)'
|
||||
}
|
||||
],
|
||||
actions: (data) => {
|
||||
const { name, path } = data
|
||||
const upperFirstName = toUpperCase(name)
|
||||
|
||||
const actions = []
|
||||
if (name) {
|
||||
actions.push({
|
||||
type: 'add',
|
||||
path: `./src/${path}/${upperFirstName}.vue`,
|
||||
templateFile: './plop/view/view.hbs',
|
||||
data: {
|
||||
name,
|
||||
upperFirstName
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return actions
|
||||
}
|
||||
}
|
||||
7
promo-ui2/plop/view/view.hbs
Normal file
@@ -0,0 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ContentWrap } from '@/components/ContentWrap'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ContentWrap title="{{ upperFirstName }}"> {{ name }} </ContentWrap>
|
||||
</template>
|
||||
7
promo-ui2/plopfile.cjs
Normal file
@@ -0,0 +1,7 @@
|
||||
const viewGenerator = require('./plop/view/prompt.cjs')
|
||||
const componentGenerator = require('./plop/component/prompt.cjs')
|
||||
|
||||
module.exports = function (plop) {
|
||||
plop.setGenerator('view', viewGenerator)
|
||||
plop.setGenerator('component', componentGenerator)
|
||||
}
|
||||
11876
promo-ui2/pnpm-lock.yaml
generated
Normal file
5
promo-ui2/postcss.config.cjs
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
autoprefixer: {}
|
||||
}
|
||||
}
|
||||
19
promo-ui2/prettier.config.cjs
Normal file
@@ -0,0 +1,19 @@
|
||||
module.exports = {
|
||||
printWidth: 100,
|
||||
tabWidth: 2,
|
||||
useTabs: false,
|
||||
semi: false,
|
||||
vueIndentScriptAndStyle: false,
|
||||
singleQuote: true,
|
||||
quoteProps: 'as-needed',
|
||||
bracketSpacing: true,
|
||||
trailingComma: 'none',
|
||||
jsxSingleQuote: false,
|
||||
arrowParens: 'always',
|
||||
insertPragma: false,
|
||||
requirePragma: false,
|
||||
proseWrap: 'never',
|
||||
htmlWhitespaceSensitivity: 'strict',
|
||||
endOfLine: 'auto',
|
||||
rangeStart: 0
|
||||
}
|
||||
BIN
promo-ui2/public/favicon.ico
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
promo-ui2/public/logo.png
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
73
promo-ui2/scripts/icon.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import path from 'path'
|
||||
import fs from 'fs-extra'
|
||||
import inquirer from 'inquirer'
|
||||
import chalk from 'chalk'
|
||||
import pkg from '../package.json'
|
||||
import { ICON_PREFIX } from '../src/constants'
|
||||
|
||||
interface Icon {
|
||||
name: string
|
||||
prefix: string
|
||||
icons: string[]
|
||||
}
|
||||
|
||||
async function generateIcon() {
|
||||
const dir = path.resolve(process.cwd(), 'node_modules/@iconify/json')
|
||||
|
||||
const raw = await fs.readJSON(path.join(dir, 'collections.json'))
|
||||
|
||||
const collections = Object.entries(raw).map(([id, v]) => ({
|
||||
...(v as any),
|
||||
id
|
||||
}))
|
||||
|
||||
const choices = collections.map((item) => ({ key: item.id, value: item.id, name: item.name }))
|
||||
|
||||
inquirer
|
||||
.prompt([
|
||||
// {
|
||||
// type: 'list',
|
||||
// name: 'useType',
|
||||
// choices: [
|
||||
// { key: 'local', value: 'local', name: 'Local' },
|
||||
// { key: 'onLine', value: 'onLine', name: 'OnLine' }
|
||||
// ],
|
||||
// message: 'How to use icons?'
|
||||
// },
|
||||
{
|
||||
type: 'list',
|
||||
name: 'iconSet',
|
||||
choices: choices,
|
||||
message: 'Select the icon set that needs to be generated?'
|
||||
}
|
||||
])
|
||||
// ↓命令行问答的答案
|
||||
.then(async (answers) => {
|
||||
const { iconSet } = answers
|
||||
// const isOnLine = useType === 'onLine'
|
||||
const outputDir = path.resolve(process.cwd(), 'src/components/IconPicker/src/data')
|
||||
fs.ensureDir(outputDir)
|
||||
const genCollections = collections.filter((item) => [iconSet].includes(item.id))
|
||||
const prefixSet: string[] = []
|
||||
for (const info of genCollections) {
|
||||
const data = await fs.readJSON(path.join(dir, 'json', `${info.id}.json`))
|
||||
if (data) {
|
||||
const { prefix } = data
|
||||
const prefixName = `${ICON_PREFIX}${prefix}`
|
||||
const icons = Object.keys(data.icons).map((item) => `${prefixName}:${item}`)
|
||||
|
||||
await fs.writeFileSync(
|
||||
path.join('src/components/IconPicker/src/data', `icons.${prefix}.ts`),
|
||||
`export default ${JSON.stringify({ name: info.name, prefix: prefixName, icons })}`
|
||||
)
|
||||
// ↓分类处理完成,push类型名称
|
||||
prefixSet.push(prefix)
|
||||
}
|
||||
}
|
||||
console.log(
|
||||
`✨ ${chalk.cyan(`[${pkg.name}]`)}` + ' - Icon generated successfully:' + `[${prefixSet}]`
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
generateIcon()
|
||||
49
promo-ui2/src/App.vue
Normal file
@@ -0,0 +1,49 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { ConfigGlobal } from '@/components/ConfigGlobal'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
const { getPrefixCls } = useDesign()
|
||||
|
||||
const prefixCls = getPrefixCls('app')
|
||||
|
||||
const appStore = useAppStore()
|
||||
|
||||
const currentSize = computed(() => appStore.getCurrentSize)
|
||||
|
||||
const greyMode = computed(() => appStore.getGreyMode)
|
||||
|
||||
appStore.initTheme()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ConfigGlobal :size="currentSize">
|
||||
<RouterView :class="greyMode ? `${prefixCls}-grey-mode` : ''" />
|
||||
</ConfigGlobal>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
@prefix-cls: ~'@{adminNamespace}-app';
|
||||
|
||||
.size {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
padding: 0 !important;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
.size;
|
||||
|
||||
#app {
|
||||
.size;
|
||||
}
|
||||
}
|
||||
|
||||
.@{prefix-cls}-grey-mode {
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
</style>
|
||||
11
promo-ui2/src/api/common/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import request from '@/axios'
|
||||
|
||||
// 获取所有字典
|
||||
export const getDictApi = () => {
|
||||
return request.get({ url: '/mock/dict/list' })
|
||||
}
|
||||
|
||||
// 模拟获取某个字典
|
||||
export const getDictOneApi = async () => {
|
||||
return request.get({ url: '/mock/dict/one' })
|
||||
}
|
||||
23
promo-ui2/src/api/dashboard/analysis/index.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import request from '@/axios'
|
||||
import type {
|
||||
AnalysisTotalTypes,
|
||||
UserAccessSource,
|
||||
WeeklyUserActivity,
|
||||
MonthlySales
|
||||
} from './types'
|
||||
|
||||
export const getCountApi = (): Promise<IResponse<AnalysisTotalTypes[]>> => {
|
||||
return request.get({ url: '/mock/analysis/total' })
|
||||
}
|
||||
|
||||
export const getUserAccessSourceApi = (): Promise<IResponse<UserAccessSource[]>> => {
|
||||
return request.get({ url: '/mock/analysis/userAccessSource' })
|
||||
}
|
||||
|
||||
export const getWeeklyUserActivityApi = (): Promise<IResponse<WeeklyUserActivity[]>> => {
|
||||
return request.get({ url: '/mock/analysis/weeklyUserActivity' })
|
||||
}
|
||||
|
||||
export const getMonthlySalesApi = (): Promise<IResponse<MonthlySales[]>> => {
|
||||
return request.get({ url: '/mock/analysis/monthlySales' })
|
||||
}
|
||||
22
promo-ui2/src/api/dashboard/analysis/types.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
export type AnalysisTotalTypes = {
|
||||
users: number
|
||||
messages: number
|
||||
moneys: number
|
||||
shoppings: number
|
||||
}
|
||||
|
||||
export type UserAccessSource = {
|
||||
value: number
|
||||
name: string
|
||||
}
|
||||
|
||||
export type WeeklyUserActivity = {
|
||||
value: number
|
||||
name: string
|
||||
}
|
||||
|
||||
export type MonthlySales = {
|
||||
name: string
|
||||
estimate: number
|
||||
actual: number
|
||||
}
|
||||
22
promo-ui2/src/api/dashboard/workplace/index.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import request from '@/axios'
|
||||
import type { WorkplaceTotal, Project, Dynamic, Team, RadarData } from './types'
|
||||
|
||||
export const getCountApi = (): Promise<IResponse<WorkplaceTotal>> => {
|
||||
return request.get({ url: '/mock/workplace/total' })
|
||||
}
|
||||
|
||||
export const getProjectApi = (): Promise<IResponse<Project>> => {
|
||||
return request.get({ url: '/mock/workplace/project' })
|
||||
}
|
||||
|
||||
export const getDynamicApi = (): Promise<IResponse<Dynamic[]>> => {
|
||||
return request.get({ url: '/mock/workplace/dynamic' })
|
||||
}
|
||||
|
||||
export const getTeamApi = (): Promise<IResponse<Team[]>> => {
|
||||
return request.get({ url: '/mock/workplace/team' })
|
||||
}
|
||||
|
||||
export const getRadarApi = (): Promise<IResponse<RadarData[]>> => {
|
||||
return request.get({ url: '/mock/workplace/radar' })
|
||||
}
|
||||
30
promo-ui2/src/api/dashboard/workplace/types.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
export type WorkplaceTotal = {
|
||||
project: number
|
||||
access: number
|
||||
todo: number
|
||||
}
|
||||
|
||||
export type Project = {
|
||||
name: string
|
||||
icon: string
|
||||
message: string
|
||||
personal: string
|
||||
time: Date | number | string
|
||||
}
|
||||
|
||||
export type Dynamic = {
|
||||
keys: string[]
|
||||
time: Date | number | string
|
||||
}
|
||||
|
||||
export type Team = {
|
||||
name: string
|
||||
icon: string
|
||||
}
|
||||
|
||||
export type RadarData = {
|
||||
personal: number
|
||||
team: number
|
||||
max: number
|
||||
name: string
|
||||
}
|
||||
30
promo-ui2/src/api/department/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import request from '@/axios'
|
||||
import { DepartmentListResponse, DepartmentUserParams, DepartmentUserResponse } from './types'
|
||||
|
||||
export const getDepartmentApi = () => {
|
||||
return request.get<DepartmentListResponse>({ url: '/mock/department/list' })
|
||||
}
|
||||
|
||||
export const getUserByIdApi = (params: DepartmentUserParams) => {
|
||||
return request.get<DepartmentUserResponse>({ url: '/mock/department/users', params })
|
||||
}
|
||||
|
||||
export const deleteUserByIdApi = (ids: string[] | number[]) => {
|
||||
return request.post({ url: '/mock/department/user/delete', data: { ids } })
|
||||
}
|
||||
|
||||
export const saveUserApi = (data: any) => {
|
||||
return request.post({ url: '/mock/department/user/save', data })
|
||||
}
|
||||
|
||||
export const saveDepartmentApi = (data: any) => {
|
||||
return request.post({ url: '/mock/department/save', data })
|
||||
}
|
||||
|
||||
export const deleteDepartmentApi = (ids: string[] | number[]) => {
|
||||
return request.post({ url: '/mock/department/delete', data: { ids } })
|
||||
}
|
||||
|
||||
export const getDepartmentTableApi = (params: any) => {
|
||||
return request.get({ url: '/mock/department/table/list', params })
|
||||
}
|
||||
32
promo-ui2/src/api/department/types.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
export interface DepartmentItem {
|
||||
id: string
|
||||
departmentName: string
|
||||
children?: DepartmentItem[]
|
||||
}
|
||||
|
||||
export interface DepartmentListResponse {
|
||||
list: DepartmentItem[]
|
||||
}
|
||||
|
||||
export interface DepartmentUserParams {
|
||||
pageSize: number
|
||||
pageIndex: number
|
||||
id: string
|
||||
username?: string
|
||||
account?: string
|
||||
}
|
||||
|
||||
export interface DepartmentUserItem {
|
||||
id: string
|
||||
username: string
|
||||
account: string
|
||||
email: string
|
||||
createTime: string
|
||||
role: string
|
||||
department: DepartmentItem
|
||||
}
|
||||
|
||||
export interface DepartmentUserResponse {
|
||||
list: DepartmentUserItem[]
|
||||
total: number
|
||||
}
|
||||
48
promo-ui2/src/api/login/index.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import request from '@/axios'
|
||||
import type { ApiSmsBodyType, RegisterUserType, UserType } from './types'
|
||||
|
||||
interface RoleParams {
|
||||
roleName: string
|
||||
}
|
||||
|
||||
export const loginApi = (data: UserType): Promise<IResponse<UserType>> => {
|
||||
return request.post({ url: '/promo/login', data })
|
||||
}
|
||||
|
||||
export const registerApi = (data: RegisterUserType): Promise<IResponse<UserType>> => {
|
||||
return request.post({ url: '/promo/register', data })
|
||||
}
|
||||
|
||||
export const getCodeApi = (phoneNumber: string): Promise<IResponse<UserType>> => {
|
||||
return request.post({
|
||||
url: '/api/sms/getVerifyCode',
|
||||
data: {
|
||||
phoneNumber: phoneNumber,
|
||||
type: '1'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const loginOutApi = (): Promise<IResponse> => {
|
||||
return request.get({ url: '/mock/user/loginOut' })
|
||||
}
|
||||
|
||||
export const getUserListApi = ({ params }: AxiosConfig) => {
|
||||
return request.get<{
|
||||
code: string
|
||||
data: {
|
||||
list: UserType[]
|
||||
total: number
|
||||
}
|
||||
}>({ url: '/mock/user/list', params })
|
||||
}
|
||||
|
||||
export const getAdminRoleApi = (
|
||||
params: RoleParams
|
||||
): Promise<IResponse<AppCustomRouteRecordRaw[]>> => {
|
||||
return request.get({ url: '/mock/role/list', params })
|
||||
}
|
||||
|
||||
export const getTestRoleApi = (params: RoleParams): Promise<IResponse<string[]>> => {
|
||||
return request.get({ url: '/mock/role/list2', params })
|
||||
}
|
||||
28
promo-ui2/src/api/login/types.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
export interface UserLoginType {
|
||||
username: string
|
||||
password: string
|
||||
}
|
||||
|
||||
export interface UserType {
|
||||
uid: number
|
||||
username: string
|
||||
password: string
|
||||
role: string
|
||||
roleId: string
|
||||
token: string
|
||||
shareLink: string
|
||||
shareDomain: string
|
||||
}
|
||||
|
||||
export interface RegisterUserType {
|
||||
username: string
|
||||
password: string
|
||||
check_password: string
|
||||
contactInformation: string
|
||||
parentInvitationCode: string
|
||||
}
|
||||
|
||||
export interface ApiSmsBodyType {
|
||||
phoneNumber: string;
|
||||
type: string;
|
||||
}
|
||||
5
promo-ui2/src/api/menu/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import request from '@/axios'
|
||||
|
||||
export const getMenuListApi = () => {
|
||||
return request.get({ url: '/mock/menu/list' })
|
||||
}
|
||||
38
promo-ui2/src/api/request/index.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import request from '@/axios'
|
||||
import { RequestResponse } from './types'
|
||||
|
||||
export const request1 = () => {
|
||||
return request.get<IResponse<RequestResponse>>({
|
||||
url: '/mock/request/1'
|
||||
})
|
||||
}
|
||||
|
||||
export const request2 = () => {
|
||||
return request.get<IResponse<RequestResponse>>({
|
||||
url: '/mock/request/2'
|
||||
})
|
||||
}
|
||||
|
||||
export const request3 = () => {
|
||||
return request.get<IResponse<RequestResponse>>({
|
||||
url: '/mock/request/3'
|
||||
})
|
||||
}
|
||||
|
||||
export const request4 = () => {
|
||||
return request.get<IResponse<RequestResponse>>({
|
||||
url: '/mock/request/4'
|
||||
})
|
||||
}
|
||||
|
||||
export const request5 = () => {
|
||||
return request.get<IResponse<RequestResponse>>({
|
||||
url: '/mock/request/5'
|
||||
})
|
||||
}
|
||||
|
||||
export const expired = () => {
|
||||
return request.get<IResponse<RequestResponse>>({
|
||||
url: '/mock/request/expired'
|
||||
})
|
||||
}
|
||||
3
promo-ui2/src/api/request/types.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export interface RequestResponse {
|
||||
data: string
|
||||
}
|
||||
5
promo-ui2/src/api/role/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import request from '@/axios'
|
||||
|
||||
export const getRoleListApi = () => {
|
||||
return request.get({ url: '/mock/role/table' })
|
||||
}
|
||||
29
promo-ui2/src/api/subflow/index.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import request from '@/axios'
|
||||
import { getPurchaseByUserIdRequest, getSubBranchesRequest } from './types'
|
||||
|
||||
export function getSubBranches(req: getSubBranchesRequest) {
|
||||
return request.get({
|
||||
url: '/promo/turnover/getSubBranches',
|
||||
params: req
|
||||
})
|
||||
}
|
||||
|
||||
export function getPurchaseByUserId(req: getPurchaseByUserIdRequest) {
|
||||
return request.get({
|
||||
url: '/promo/turnover/getPurchaseByUserId/' + req.userId,
|
||||
params: req
|
||||
})
|
||||
}
|
||||
|
||||
export function getCommissionRateByUserId(userId) {
|
||||
return request.get({
|
||||
url: '/promo/turnover/getCommissionRateByUserId/' + userId
|
||||
})
|
||||
}
|
||||
|
||||
export function updateCommissionRate(data) {
|
||||
return request.put({
|
||||
url: '/promo/turnover/updateCommissionRate',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
14
promo-ui2/src/api/subflow/types.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export interface getPurchaseByUserIdRequest {
|
||||
pageNum: number
|
||||
pageSize: number
|
||||
beginTime: undefined | string
|
||||
endTime: string | undefined
|
||||
userId: undefined | string | number
|
||||
}
|
||||
|
||||
export interface getSubBranchesRequest {
|
||||
pageNum: number
|
||||
pageSize: number
|
||||
userId: undefined | string | number
|
||||
playerId: undefined | string | number
|
||||
}
|
||||
26
promo-ui2/src/api/table/index.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import request from '@/axios'
|
||||
import type { TableData } from './types'
|
||||
|
||||
export const getTableListApi = (params: any) => {
|
||||
return request.get({ url: '/mock/example/list', params })
|
||||
}
|
||||
|
||||
export const getCardTableListApi = (params: any) => {
|
||||
return request.get({ url: '/mock/card/list', params })
|
||||
}
|
||||
|
||||
export const getTreeTableListApi = (params: any) => {
|
||||
return request.get({ url: '/mock/example/treeList', params })
|
||||
}
|
||||
|
||||
export const saveTableApi = (data: Partial<TableData>): Promise<IResponse> => {
|
||||
return request.post({ url: '/mock/example/save', data })
|
||||
}
|
||||
|
||||
export const getTableDetApi = (id: string): Promise<IResponse<TableData>> => {
|
||||
return request.get({ url: '/mock/example/detail', params: { id } })
|
||||
}
|
||||
|
||||
export const delTableListApi = (ids: string[] | number[]): Promise<IResponse> => {
|
||||
return request.post({ url: '/mock/example/delete', data: { ids } })
|
||||
}
|
||||
9
promo-ui2/src/api/table/types.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export type TableData = {
|
||||
id: string
|
||||
author: string
|
||||
title: string
|
||||
content: string
|
||||
importance: number
|
||||
display_time: string
|
||||
pageviews: number
|
||||
}
|
||||
27
promo-ui2/src/api/turnover/index.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import request from '@/axios'
|
||||
|
||||
export function getRealTimeData() {
|
||||
return request.get({
|
||||
url: '/promo/turnover/getRealTimeData'
|
||||
})
|
||||
}
|
||||
|
||||
export function getLast10DaysPromotionData() {
|
||||
return request.get({
|
||||
url: '/promo/turnover/getLast10DaysPromotionData'
|
||||
})
|
||||
}
|
||||
|
||||
export function getAnchorPromotionData(query) {
|
||||
return request.get({
|
||||
url: '/promo/turnover/getAnchorPromotionData',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
export function queryPromoteWelfare(query) {
|
||||
return request.get({
|
||||
url: '/promo/turnover/queryPromoteWelfare',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
33
promo-ui2/src/api/user/index.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import request from '@/axios'
|
||||
|
||||
export function getInfo() {
|
||||
return request.get({
|
||||
url: '/api/getInfo',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function updateInvitationCode(data: any) {
|
||||
return request.post({
|
||||
url: '/promo/updateInvitationCode',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function getShareDomain() {
|
||||
return request.get({
|
||||
url: '/promo/getsharedomain'
|
||||
})
|
||||
}
|
||||
|
||||
export function getRechargeListApi() {
|
||||
return request.get({
|
||||
url: '/promo/card/list'
|
||||
})
|
||||
}
|
||||
|
||||
export function generateCardListApi(id:number, num:number) {
|
||||
return request.post({
|
||||
url: `/promo/generateCard/${id}/${num}`
|
||||
})
|
||||
}
|
||||
BIN
promo-ui2/src/assets/imgs/avatar.jpg
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
promo-ui2/src/assets/imgs/logo.png
Normal file
|
After Width: | Height: | Size: 9.0 KiB |
BIN
promo-ui2/src/assets/imgs/personal-center-bg.jpg
Normal file
|
After Width: | Height: | Size: 181 KiB |
1
promo-ui2/src/assets/svgs/403.svg
Normal file
|
After Width: | Height: | Size: 13 KiB |
1
promo-ui2/src/assets/svgs/404.svg
Normal file
|
After Width: | Height: | Size: 13 KiB |
1
promo-ui2/src/assets/svgs/500.svg
Normal file
|
After Width: | Height: | Size: 19 KiB |
1
promo-ui2/src/assets/svgs/icon.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M115.147.062a13 13 0 014.94.945c1.55.63 2.907 1.526 4.069 2.688a13.148 13.148 0 012.761 4.069c.678 1.55 1.017 3.245 1.017 5.086v102.3c0 3.681-1.187 6.733-3.56 9.155-2.373 2.422-5.352 3.633-8.937 3.633H12.992c-3.875 0-7-1.26-9.373-3.779-2.373-2.518-3.56-5.667-3.56-9.445V12.704c0-3.39 1.163-6.345 3.488-8.863C5.872 1.32 8.972.062 12.847.062h102.3zM81.434 109.047c1.744 0 3.003-.412 3.778-1.235.775-.824 1.163-1.914 1.163-3.27 0-1.26-.388-2.325-1.163-3.197-.775-.872-2.034-1.307-3.778-1.307H72.57c.097-.194.145-.485.145-.872V27.09h9.01c1.743 0 2.954-.436 3.633-1.308.678-.872 1.017-1.938 1.017-3.197 0-1.26-.34-2.325-1.017-3.197-.679-.872-1.89-1.308-3.633-1.308H46.268c-1.743 0-2.954.436-3.632 1.308-.678.872-1.018 1.938-1.018 3.197 0 1.26.34 2.325 1.018 3.197.678.872 1.889 1.308 3.632 1.308h8.138v72.075c0 .193.024.339.073.436.048.096.072.242.072.436H46.56c-1.744 0-3.003.435-3.778 1.307-.775.872-1.163 1.938-1.163 3.197 0 1.356.388 2.446 1.163 3.27.775.823 2.034 1.235 3.778 1.235h34.875z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
1
promo-ui2/src/assets/svgs/login-bg.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="5760" height="3040"><image width="5760" height="3040" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAFoAAAAvgAQMAAAC1QKagAAAABGdBTUEAALGPC/xhBQAAACBjSFJN AAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABlBMVEUsNEr///91v/yPAAAA AWJLR0QB/wIt3gAAAAd0SU1FB+YBBQYyN1c3BnEAAAhjSURBVHja7cExAQAAAMKg9U9tDB+gAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAACAtwFzzwABY3VrRQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMi0wMS0wNVQwNjo1 MDo1MyswMDowMCfNlVoAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjItMDEtMDVUMDY6NTA6NTQrMDA6 MDCTNxNoAAAAAElFTkSuQmCC"/></svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
1
promo-ui2/src/assets/svgs/login-box-bg.svg
Normal file
|
After Width: | Height: | Size: 33 KiB |
1
promo-ui2/src/assets/svgs/message.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 20.967v59.59c0 11.59 8.537 20.966 19.075 20.966h28.613l1 26.477L76.8 101.523h32.125c10.538 0 19.075-9.377 19.075-20.966v-59.59C128 9.377 119.463 0 108.925 0h-89.85C8.538 0 0 9.377 0 20.967zm82.325 33.1c0-5.524 4.013-9.935 9.037-9.935 5.026 0 9.038 4.41 9.038 9.934 0 5.524-4.025 9.934-9.038 9.934-5.024 0-9.037-4.41-9.037-9.934zm-27.613 0c0-5.524 4.013-9.935 9.038-9.935s9.037 4.41 9.037 9.934c0 5.524-4.025 9.934-9.037 9.934-5.025 0-9.038-4.41-9.038-9.934zm-27.1 0c0-5.524 4.013-9.935 9.038-9.935s9.038 4.41 9.038 9.934c0 5.524-4.026 9.934-9.05 9.934-5.013 0-9.025-4.41-9.025-9.934z"/></svg>
|
||||
|
After Width: | Height: | Size: 669 B |
1
promo-ui2/src/assets/svgs/money.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M54.122 127.892v-28.68H7.513V87.274h46.609v-12.4H7.513v-12.86h38.003L.099 0h22.6l32.556 45.07c3.617 5.144 6.44 9.611 8.487 13.385 1.788-3.05 4.89-7.779 9.301-14.186L103.93 0h24.01L82.385 62.013h38.34v12.862h-46.41v12.4h46.41v11.937h-46.41v28.68H54.123z"/></svg>
|
||||
|
After Width: | Height: | Size: 335 B |
1
promo-ui2/src/assets/svgs/peoples.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M95.648 118.762c0 5.035-3.563 9.121-7.979 9.121H7.98c-4.416 0-7.979-4.086-7.979-9.121C0 100.519 15.408 83.47 31.152 76.75c-9.099-6.43-15.216-17.863-15.216-30.987v-9.128c0-20.16 14.293-36.518 31.893-36.518s31.894 16.358 31.894 36.518v9.122c0 13.137-6.123 24.556-15.216 30.993 15.738 6.726 31.141 23.769 31.141 42.012z"/><path d="M106.032 118.252h15.867c3.376 0 6.101-3.125 6.101-6.972 0-13.957-11.787-26.984-23.819-32.123 6.955-4.919 11.638-13.66 11.638-23.704v-6.985c0-15.416-10.928-27.926-24.39-27.926-1.674 0-3.306.193-4.89.561 1.936 4.713 3.018 9.974 3.018 15.526v9.121c0 13.137-3.056 23.111-11.066 30.993 14.842 4.41 27.312 23.42 27.541 41.509z"/></svg>
|
||||
|
After Width: | Height: | Size: 731 B |
1
promo-ui2/src/assets/svgs/shopping.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M42.913 101.36c1.642 0 3.198.332 4.667.996a12.28 12.28 0 013.89 2.772c1.123 1.184 1.987 2.582 2.592 4.193.605 1.612.908 3.318.908 5.118 0 1.8-.303 3.507-.908 5.118-.605 1.611-1.469 3.01-2.593 4.194a13.3 13.3 0 01-3.889 2.843 10.582 10.582 0 01-4.667 1.066c-1.729 0-3.306-.355-4.732-1.066a13.604 13.604 0 01-3.825-2.843c-1.123-1.185-1.988-2.583-2.593-4.194a14.437 14.437 0 01-.907-5.118c0-1.8.302-3.506.907-5.118.605-1.61 1.47-3.009 2.593-4.193a12.515 12.515 0 013.825-2.772c1.426-.664 3.003-.996 4.732-.996zm53.932.285c1.643 0 3.22.331 4.733.995a11.386 11.386 0 013.889 2.772c1.08 1.185 1.945 2.583 2.593 4.194.648 1.61.972 3.317.972 5.118 0 1.8-.324 3.506-.972 5.117-.648 1.611-1.513 3.01-2.593 4.194a12.253 12.253 0 01-3.89 2.843 11 11 0 01-4.732 1.066 10.58 10.58 0 01-4.667-1.066 12.478 12.478 0 01-3.824-2.843c-1.08-1.185-1.945-2.583-2.593-4.194a13.581 13.581 0 01-.973-5.117c0-1.801.325-3.507.973-5.118.648-1.611 1.512-3.01 2.593-4.194a11.559 11.559 0 013.824-2.772 11.212 11.212 0 014.667-.995zm21.781-80.747c2.42 0 4.3.355 5.64 1.066 1.34.71 2.29 1.587 2.852 2.63a6.427 6.427 0 01.778 3.34c-.044 1.185-.195 2.204-.454 3.057-.26.853-.8 2.606-1.62 5.26a589.268 589.268 0 01-2.788 8.743 1236.373 1236.373 0 00-3.047 9.453c-.994 3.128-1.75 5.592-2.269 7.393-1.123 3.79-2.55 6.42-4.278 7.89-1.728 1.469-3.846 2.203-6.352 2.203H39.023l1.945 12.795h65.342c4.148 0 6.223 1.943 6.223 5.828 0 1.896-.41 3.53-1.232 4.905-.821 1.374-2.442 2.061-4.862 2.061H38.505c-1.729 0-3.176-.426-4.343-1.28-1.167-.852-2.14-1.966-2.917-3.34a21.277 21.277 0 01-1.88-4.478 44.128 44.128 0 01-1.102-4.55c-.087-.568-.324-1.942-.713-4.122-.39-2.18-.865-4.904-1.426-8.174l-1.88-10.947c-.692-4.027-1.383-8.079-2.075-12.154-1.642-9.572-3.5-20.234-5.574-31.986H6.87c-1.296 0-2.377-.356-3.24-1.067a9.024 9.024 0 01-2.14-2.558 10.416 10.416 0 01-1.167-3.2C.108 8.53 0 7.488 0 6.54c0-1.896.583-3.46 1.75-4.69C2.917.615 4.494 0 6.482 0h13.095c1.728 0 3.111.284 4.148.853 1.037.569 1.858 1.28 2.463 2.132a8.548 8.548 0 011.297 2.701c.26.948.475 1.754.648 2.417.173.758.346 1.825.519 3.199.173 1.374.345 2.772.518 4.193.26 1.706.519 3.507.778 5.403h88.678z"/></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
58
promo-ui2/src/axios/config.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { AxiosResponse, InternalAxiosRequestConfig } from './types'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import qs from 'qs'
|
||||
import { SUCCESS_CODE, TRANSFORM_REQUEST_DATA } from '@/constants'
|
||||
import { useUserStoreWithOut } from '@/store/modules/user'
|
||||
import { objToFormData } from '@/utils'
|
||||
|
||||
const defaultRequestInterceptors = (config: InternalAxiosRequestConfig) => {
|
||||
if (
|
||||
config.method === 'post' &&
|
||||
config.headers['Content-Type'] === 'application/x-www-form-urlencoded'
|
||||
) {
|
||||
config.data = qs.stringify(config.data)
|
||||
} else if (
|
||||
TRANSFORM_REQUEST_DATA &&
|
||||
config.method === 'post' &&
|
||||
config.headers['Content-Type'] === 'multipart/form-data' &&
|
||||
!(config.data instanceof FormData)
|
||||
) {
|
||||
config.data = objToFormData(config.data)
|
||||
}
|
||||
if (config.method === 'get' && config.params) {
|
||||
let url = config.url as string
|
||||
url += '?'
|
||||
const keys = Object.keys(config.params)
|
||||
for (const key of keys) {
|
||||
if (config.params[key] !== void 0 && config.params[key] !== null) {
|
||||
url += `${key}=${encodeURIComponent(config.params[key])}&`
|
||||
}
|
||||
}
|
||||
url = url.substring(0, url.length - 1)
|
||||
config.params = {}
|
||||
config.url = url
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
const defaultResponseInterceptors = (response: AxiosResponse) => {
|
||||
if (response?.config?.responseType === 'blob') {
|
||||
// 如果是文件流,直接过
|
||||
return response
|
||||
} else if (response.data.code === SUCCESS_CODE || response.data.code === 200) {
|
||||
return response.data
|
||||
} else {
|
||||
if (response?.data?.msg) {
|
||||
ElMessage.error(response?.data?.msg)
|
||||
} else {
|
||||
ElMessage.error(response?.data?.message)
|
||||
}
|
||||
|
||||
if (response?.data?.code === 401) {
|
||||
const userStore = useUserStoreWithOut()
|
||||
userStore.logout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { defaultResponseInterceptors, defaultRequestInterceptors }
|
||||
42
promo-ui2/src/axios/index.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import service from './service'
|
||||
import { CONTENT_TYPE } from '@/constants'
|
||||
import { useUserStoreWithOut } from '@/store/modules/user'
|
||||
|
||||
const request = (option: AxiosConfig) => {
|
||||
const { url, method, params, data, headers, responseType } = option
|
||||
|
||||
const userStore = useUserStoreWithOut()
|
||||
return service.request({
|
||||
url: url,
|
||||
method,
|
||||
params,
|
||||
data: data,
|
||||
responseType: responseType,
|
||||
headers: {
|
||||
'Content-Type': CONTENT_TYPE,
|
||||
[userStore.getTokenKey ?? 'Authorization']: userStore.getToken ?? '',
|
||||
...headers
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
get: <T = any>(option: AxiosConfig) => {
|
||||
return request({ method: 'get', ...option }) as Promise<IResponse<T>>
|
||||
},
|
||||
post: <T = any>(option: AxiosConfig) => {
|
||||
return request({ method: 'post', ...option }) as Promise<IResponse<T>>
|
||||
},
|
||||
delete: <T = any>(option: AxiosConfig) => {
|
||||
return request({ method: 'delete', ...option }) as Promise<IResponse<T>>
|
||||
},
|
||||
put: <T = any>(option: AxiosConfig) => {
|
||||
return request({ method: 'put', ...option }) as Promise<IResponse<T>>
|
||||
},
|
||||
cancelRequest: (url: string | string[]) => {
|
||||
return service.cancelRequest(url)
|
||||
},
|
||||
cancelAllRequest: () => {
|
||||
return service.cancelAllRequest()
|
||||
}
|
||||
}
|
||||
76
promo-ui2/src/axios/service.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import axios, { AxiosError } from 'axios'
|
||||
import { defaultRequestInterceptors, defaultResponseInterceptors } from './config'
|
||||
import { AxiosInstance, InternalAxiosRequestConfig, RequestConfig, AxiosResponse } from './types'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { REQUEST_TIMEOUT } from '@/constants'
|
||||
|
||||
export const PATH_URL = import.meta.env.VITE_API_BASE_PATH
|
||||
|
||||
const abortControllerMap: Map<string, AbortController> = new Map()
|
||||
|
||||
const axiosInstance: AxiosInstance = axios.create({
|
||||
timeout: REQUEST_TIMEOUT,
|
||||
baseURL: PATH_URL
|
||||
})
|
||||
|
||||
axiosInstance.interceptors.request.use((res: InternalAxiosRequestConfig) => {
|
||||
const controller = new AbortController()
|
||||
const url = res.url || ''
|
||||
res.signal = controller.signal
|
||||
abortControllerMap.set(
|
||||
import.meta.env.VITE_USE_MOCK === 'true' ? url.replace('/mock', '') : url,
|
||||
controller
|
||||
)
|
||||
return res
|
||||
})
|
||||
|
||||
axiosInstance.interceptors.response.use(
|
||||
(res: AxiosResponse) => {
|
||||
const url = res.config.url || ''
|
||||
abortControllerMap.delete(url)
|
||||
// 这里不能做任何处理,否则后面的 interceptors 拿不到完整的上下文了
|
||||
return res
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
console.log('err: ' + error) // for debug
|
||||
ElMessage.error(error.message)
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
axiosInstance.interceptors.request.use(defaultRequestInterceptors)
|
||||
axiosInstance.interceptors.response.use(defaultResponseInterceptors)
|
||||
|
||||
const service = {
|
||||
request: (config: RequestConfig) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (config.interceptors?.requestInterceptors) {
|
||||
config = config.interceptors.requestInterceptors(config as any)
|
||||
}
|
||||
|
||||
axiosInstance
|
||||
.request(config)
|
||||
.then((res) => {
|
||||
resolve(res)
|
||||
})
|
||||
.catch((err: any) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
cancelRequest: (url: string | string[]) => {
|
||||
const urlList = Array.isArray(url) ? url : [url]
|
||||
for (const _url of urlList) {
|
||||
abortControllerMap.get(_url)?.abort()
|
||||
abortControllerMap.delete(_url)
|
||||
}
|
||||
},
|
||||
cancelAllRequest() {
|
||||
for (const [_, controller] of abortControllerMap) {
|
||||
controller.abort()
|
||||
}
|
||||
abortControllerMap.clear()
|
||||
}
|
||||
}
|
||||
|
||||
export default service
|
||||
31
promo-ui2/src/axios/types/index.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import type {
|
||||
InternalAxiosRequestConfig,
|
||||
AxiosResponse,
|
||||
AxiosRequestConfig,
|
||||
AxiosInstance,
|
||||
AxiosRequestHeaders,
|
||||
AxiosError
|
||||
} from 'axios'
|
||||
|
||||
interface RequestInterceptors<T> {
|
||||
// 请求拦截
|
||||
requestInterceptors?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig
|
||||
requestInterceptorsCatch?: (err: any) => any
|
||||
// 响应拦截
|
||||
responseInterceptors?: (config: T) => T
|
||||
responseInterceptorsCatch?: (err: any) => any
|
||||
}
|
||||
|
||||
interface RequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
|
||||
interceptors?: RequestInterceptors<T>
|
||||
}
|
||||
|
||||
export {
|
||||
AxiosResponse,
|
||||
RequestInterceptors,
|
||||
RequestConfig,
|
||||
AxiosInstance,
|
||||
InternalAxiosRequestConfig,
|
||||
AxiosRequestHeaders,
|
||||
AxiosError
|
||||
}
|
||||
4
promo-ui2/src/components/Avatars/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import Avatars from './src/Avatars.vue'
|
||||
|
||||
export type { AvatarItem } from './src/types'
|
||||
export { Avatars }
|
||||
79
promo-ui2/src/components/Avatars/src/Avatars.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<script setup lang="ts">
|
||||
import { ComponentSize, ElAvatar, ElTooltip } from 'element-plus'
|
||||
import { PropType, computed } from 'vue'
|
||||
import { AvatarItem } from './types'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
const { getPrefixCls } = useDesign()
|
||||
|
||||
const prefixCls = getPrefixCls('avatars')
|
||||
|
||||
const props = defineProps({
|
||||
size: {
|
||||
type: [String, Number] as PropType<ComponentSize | number>,
|
||||
default: ''
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
default: 5
|
||||
},
|
||||
data: {
|
||||
type: Array as PropType<AvatarItem[]>,
|
||||
default: () => []
|
||||
},
|
||||
showTooltip: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
|
||||
const filterData = computed(() => props.data.slice(0, props.max))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="prefixCls" class="flex items-center">
|
||||
<template v-for="item in filterData" :key="item.url">
|
||||
<template v-if="showTooltip && item.name">
|
||||
<ElTooltip :content="item.name" placement="top">
|
||||
<ElAvatar
|
||||
:size="size"
|
||||
:src="item.url"
|
||||
class="relative"
|
||||
:style="{
|
||||
zIndex: filterData.indexOf(item)
|
||||
}"
|
||||
/>
|
||||
</ElTooltip>
|
||||
</template>
|
||||
<template v-else>
|
||||
<ElAvatar
|
||||
:size="size"
|
||||
:src="item.url"
|
||||
class="relative"
|
||||
:style="{
|
||||
zIndex: filterData.indexOf(item)
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<ElAvatar
|
||||
v-if="data.length > max"
|
||||
:style="{
|
||||
zIndex: data.length
|
||||
}"
|
||||
>
|
||||
<span>+{{ data.length - max }}</span>
|
||||
</ElAvatar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="less">
|
||||
@prefix-cls: ~'@{adminNamespace}-avatars';
|
||||
|
||||
.@{prefix-cls} {
|
||||
.@{elNamespace}-avatar + .@{elNamespace}-avatar {
|
||||
margin-left: -15px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
4
promo-ui2/src/components/Avatars/src/types/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface AvatarItem {
|
||||
url: string
|
||||
name?: string
|
||||
}
|
||||
3
promo-ui2/src/components/Backtop/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import Backtop from './src/Backtop.vue'
|
||||
|
||||
export { Backtop }
|
||||
15
promo-ui2/src/components/Backtop/src/Backtop.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { ElBacktop } from 'element-plus'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
const { getPrefixCls, variables } = useDesign()
|
||||
|
||||
const prefixCls = getPrefixCls('backtop')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElBacktop
|
||||
:class="prefixCls"
|
||||
:target="`.${variables.namespace}-layout-content-scrollbar .${variables.elNamespace}-scrollbar__wrap`"
|
||||
/>
|
||||
</template>
|
||||
3
promo-ui2/src/components/Breadcrumb/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import Breadcrumb from './src/Breadcrumb.vue'
|
||||
|
||||
export { Breadcrumb }
|
||||
126
promo-ui2/src/components/Breadcrumb/src/Breadcrumb.vue
Normal file
@@ -0,0 +1,126 @@
|
||||
<script lang="tsx">
|
||||
import { ElBreadcrumb, ElBreadcrumbItem } from 'element-plus'
|
||||
import { ref, watch, computed, unref, defineComponent, TransitionGroup } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { usePermissionStore } from '@/store/modules/permission'
|
||||
import { filterBreadcrumb } from './helper'
|
||||
import { filter, treeToList } from '@/utils/tree'
|
||||
import type { RouteLocationNormalizedLoaded } from 'vue-router'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { Icon } from '@/components/Icon'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
const { getPrefixCls } = useDesign()
|
||||
|
||||
const prefixCls = getPrefixCls('breadcrumb')
|
||||
|
||||
const appStore = useAppStore()
|
||||
|
||||
// 面包屑图标
|
||||
const breadcrumbIcon = computed(() => appStore.getBreadcrumbIcon)
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Breadcrumb',
|
||||
setup() {
|
||||
const { currentRoute } = useRouter()
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const levelList = ref<AppRouteRecordRaw[]>([])
|
||||
|
||||
const permissionStore = usePermissionStore()
|
||||
|
||||
const menuRouters = computed(() => {
|
||||
const routers = permissionStore.getRouters
|
||||
return filterBreadcrumb(routers)
|
||||
})
|
||||
|
||||
const getBreadcrumb = () => {
|
||||
const currentPath = currentRoute.value.matched.slice(-1)[0].path
|
||||
levelList.value = filter<AppRouteRecordRaw>(unref(menuRouters), (node: AppRouteRecordRaw) => {
|
||||
return node.path === currentPath
|
||||
})
|
||||
}
|
||||
|
||||
const renderBreadcrumb = () => {
|
||||
const breadcrumbList = treeToList<AppRouteRecordRaw[]>(unref(levelList))
|
||||
return breadcrumbList.map((v) => {
|
||||
const disabled = !v.redirect || v.redirect === 'noredirect'
|
||||
const meta = v.meta
|
||||
return (
|
||||
<ElBreadcrumbItem to={{ path: disabled ? '' : v.path }} key={v.name}>
|
||||
{meta?.icon && breadcrumbIcon.value ? (
|
||||
<>
|
||||
<Icon icon={meta.icon} class="mr-[5px]"></Icon> {t(v?.meta?.title || '')}
|
||||
</>
|
||||
) : (
|
||||
t(v?.meta?.title || '')
|
||||
)}
|
||||
</ElBreadcrumbItem>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
watch(
|
||||
() => currentRoute.value,
|
||||
(route: RouteLocationNormalizedLoaded) => {
|
||||
if (route.path.startsWith('/redirect/')) {
|
||||
return
|
||||
}
|
||||
getBreadcrumb()
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
return () => (
|
||||
<ElBreadcrumb separator="/" class={`${prefixCls} flex items-center h-full ml-[10px]`}>
|
||||
<TransitionGroup appear enter-active-class="animate__animated animate__fadeInRight">
|
||||
{renderBreadcrumb()}
|
||||
</TransitionGroup>
|
||||
</ElBreadcrumb>
|
||||
)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@prefix-cls: ~'@{elNamespace}-breadcrumb';
|
||||
|
||||
.@{prefix-cls} {
|
||||
:deep(&__item) {
|
||||
display: flex;
|
||||
.@{prefix-cls}__inner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--top-header-text-color);
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(&__item):not(:last-child) {
|
||||
.@{prefix-cls}__inner {
|
||||
color: var(--top-header-text-color);
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(&__item):last-child {
|
||||
.@{prefix-cls}__inner {
|
||||
color: var(--el-text-color-placeholder);
|
||||
|
||||
&:hover {
|
||||
color: var(--el-text-color-placeholder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
30
promo-ui2/src/components/Breadcrumb/src/helper.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { pathResolve } from '@/utils/routerHelper'
|
||||
|
||||
export const filterBreadcrumb = (
|
||||
routes: AppRouteRecordRaw[],
|
||||
parentPath = ''
|
||||
): AppRouteRecordRaw[] => {
|
||||
const res: AppRouteRecordRaw[] = []
|
||||
|
||||
for (const route of routes) {
|
||||
const meta = route?.meta
|
||||
if (meta.hidden && !meta.canTo) {
|
||||
continue
|
||||
}
|
||||
|
||||
const data: AppRouteRecordRaw =
|
||||
!meta.alwaysShow && route.children?.length === 1
|
||||
? { ...route.children[0], path: pathResolve(route.path, route.children[0].path) }
|
||||
: { ...route }
|
||||
|
||||
data.path = pathResolve(parentPath, data.path)
|
||||
|
||||
if (data.children) {
|
||||
data.children = filterBreadcrumb(data.children, data.path)
|
||||
}
|
||||
if (data) {
|
||||
res.push(data)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
3
promo-ui2/src/components/Button/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import BaseButton from './src/Button.vue'
|
||||
|
||||
export { BaseButton }
|
||||
121
promo-ui2/src/components/Button/src/Button.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
<script setup lang="ts">
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
import { ElButton, ComponentSize, ButtonType } from 'element-plus'
|
||||
import { PropType, Component, computed, unref } from 'vue'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
|
||||
const appStore = useAppStore()
|
||||
|
||||
const getTheme = computed(() => appStore.getTheme)
|
||||
|
||||
const { getPrefixCls } = useDesign()
|
||||
|
||||
const prefixCls = getPrefixCls('button')
|
||||
|
||||
const props = defineProps({
|
||||
size: {
|
||||
type: String as PropType<ComponentSize>,
|
||||
default: undefined
|
||||
},
|
||||
type: {
|
||||
type: String as PropType<ButtonType>,
|
||||
default: 'default'
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
plain: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
text: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
bg: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
link: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
round: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
circle: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
loadingIcon: {
|
||||
type: [String, Object] as PropType<string | Component>,
|
||||
default: undefined
|
||||
},
|
||||
icon: {
|
||||
type: [String, Object] as PropType<string | Component>,
|
||||
default: undefined
|
||||
},
|
||||
autofocus: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
nativeType: {
|
||||
type: String as PropType<'button' | 'submit' | 'reset'>,
|
||||
default: 'button'
|
||||
},
|
||||
autoInsertSpace: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
darker: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
tag: {
|
||||
type: [String, Object] as PropType<string | Component>,
|
||||
default: 'button'
|
||||
}
|
||||
})
|
||||
|
||||
const emits = defineEmits(['click'])
|
||||
|
||||
const color = computed(() => {
|
||||
const { type, link } = props
|
||||
if (type === 'primary' && !link) {
|
||||
return unref(getTheme).elColorPrimary
|
||||
}
|
||||
return ''
|
||||
})
|
||||
|
||||
const style = computed(() => {
|
||||
const { type, link } = props
|
||||
if (type === 'primary' && !link) {
|
||||
return '--el-button-text-color: #fff; --el-button-hover-text-color: #fff'
|
||||
}
|
||||
return ''
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElButton
|
||||
:class="`${prefixCls} color-#fff`"
|
||||
v-bind="{ ...props }"
|
||||
:color="color"
|
||||
:style="style"
|
||||
@click="() => emits('click')"
|
||||
>
|
||||
<slot></slot>
|
||||
<slot name="icon"></slot>
|
||||
<slot name="loading"></slot>
|
||||
</ElButton>
|
||||
</template>
|
||||
3
promo-ui2/src/components/CodeEditor/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import CodeEditor from './src/CodeEditor.vue'
|
||||
|
||||
export { CodeEditor }
|
||||
119
promo-ui2/src/components/CodeEditor/src/CodeEditor.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<script setup lang="tsx">
|
||||
import { useMonacoEditor } from '@/hooks/web/useMonacoEditor'
|
||||
import { onMounted, computed, watch, ref } from 'vue'
|
||||
import { ElSelect, ElOption, ElFormItem, ElForm } from 'element-plus'
|
||||
import { languageOptions, themeOptions } from './config/config'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
width?: string | number
|
||||
height?: string | number
|
||||
languageSelector?: boolean
|
||||
language?: string
|
||||
themeSelector?: boolean
|
||||
theme?: string
|
||||
editorOption?: object
|
||||
modelValue: string
|
||||
}>(),
|
||||
{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
languageSelector: true,
|
||||
language: 'javascript',
|
||||
themeSelector: true,
|
||||
theme: 'vs-dark',
|
||||
editorOption: () => ({}),
|
||||
modelValue: ''
|
||||
}
|
||||
)
|
||||
|
||||
const emits = defineEmits<{
|
||||
(e: 'blur'): void
|
||||
(e: 'update:modelValue', val: string): void
|
||||
}>()
|
||||
|
||||
const monacoEditorStyle = computed(() => {
|
||||
return {
|
||||
width: typeof props.width === 'string' ? props.width : props.width + 'px',
|
||||
height: typeof props.height === 'string' ? props.height : props.height + 'px'
|
||||
}
|
||||
})
|
||||
|
||||
const {
|
||||
monacoEditorRef,
|
||||
createEditor,
|
||||
updateVal,
|
||||
updateOptions,
|
||||
getEditor,
|
||||
changeLanguage,
|
||||
changeTheme
|
||||
} = useMonacoEditor(props.language)
|
||||
|
||||
onMounted(() => {
|
||||
const monacoEditor = createEditor(props.editorOption)
|
||||
updateMonacoVal(props.modelValue)
|
||||
monacoEditor?.onDidChangeModelContent(() => {
|
||||
emits('update:modelValue', monacoEditor!.getValue())
|
||||
})
|
||||
monacoEditor?.onDidBlurEditorText(() => {
|
||||
emits('blur')
|
||||
})
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
() => {
|
||||
updateMonacoVal(props.modelValue)
|
||||
}
|
||||
)
|
||||
|
||||
const localLanguage = ref(props.language)
|
||||
|
||||
watch(localLanguage, (newLanguage) => {
|
||||
changeLanguage(newLanguage)
|
||||
})
|
||||
|
||||
const localTheme = ref(props.theme)
|
||||
watch(localTheme, (newTheme) => {
|
||||
changeTheme(newTheme)
|
||||
})
|
||||
|
||||
function updateMonacoVal(val: string) {
|
||||
if (val !== getEditor()?.getValue()) {
|
||||
updateVal(val)
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ updateOptions })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElForm :inline="true">
|
||||
<ElFormItem v-if="languageSelector" label="language" class="w-30% mb-5px!">
|
||||
<ElSelect
|
||||
v-model="localLanguage"
|
||||
placeholder="Please select language"
|
||||
size="small"
|
||||
filterable
|
||||
>
|
||||
<ElOption
|
||||
v-for="item in languageOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
<ElFormItem v-if="themeSelector" label="theme" class="w-30% mb-5px!">
|
||||
<ElSelect v-model="localTheme" placeholder="Please select language" size="small" filterable>
|
||||
<ElOption
|
||||
v-for="item in themeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
<div ref="monacoEditorRef" :style="monacoEditorStyle"></div>
|
||||
</template>
|
||||
129
promo-ui2/src/components/CodeEditor/src/config/config.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
export const languageOptions = [
|
||||
{ label: 'plaintext', value: 'plaintext' },
|
||||
{ label: 'abap', value: 'abap' },
|
||||
{ label: 'apex', value: 'apex' },
|
||||
{ label: 'azcli', value: 'azcli' },
|
||||
{ label: 'bat', value: 'bat' },
|
||||
{ label: 'bicep', value: 'bicep' },
|
||||
{ label: 'cameligo', value: 'cameligo' },
|
||||
{ label: 'clojure', value: 'clojure' },
|
||||
{ label: 'coffeescript', value: 'coffeescript' },
|
||||
{ label: 'c', value: 'c' },
|
||||
{ label: 'cpp', value: 'cpp' },
|
||||
{ label: 'csharp', value: 'csharp' },
|
||||
{ label: 'csp', value: 'csp' },
|
||||
{ label: 'css', value: 'css' },
|
||||
{ label: 'cypher', value: 'cypher' },
|
||||
{ label: 'dart', value: 'dart' },
|
||||
{ label: 'dockerfile', value: 'dockerfile' },
|
||||
{ label: 'ecl', value: 'ecl' },
|
||||
{ label: 'elixir', value: 'elixir' },
|
||||
{ label: 'flow9', value: 'flow9' },
|
||||
{ label: 'fsharp', value: 'fsharp' },
|
||||
{ label: 'freemarker2', value: 'freemarker2' },
|
||||
{
|
||||
label: 'freemarker2.tag-angle.interpolation-dollar',
|
||||
value: 'freemarker2.tag-angle.interpolation-dollar'
|
||||
},
|
||||
{
|
||||
label: 'freemarker2.tag-bracket.interpolation-dollar',
|
||||
value: 'freemarker2.tag-bracket.interpolation-dollar'
|
||||
},
|
||||
{
|
||||
label: 'freemarker2.tag-angle.interpolation-bracket',
|
||||
value: 'freemarker2.tag-angle.interpolation-bracket'
|
||||
},
|
||||
{
|
||||
label: 'freemarker2.tag-bracket.interpolation-bracket',
|
||||
value: 'freemarker2.tag-bracket.interpolation-bracket'
|
||||
},
|
||||
{
|
||||
label: 'freemarker2.tag-auto.interpolation-dollar',
|
||||
value: 'freemarker2.tag-auto.interpolation-dollar'
|
||||
},
|
||||
{
|
||||
label: 'freemarker2.tag-auto.interpolation-bracket',
|
||||
value: 'freemarker2.tag-auto.interpolation-bracket'
|
||||
},
|
||||
{ label: 'go', value: 'go' },
|
||||
{ label: 'graphql', value: 'graphql' },
|
||||
{ label: 'handlebars', value: 'handlebars' },
|
||||
{ label: 'hcl', value: 'hcl' },
|
||||
{ label: 'html', value: 'html' },
|
||||
{ label: 'ini', value: 'ini' },
|
||||
{ label: 'java', value: 'java' },
|
||||
{ label: 'javascript', value: 'javascript' },
|
||||
{ label: 'julia', value: 'julia' },
|
||||
{ label: 'kotlin', value: 'kotlin' },
|
||||
{ label: 'less', value: 'less' },
|
||||
{ label: 'lexon', value: 'lexon' },
|
||||
{ label: 'lua', value: 'lua' },
|
||||
{ label: 'liquid', value: 'liquid' },
|
||||
{ label: 'm3', value: 'm3' },
|
||||
{ label: 'markdown', value: 'markdown' },
|
||||
{ label: 'mdx', value: 'mdx' },
|
||||
{ label: 'mips', value: 'mips' },
|
||||
{ label: 'msdax', value: 'msdax' },
|
||||
{ label: 'mysql', value: 'mysql' },
|
||||
{ label: 'objective-c', value: 'objective-c' },
|
||||
{ label: 'pascal', value: 'pascal' },
|
||||
{ label: 'pascaligo', value: 'pascaligo' },
|
||||
{ label: 'perl', value: 'perl' },
|
||||
{ label: 'pgsql', value: 'pgsql' },
|
||||
{ label: 'php', value: 'php' },
|
||||
{ label: 'pla', value: 'pla' },
|
||||
{ label: 'postiats', value: 'postiats' },
|
||||
{ label: 'powerquery', value: 'powerquery' },
|
||||
{ label: 'powershell', value: 'powershell' },
|
||||
{ label: 'proto', value: 'proto' },
|
||||
{ label: 'pug', value: 'pug' },
|
||||
{ label: 'python', value: 'python' },
|
||||
{ label: 'qsharp', value: 'qsharp' },
|
||||
{ label: 'r', value: 'r' },
|
||||
{ label: 'razor', value: 'razor' },
|
||||
{ label: 'redis', value: 'redis' },
|
||||
{ label: 'redshift', value: 'redshift' },
|
||||
{ label: 'restructuredtext', value: 'restructuredtext' },
|
||||
{ label: 'ruby', value: 'ruby' },
|
||||
{ label: 'rust', value: 'rust' },
|
||||
{ label: 'sb', value: 'sb' },
|
||||
{ label: 'scala', value: 'scala' },
|
||||
{ label: 'scheme', value: 'scheme' },
|
||||
{ label: 'scss', value: 'scss' },
|
||||
{ label: 'shell', value: 'shell' },
|
||||
{ label: 'sol', value: 'sol' },
|
||||
{ label: 'aes', value: 'aes' },
|
||||
{ label: 'sparql', value: 'sparql' },
|
||||
{ label: 'sql', value: 'sql' },
|
||||
{ label: 'st', value: 'st' },
|
||||
{ label: 'swift', value: 'swift' },
|
||||
{ label: 'systemverilog', value: 'systemverilog' },
|
||||
{ label: 'verilog', value: 'verilog' },
|
||||
{ label: 'tcl', value: 'tcl' },
|
||||
{ label: 'twig', value: 'twig' },
|
||||
{ label: 'typescript', value: 'typescript' },
|
||||
{ label: 'vb', value: 'vb' },
|
||||
{ label: 'wgsl', value: 'wgsl' },
|
||||
{ label: 'xml', value: 'xml' },
|
||||
{ label: 'yaml', value: 'yaml' },
|
||||
{ label: 'json', value: 'json' }
|
||||
]
|
||||
|
||||
export const themeOptions = [
|
||||
{
|
||||
label: 'vs',
|
||||
value: 'vs'
|
||||
},
|
||||
{
|
||||
label: 'vs-dark',
|
||||
value: 'vs-dark'
|
||||
},
|
||||
{
|
||||
label: 'hc-black',
|
||||
value: 'hc-black'
|
||||
},
|
||||
{
|
||||
label: 'hc-light',
|
||||
value: 'hc-light'
|
||||
}
|
||||
]
|
||||