feat 同步前端代码

feat 同步PC代码
feat 增加1.9DB
feat 同步逻辑
This commit is contained in:
damonyuan
2024-08-29 00:24:01 +08:00
parent 1e233d1207
commit 7badc8ae0f
352 changed files with 42846 additions and 37408 deletions

View File

@@ -1,4 +1,4 @@
NODE_ENV = 'development'
# 请求域名
# Base API
VITE_APP_BASE_URL=''

View File

@@ -1,4 +1,3 @@
NODE_ENV = 'production'
# 请求域名
# Base API
VITE_APP_BASE_URL=''

4
admin/.eslintignore Normal file
View File

@@ -0,0 +1,4 @@
.vscode
.idea
dist/
node_modules/

View File

@@ -11,7 +11,9 @@ module.exports = {
'@vue/eslint-config-prettier',
'./.eslintrc-auto-import.json'
],
plugins: ['simple-import-sort'],
rules: {
'simple-import-sort/imports': 'error', // 强制导入语句排序
'prettier/prettier': [
'warn',
{
@@ -34,8 +36,7 @@ module.exports = {
'no-prototype-builtins': 'off',
'prefer-spread': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
'vue/no-mutating-props': 'off'
'@typescript-eslint/no-non-null-asserted-optional-chain': 'off'
},
globals: {
module: 'readonly'

3
admin/.gitignore vendored
View File

@@ -24,6 +24,7 @@ components.d.ts
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
@@ -32,4 +33,4 @@ components.d.ts
# .env
.env.development
.env.production
.env.production

4
admin/.prettierignore Normal file
View File

@@ -0,0 +1,4 @@
.vscode
.idea
dist/
node_modules/

11
admin/.prettierrc Normal file
View File

@@ -0,0 +1,11 @@
{
"semi": false,
"singleQuote": true,
"printWidth": 100,
"proseWrap": "preserve",
"bracketSameLine": false,
"endOfLine": "lf",
"tabWidth": 4,
"useTabs": false,
"trailingComma": "none"
}

View File

@@ -1,3 +0,0 @@
{
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
}

View File

@@ -1,11 +0,0 @@
{
"editor.detectIndentation": false,
"editor.tabSize": 4,
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"css.validate": false,
"less.validate": false,
"scss.validate": false
}

View File

@@ -13,8 +13,8 @@ TypeScript cannot handle type information for `.vue` imports by default, so we r
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
1. Disable the built-in TypeScript Extension
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
1. Run `Extensions: Show Built-in Extensions` from VSCode's command palette
2. Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
## Customize configuration

View File

@@ -1,66 +1,65 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>后台管理系统</title>
<style>
* {
margin: 0;
padding: 0;
}
.preload {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
width: 100vw;
}
.circular {
height: 42px;
width: 42px;
animation: loading-rotate 2s linear infinite;
}
.circular .path {
animation: loading-dash 1.5s ease-in-out infinite;
stroke-dasharray: 90, 150;
stroke-dashoffset: 0;
stroke-width: 2;
stroke: #4073fa;
stroke-linecap: round;
}
@keyframes loading-rotate {
100% {
transform: rotate(1turn);
}
}
@keyframes loading-dash {
0% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -40px;
}
100% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -120px;
}
}
</style>
</head>
<body>
<div id="app">
<div class="preload">
<svg viewBox="25 25 50 50" class="circular">
<circle cx="50" cy="50" r="20" fill="none" class="path"></circle>
</svg>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>后台管理系统</title>
<style>
* {
margin: 0;
padding: 0;
}
.preload {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
width: 100vw;
}
.circular {
height: 42px;
width: 42px;
animation: loading-rotate 2s linear infinite;
}
.circular .path {
animation: loading-dash 1.5s ease-in-out infinite;
stroke-dasharray: 90, 150;
stroke-dashoffset: 0;
stroke-width: 2;
stroke: #4073fa;
stroke-linecap: round;
}
@keyframes loading-rotate {
100% {
transform: rotate(1turn);
}
}
@keyframes loading-dash {
0% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -40px;
}
100% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -120px;
}
}
</style>
</head>
<body>
<div id="app">
<div class="preload">
<svg viewBox="25 25 50 50" class="circular">
<circle cx="50" cy="50" r="20" fill="none" class="path"></circle>
</svg>
</div>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

29347
admin/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,61 +1,67 @@
{
"name": "vue-project",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"dev": "vite",
"preview": "vite preview --port 4173",
"build": "node ./scripts/build.mjs",
"type-check": "vue-tsc --noEmit",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
},
"dependencies": {
"@element-plus/icons-vue": "^2.0.6",
"@highlightjs/vue-plugin": "^2.1.0",
"@wangeditor/editor": "^5.1.12",
"@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^0.27.2",
"css-color-function": "^1.3.3",
"echarts": "^5.3.3",
"element-plus": "^2.2.9",
"highlight.js": "^11.6.0",
"nprogress": "^0.2.0",
"pinia": "^2.0.14",
"vue": "^3.2.37",
"vue-clipboard3": "^2.0.0",
"vue-echarts": "^6.2.3",
"vue-router": "^4.0.16",
"vue3-video-play": "^1.3.1-beta.6",
"vuedraggable": "^4.1.0"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.1.0",
"@tailwindcss/line-clamp": "^0.4.2",
"@types/lodash-es": "^4.17.6",
"@types/node": "^16.11.41",
"@types/nprogress": "^0.2.0",
"@vitejs/plugin-vue": "^3.0.0",
"@vitejs/plugin-vue-jsx": "^2.0.0",
"@vue/eslint-config-prettier": "^7.0.0",
"@vue/eslint-config-typescript": "^11.0.0",
"@vue/tsconfig": "^0.1.3",
"autoprefixer": "^10.4.7",
"consola": "^2.15.3",
"eslint": "^8.5.0",
"eslint-plugin-vue": "^9.0.0",
"execa": "^6.1.0",
"fs-extra": "^10.1.0",
"postcss": "^8.4.14",
"prettier": "^2.5.1",
"sass": "^1.53.0",
"tailwindcss": "^3.0.24",
"typescript": "~4.7.4",
"unplugin-auto-import": "^0.9.2",
"unplugin-vue-components": "^0.19.9",
"vite": "^3.0.0",
"vite-plugin-style-import": "^2.0.0",
"vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-vue-setup-extend": "^0.4.0",
"vue-tsc": "^0.38.1"
}
"name": "vue-project",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"dev": "vite",
"preview": "vite preview --port 4173",
"build": "vite build && node scripts/release.mjs",
"type-check": "vue-tsc --noEmit",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
},
"dependencies": {
"@element-plus/icons-vue": "^2.3.1",
"@highlightjs/vue-plugin": "^2.1.0",
"@vue/shared": "^3.4.38",
"@vueuse/core": "^11.0.0",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^0.27.2",
"css-color-function": "^1.3.3",
"echarts": "^5.5.1",
"element-plus": "2.2.27",
"highlight.js": "^11.10.0",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"nprogress": "^0.2.0",
"pinia": "^2.2.2",
"vue": "^3.4.38",
"vue-clipboard3": "^2.0.0",
"vue-echarts": "^6.7.3",
"vue-router": "^4.4.3",
"vue3-video-play": "1.3.1-beta.6",
"vuedraggable": "^4.1.0"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.10.4",
"@types/lodash-es": "^4.17.12",
"@types/node": "^16.18.105",
"@types/nprogress": "^0.2.3",
"@vitejs/plugin-legacy": "^2.3.1",
"@vitejs/plugin-vue": "^3.2.0",
"@vitejs/plugin-vue-jsx": "^2.1.1",
"@vue/eslint-config-prettier": "^7.1.0",
"@vue/eslint-config-typescript": "^11.0.3",
"@vue/tsconfig": "^0.1.3",
"autoprefixer": "^10.4.20",
"consola": "^2.15.3",
"eslint": "^8.57.0",
"eslint-plugin-simple-import-sort": "^12.1.1",
"eslint-plugin-vue": "^9.27.0",
"execa": "^6.1.0",
"fs-extra": "^10.1.0",
"postcss": "^8.4.41",
"prettier": "^2.8.8",
"sass": "^1.77.8",
"tailwindcss": "^3.4.10",
"terser": "^5.31.6",
"typescript": "~4.7.4",
"unplugin-auto-import": "^0.9.5",
"unplugin-vue-components": "^0.19.9",
"vite": "^3.2.10",
"vite-plugin-style-import": "^2.0.0",
"vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-vue-setup-extend": "^0.4.0",
"vue-tsc": "^0.38.9"
}
}

View File

@@ -1,15 +1,14 @@
import { execaCommand } from 'execa'
import path from 'path'
import fsExtra from 'fs-extra'
import path from 'path'
const { existsSync, remove, copy } = fsExtra
const cwd = process.cwd()
//打包发布路径,谨慎改动
const releaseRelativePath = '../public/admin'
const releaseRelativePath = '../server/public/admin'
const distPath = path.resolve(cwd, 'dist')
const releasePath = path.resolve(cwd, releaseRelativePath)
async function build() {
await execaCommand('vite build', { stdio: 'inherit', encoding: 'utf-8', cwd })
if (existsSync(releasePath)) {
await remove(releasePath)
}

View File

@@ -1,9 +1,11 @@
<script setup lang="ts">
import { useDark, useWindowSize, useThrottleFn } from '@vueuse/core'
import zhCn from 'element-plus/lib/locale/lang/zh-cn'
import { useDark, useThrottleFn, useWindowSize } from '@vueuse/core'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import { ScreenEnum } from './enums/appEnums'
import useAppStore from './stores/modules/app'
import useSettingStore from './stores/modules/setting'
import { ScreenEnum } from './enums/appEnums'
const appStore = useAppStore()
const settingStore = useSettingStore()
const elConfig = {
@@ -14,18 +16,6 @@ const isDark = useDark()
onMounted(async () => {
//设置主题色
settingStore.setTheme(isDark.value)
// 获取配置
const data: any = await appStore.getConfig()
// 设置网站logo
let favicon: HTMLLinkElement = document.querySelector('link[rel="icon"]')!
if (favicon) {
favicon.href = data.webFavicon
return
}
favicon = document.createElement('link')
favicon.rel = 'icon'
favicon.href = data.webFavicon
document.head.appendChild(favicon)
})
const { width } = useWindowSize()

View File

@@ -2,10 +2,15 @@ import request from '@/utils/request'
// 配置
export function getConfig() {
return request.get({ url: '/index/config' })
return request.get({ url: '/config/getConfig' })
}
// 工作台主页
export function getWorkbench() {
return request.get({ url: '/index/console' })
return request.get({ url: '/workbench/index' })
}
//字典数据
export function getDictData(params: any) {
return request.get({ url: '/config/dict', params })
}

View File

@@ -1,10 +1,10 @@
import request from '@/utils/request'
export function getRechargeConfig() {
return request.get({ url: '/marketing/recharge/detail' })
return request.get({ url: '/recharge.recharge/getConfig' })
}
// 设置
export function setRechargeConfig(params: any) {
return request.post({ url: '/marketing/recharge/save', params })
return request.post({ url: '/recharge.recharge/setConfig', params })
}

View File

@@ -2,41 +2,41 @@ import request from '@/utils/request'
// 文章分类列表
export function articleCateLists(params?: any) {
return request.get({ url: '/article/cate/list', params })
return request.get({ url: '/article.articleCate/lists', params })
}
// 文章分类列表
export function articleCateAll(params?: any) {
return request.get({ url: '/article/cate/all', params })
return request.get({ url: '/article.articleCate/all', params })
}
// 添加文章分类
export function articleCateAdd(params: any) {
return request.post({ url: '/article/cate/add', params })
return request.post({ url: '/article.articleCate/add', params })
}
// 编辑文章分类
export function articleCateEdit(params: any) {
return request.post({ url: '/article/cate/edit', params })
return request.post({ url: '/article.articleCate/edit', params })
}
// 删除文章分类
export function articleCateDelete(params: any) {
return request.post({ url: '/article/cate/del', params })
return request.post({ url: '/article.articleCate/delete', params })
}
// 文章分类详情
export function articleCateDetail(params: any) {
return request.get({ url: '/article/cate/detail', params })
return request.get({ url: '/article.articleCate/detail', params })
}
// 文章分类状态
export function articleCateStatus(params: any) {
return request.post({ url: '/article/cate/change', params })
return request.post({ url: '/article.articleCate/updateStatus', params })
}
// 文章列表
export function articleLists(params?: any) {
return request.get({ url: '/article/list', params })
return request.get({ url: '/article.article/lists', params })
}
// 文章列表
export function articleAll(params?: any) {
@@ -45,25 +45,25 @@ export function articleAll(params?: any) {
// 添加文章
export function articleAdd(params: any) {
return request.post({ url: '/article/add', params })
return request.post({ url: '/article.article/add', params })
}
// 编辑文章
export function articleEdit(params: any) {
return request.post({ url: '/article/edit', params })
return request.post({ url: '/article.article/edit', params })
}
// 删除文章
export function articleDelete(params: any) {
return request.post({ url: '/article/del', params })
return request.post({ url: '/article.article/delete', params })
}
// 文章详情
export function articleDetail(params: any) {
return request.get({ url: '/article/detail', params })
return request.get({ url: '/article.article/detail', params })
}
// 文章分类状态
export function articleStatus(params: any) {
return request.post({ url: '/article/change', params })
return request.post({ url: '/article.article/updateStatus', params })
}

View File

@@ -2,10 +2,10 @@ import request from '@/utils/request'
// H5渠道配置保存
export function setH5Config(params: any) {
return request.post({ url: '/channel/h5/save', params })
return request.post({ url: '/channel.web_page_setting/setConfig', params })
}
// H5渠道配置详情
export function getH5Config() {
return request.get({ url: '/channel/h5/detail' })
return request.get({ url: '/channel.web_page_setting/getConfig' })
}

View File

@@ -0,0 +1,11 @@
import request from '@/utils/request'
// 微信开发平台配置保存
export function setOpenSettingConfig(params: any) {
return request.post({ url: '/channel.open_setting/setConfig', params })
}
// 微信开发平台配置详情
export function getOpenSettingConfig() {
return request.get({ url: '/channel.open_setting/getConfig' })
}

View File

@@ -2,10 +2,10 @@ import request from '@/utils/request'
// 微信小程序配置保存
export function setWeappConfig(params: any) {
return request.post({ url: '/channel/mp/save', params })
return request.post({ url: '/channel.mnp_settings/setConfig', params })
}
// 微信小程序配置详情
export function getWeappConfig() {
return request.get({ url: '/channel/mp/detail' })
return request.get({ url: '/channel.mnp_settings/getConfig' })
}

View File

@@ -1,24 +1,23 @@
import request from '@/utils/request'
import { firstToUpperCase } from '@/utils/util'
// 微信公众号配置保存
export function setOaConfig(params: any) {
return request.post({ url: '/channel/oa/save', params })
return request.post({ url: '/channel.official_account_setting/setConfig', params })
}
// 微信公众号配置详情
export function getOaConfig() {
return request.get({ url: '/channel/oa/detail' })
return request.get({ url: '/channel.official_account_setting/getConfig' })
}
export interface Menu {
name: string
menuType?: number
visitType?: string
has_menu?: boolean
type?: string
url?: string
appId?: string
pagePath?: string
subButtons: Menu[] | any
appid?: string
pagepath?: string
sub_button: Menu[] | any
}
/**
@@ -26,7 +25,7 @@ export interface Menu {
* @description 获取菜单
*/
export function getOaMenu() {
return request.get({ url: '/channel/oaMenu/detail' })
return request.get({ url: '/channel.official_account_menu/detail' })
}
/**
@@ -35,7 +34,7 @@ export function getOaMenu() {
* @description 菜单保存
*/
export function setOaMenuSave(params: Menu | any) {
return request.post({ url: '/channel/oaMenu/save', params })
return request.post({ url: '/channel.official_account_menu/save', params })
}
/**
@@ -44,15 +43,16 @@ export function setOaMenuSave(params: Menu | any) {
* @description 菜单发布
*/
export function setOaMenuPublish(params: Menu | any) {
return request.post({ url: '/channel/oaMenu/publish', params })
return request.post({ url: '/channel.official_account_menu/saveAndPublish', params })
}
/**
* @description 默认回复列表
* @return { Promise }
* @param { string } reply_type
* @description 获取回复列表
*/
export function getOaReplyList(params: any) {
const type = firstToUpperCase(params.type)
return request.get({ url: `/channel/oaReply${type}/list`, params })
export function getOaReplyList(params: { reply_type: string }) {
return request.get({ url: '/channel.official_account_reply/lists', params })
}
/**
@@ -60,9 +60,8 @@ export function getOaReplyList(params: any) {
* @param { number } id
* @description 回复列表删除
*/
export function oaReplyDel(params: any) {
const type = firstToUpperCase(params.type)
return request.post({ url: `/channel/oaReply${type}/del`, params })
export function oaReplyDel(params: { id: number }) {
return request.post({ url: '/channel.official_account_reply/delete', params })
}
/**
@@ -70,43 +69,42 @@ export function oaReplyDel(params: any) {
* @param { number } id
* @description 回复状态修改
*/
export function changeOaReplyStatus(params: any) {
const type = firstToUpperCase(params.type)
return request.post({ url: `/channel/oaReply${type}/status`, params })
export function changeOaReplyStatus(params: { id: number }) {
return request.post({ url: '/channel.official_account_reply/status', params })
}
export interface Reply {
content: string // 内容
contentType: number // 内容类型: 1=文本
content_type: number // 内容类型: 1=文本
keyword?: string // 关键词
matchingType?: number // 匹配方式: [1=全匹配, 2=模糊匹配]
matching_type?: number // 匹配方式: [1=全匹配, 2=模糊匹配]
name: string // 规则名称
status: number // 状态: 1=开启, 0=关闭
type: string // 类型: follow=关注, keyword=关键词, default=默认
reply_type: number // 类型: 回复类型 1-关注回复 2-关键词回复 3-默认回复
reply_num: number // 回复数量`
sort: number // 排序
}
/**
* @return { Promise }
* @description 默认回复编辑
* @description 回复添加
*/
export function oaReplyAdd(params: Reply) {
const type = firstToUpperCase(params.type)
return request.post({ url: `/channel/oaReply${type}/add`, params })
return request.post({ url: '/channel.official_account_reply/add', params })
}
/**
* @return { Promise }
* @description 默认回复编辑
* @description 回复编辑
*/
export function oaReplyEdit(params: Reply) {
const type = firstToUpperCase(params.type)
return request.post({ url: `/channel/oaReply${type}/edit`, params })
return request.post({ url: '/channel.official_account_reply/edit', params })
}
/**
* @description 默认回复详情
* @return { Promise }
* @param { string } type
* @description 获取回复详情
*/
export function getOaReplyDetail(params: any) {
const type = firstToUpperCase(params.type)
return request.get({ url: `/channel/oaReply${type}/detail`, params })
export function getOaReplyDetail(params: { id: number }) {
return request.get({ url: '/channel.official_account_reply/detail', params })
}

View File

@@ -1,11 +0,0 @@
import request from '@/utils/request'
// 微信开发平台配置保存
export function setWxDevConfig(params: any) {
return request.post({ url: '/channel/op/save', params })
}
// 微信开发平台配置详情
export function getWxDevConfig() {
return request.get({ url: '/channel/op/detail' })
}

View File

@@ -2,15 +2,20 @@ import request from '@/utils/request'
// 用户列表
export function getUserList(params: any) {
return request.get({ url: '/user/list', params })
return request.get({ url: '/user.user/lists', params }, { ignoreCancelToken: true })
}
// 用户详情
export function getUserDetail(params: any) {
return request.get({ url: '/user/detail', params })
return request.get({ url: '/user.user/detail', params })
}
// 用户编辑
export function userEdit(params: any) {
return request.post({ url: '/user/edit', params })
return request.post({ url: '/user.user/edit', params })
}
// 用户编辑
export function adjustMoney(params: any) {
return request.post({ url: '/user.user/adjustMoney', params })
}

View File

@@ -2,25 +2,30 @@ import request from '@/utils/request'
// 页面装修详情
export function getDecoratePages(params: any) {
return request.get({ url: '/decorate/pages/detail', params }, { ignoreCancelToken: true })
return request.get({ url: '/decorate.page/detail', params }, { ignoreCancelToken: true })
}
// 页面装修保存
export function setDecoratePages(params: any) {
return request.post({ url: '/decorate/pages/save', params })
return request.post({ url: '/decorate.page/save', params })
}
// 获取首页文章数据
export function getDecorateArticle(params?: any) {
return request.get({ url: '/decorate/data/article', params })
return request.get({ url: '/decorate.data/article', params })
}
// 底部导航详情
export function getDecorateTabbar(params?: any) {
return request.get({ url: '/decorate/tabbar/detail', params })
return request.get({ url: '/decorate.tabbar/detail', params })
}
// 底部导航保存
export function setDecorateTabbar(params: any) {
return request.post({ url: '/decorate/tabbar/save', params })
return request.post({ url: '/decorate.tabbar/save', params })
}
// pc装修数据
export function getDecoratePc() {
return request.get({ url: '/decorate.data/pc' })
}

View File

@@ -1,39 +1,42 @@
import request from '@/utils/request'
export function fileCateAdd(params: Record<string, any>) {
return request.post({ url: '/albums/cateAdd', params })
return request.post({ url: '/file/addCate', params })
}
export function fileCateEdit(params: Record<string, any>) {
return request.post({ url: '/albums/cateRename', params })
return request.post({ url: '/file/editCate', params })
}
// 文件分类删除
export function fileCateDelete(params: Record<string, any>) {
return request.post({ url: '/albums/cateDel', params })
return request.post({ url: '/file/delCate', params })
}
// 文件分类列表
export function fileCateLists(params: Record<string, any>) {
return request.get({ url: '/albums/cateList', params })
return request.get({ url: '/file/listCate', params })
}
// 文件列表
export function fileList(params: Record<string, any>) {
return request.get({ url: '/albums/albumList', params })
return request.get(
{ url: '/file/lists', params },
{ ignoreCancelToken: true, isOpenRetry: false }
)
}
// 文件删除
export function fileDelete(params: Record<string, any>) {
return request.post({ url: '/albums/albumDel', params })
return request.post({ url: '/file/delete', params })
}
// 文件移动
export function fileMove(params: Record<string, any>) {
return request.post({ url: '/albums/albumMove', params })
return request.post({ url: '/file/move', params })
}
// 文件重命名
export function fileRename(params: { id: number; name: string }) {
return request.post({ url: '/albums/albumRename', params })
return request.post({ url: '/file/rename', params })
}

View File

@@ -2,30 +2,40 @@ import request from '@/utils/request'
// 余额明细
export function accountLog(params?: any) {
return request.get({ url: '/finance/wallet/list', params })
return request.get({ url: '/finance.account_log/lists', params })
}
// 充值记录
export function rechargeLists(params?: any) {
return request.get({ url: '/finance/recharger/list', params }, { ignoreCancelToken: true })
return request.get({ url: '/recharge.recharge/lists', params }, { ignoreCancelToken: true })
}
// 余额变动类型
export function getUmChangeType(params?: any) {
return request.get({ url: '/finance.account_log/getUmChangeType', params })
}
//退款
export function refund(params?: any) {
return request.post({ url: '/finance/recharger/refund', params })
return request.post({ url: '/recharge.recharge/refund', params })
}
//重新退款
export function refundAgain(params?: any) {
return request.post({ url: '/finance/recharger/refundAgain', params })
return request.post({ url: '/recharge.recharge/refundAgain', params })
}
//退款记录
export function refundRecord(params?: any) {
return request.get({ url: '/finance/refund/list', params })
return request.get({ url: '/finance.refund/record', params })
}
//退款日志
export function refundLog(params?: any) {
return request.get({ url: '/finance/refund/log', params })
return request.get({ url: '/finance.refund/log', params })
}
//退款统计
export function refundStat(params?: any) {
return request.get({ url: '/finance.refund/stat', params })
}

View File

@@ -2,30 +2,30 @@ import request from '@/utils/request'
// 通知设置列表
export function noticeLists(params: any) {
return request.get({ url: '/setting/notice/list', params })
return request.get({ url: '/notice.notice/settingLists', params })
}
// 通知设置详情
export function noticeDetail(params: any) {
return request.get({ url: '/setting/notice/detail', params })
return request.get({ url: '/notice.notice/detail', params })
}
// 通知设置保存
export function setNoticeConfig(params: any) {
return request.post({ url: '/setting/notice/save', params })
return request.post({ url: '/notice.notice/set', params })
}
// 短信设置列表
export function smsLists() {
return request.get({ url: '/setting/sms/list' })
return request.get({ url: '/notice.sms_config/getConfig' })
}
// 短信设置详情
export function smsDetail(params: any) {
return request.get({ url: '/setting/sms/detail', params })
return request.get({ url: '/notice.sms_config/detail', params })
}
// 短信设置保存
export function setSmsConfig(params: any) {
return request.post({ url: '/setting/sms/save', params })
return request.post({ url: '/notice.sms_config/setConfig', params })
}

View File

@@ -2,25 +2,30 @@ import request from '@/utils/request'
// 部门列表
export function deptLists(params?: any) {
return request.get({ url: '/system/dept/list', params })
return request.get({ url: '/dept.dept/lists', params })
}
// 添加部门
export function deptAdd(params: any) {
return request.post({ url: '/system/dept/add', params })
return request.post({ url: '/dept.dept/add', params })
}
// 编辑部门
export function deptEdit(params: any) {
return request.post({ url: '/system/dept/edit', params })
return request.post({ url: '/dept.dept/edit', params })
}
// 删除部门
export function deptDelete(params: any) {
return request.post({ url: '/system/dept/del', params })
return request.post({ url: '/dept.dept/delete', params })
}
// 部门详情
export function deptDetail(params?: any) {
return request.get({ url: '/system/dept/detail', params })
export function deptDetail(params: any) {
return request.get({ url: '/dept.dept/detail', params })
}
// 部门列表全部
export function deptAll() {
return request.get({ url: '/dept.dept/all' })
}

View File

@@ -1,30 +1,31 @@
import request from '@/utils/request'
// 岗位列表
export function postLists(params?: any) {
return request.get({ url: '/system/post/list', params })
export function jobsLists(params: any) {
return request.get({ url: '/dept.jobs/lists', params }, { ignoreCancelToken: true })
}
// 岗位列表
export function postAll(params?: any) {
return request.get({ url: '/system/post/all', params })
// 岗位列表全部
export function jobsAll(params: any) {
return request.get({ url: '/dept.jobs/all', params })
}
// 添加岗位
export function postAdd(params: any) {
return request.post({ url: '/system/post/add', params })
export function jobsAdd(params: any) {
return request.post({ url: '/dept.jobs/add', params })
}
// 编辑岗位
export function postEdit(params: any) {
return request.post({ url: '/system/post/edit', params })
export function jobsEdit(params: any) {
return request.post({ url: '/dept.jobs/edit', params })
}
// 删除岗位
export function postDelete(params: any) {
return request.post({ url: '/system/post/del', params })
export function jobsDelete(params: any) {
return request.post({ url: '/dept.jobs/delete', params })
}
// 岗位详情
export function postDetail(params: any) {
return request.get({ url: '/system/post/detail', params })
export function jobsDetail(params: any) {
return request.get({ url: '/dept.jobs/detail', params })
}

View File

@@ -2,30 +2,28 @@ import request from '@/utils/request'
// 管理员列表
export function adminLists(params: any) {
return request.get({ url: '/system/admin/list', params })
return request.get({ url: '/auth.admin/lists', params }, { ignoreCancelToken: true })
}
// 管理员列表全部
export function adminAll(params: any) {
return request.get({ url: '/auth.admin/all', params })
}
// 管理员添加
export function adminAdd(params: any) {
return request.post({ url: '/system/admin/add', params })
}
// 管理员编辑
export function adminDetail(params: any) {
return request.get({ url: '/system/admin/detail', params })
return request.post({ url: '/auth.admin/add', params })
}
// 管理员编辑
export function adminEdit(params: any) {
return request.post({ url: '/system/admin/edit', params })
return request.post({ url: '/auth.admin/edit', params })
}
// 管理员删除
export function adminDelete(params: any) {
return request.post({ url: '/system/admin/del', params })
return request.post({ url: '/auth.admin/delete', params })
}
// 管理员删除
export function adminStatus(params: any) {
return request.post({ url: '/system/admin/disable', params })
// 管理员详情
export function adminDetail(params: any) {
return request.get({ url: '/auth.admin/detail', params })
}

View File

@@ -1,26 +1,30 @@
import request from '@/utils/request'
// 菜单列表
export function menuLists(params?: Record<string, any>) {
return request.get({ url: '/system/menu/list', params })
export function menuLists(params: Record<string, any>) {
return request.get({ url: '/auth.menu/lists', params })
}
// 菜单全部
export function menuAll(params?: Record<string, any>) {
return request.get({ url: '/auth.menu/all', params })
}
// 添加菜单
export function menuAdd(params: Record<string, any>) {
return request.post({ url: '/system/menu/add', params })
return request.post({ url: '/auth.menu/add', params })
}
// 编辑菜单
export function menuEdit(params: Record<string, any>) {
return request.post({ url: '/system/menu/edit', params })
return request.post({ url: '/auth.menu/edit', params })
}
// 菜单删除
export function menuDelete(params: Record<string, any>) {
return request.post({ url: '/system/menu/del', params })
return request.post({ url: '/auth.menu/delete', params })
}
// 菜单删除
// 菜单详情
export function menuDetail(params: Record<string, any>) {
return request.get({ url: '/system/menu/detail', params })
return request.get({ url: '/auth.menu/detail', params })
}

View File

@@ -2,28 +2,26 @@ import request from '@/utils/request'
// 角色列表
export function roleLists(params: any) {
return request.get({ url: '/system/role/list', params })
return request.get({ url: '/auth.role/lists', params })
}
// 角色列表
export function roleAll(params?: any) {
return request.get({ url: '/system/role/all', params })
// 角色列表全部
export function roleAll(params: any) {
return request.get({ url: '/auth.role/all', params })
}
// 角色列表
export function roleDetail(params: any) {
return request.get({ url: '/system/role/detail', params })
}
// 添加角色
export function roleAdd(params: any) {
return request.post({ url: '/system/role/add', params })
return request.post({ url: '/auth.role/add', params })
}
// 编辑角色
export function roleEdit(params: any) {
return request.post({ url: '/system/role/edit', params })
return request.post({ url: '/auth.role/edit', params })
}
// 删除角色
export function roleDelete(params: any) {
return request.post({ url: '/system/role/del', params })
return request.post({ url: '/auth.role/delete', params })
}
// 角色详情
export function roleDetail(params: any) {
return request.get({ url: '/auth.role/detail', params })
}

View File

@@ -1,44 +1,39 @@
import request from '@/utils/request'
// 字典类型列表
export function dictTypeLists(params?: any) {
return request.get({ url: '/setting/dict/type/list', params })
export function dictTypeLists(params: any) {
return request.get({ url: '/setting.dict.dict_type/lists', params })
}
// 字典类型列表
export function dictTypeAll(params?: any) {
return request.get({ url: '/setting/dict/type/all', params })
// 字典类型列表全部
export function dictTypeAll(params: any) {
return request.get({ url: '/setting.dict.dict_type/all', params })
}
// 添加字典类型
export function dictTypeAdd(params: any) {
return request.post({ url: '/setting/dict/type/add', params })
return request.post({ url: '/setting.dict.dict_type/add', params })
}
// 编辑字典类型
export function dictTypeEdit(params: any) {
return request.post({ url: '/setting/dict/type/edit', params })
return request.post({ url: '/setting.dict.dict_type/edit', params })
}
// 删除字典类型
export function dictTypeDelete(params: any) {
return request.post({ url: '/setting/dict/type/del', params })
return request.post({ url: '/setting.dict.dict_type/delete', params })
}
// 字典类型详情
export function dictTypeDetail(params: any) {
return request.get({ url: '/setting.dict.dict_type/detail', params })
}
// 字典数据列表
export function dictDataLists(params: any) {
return request.get(
{ url: '/setting/dict/data/list', params },
{
ignoreCancelToken: true
}
)
}
// 字典数据列表
export function dictDataAll(params: any) {
return request.get(
{ url: '/setting/dict/data/all', params },
{ url: '/setting.dict.dict_data/lists', params },
{
ignoreCancelToken: true
}
@@ -47,15 +42,20 @@ export function dictDataAll(params: any) {
// 添加字典数据
export function dictDataAdd(params: any) {
return request.post({ url: '/setting/dict/data/add', params })
return request.post({ url: '/setting.dict.dict_data/add', params })
}
// 编辑字典数据
export function dictDataEdit(params: any) {
return request.post({ url: '/setting/dict/data/edit', params })
return request.post({ url: '/setting.dict.dict_data/edit', params })
}
// 删除字典数据
export function dictDataDelete(params: any) {
return request.post({ url: '/setting/dict/data/del', params })
return request.post({ url: '/setting.dict.dict_data/delete', params })
}
// 字典数据详情
export function dictDataDetail(params: any) {
return request.get({ url: '/setting.dict.dict_data/detail', params })
}

View File

@@ -2,25 +2,25 @@ import request from '@/utils/request'
// 获取支付方式
export function getPayWay() {
return request.get({ url: '/setting/payment/method' })
return request.get({ url: '/setting.pay.pay_way/getPayWay' })
}
// 设置支付方式
export function setPayWay(params: any) {
return request.post({ url: '/setting/payment/editMethod', params })
return request.post({ url: '/setting.pay.pay_way/setPayWay', params })
}
// 获取支付方式
export function getPayConfigLists() {
return request.get({ url: '/setting/payment/list' })
return request.get({ url: '/setting.pay.pay_config/lists' })
}
// 设置支付方式
export function setPayConfig(params: any) {
return request.post({ url: '/setting/payment/editConfig', params })
return request.post({ url: '/setting.pay.pay_config/setConfig', params })
}
// 设置支付方式
export function getPayConfig(params: any) {
return request.get({ url: '/setting/payment/detail', params })
return request.get({ url: '/setting.pay.pay_config/getConfig', params })
}

View File

@@ -5,7 +5,7 @@ import request from '@/utils/request'
* @description 获取热门搜索数据
*/
export function getSearch() {
return request.get({ url: '/setting/search/detail' })
return request.get({ url: '/setting.hot_search/getConfig' })
}
export interface List {
@@ -14,8 +14,8 @@ export interface List {
}
export interface Search {
isHotSearch: number // 是否开启搜索0/1
list: List[]
status: number // 是否开启搜索0/1
data: List[]
}
/**
* @return { Promise }
@@ -23,5 +23,5 @@ export interface Search {
* @description 设置热门搜索
*/
export function setSearch(params: Search) {
return request.post({ url: '/setting/search/save', params })
return request.post({ url: '/setting.hot_search/setConfig', params })
}

View File

@@ -2,20 +2,20 @@ import request from '@/utils/request'
// 获取存储引擎列表
export function storageLists() {
return request.get({ url: '/setting/storage/list' })
return request.get({ url: '/setting.storage/lists' })
}
// 设置存储引擎信息
export function storageChange(params: any) {
return request.post({ url: '/setting/storage/change', params })
return request.post({ url: '/setting.storage/change', params })
}
// 设置存储引擎信息
export function storageSetup(params: any) {
return request.post({ url: '/setting/storage/edit', params })
return request.post({ url: '/setting.storage/setup', params })
}
// 获取存储配置信息
export function storageDetail(params: any) {
return request.get({ url: '/setting/storage/detail', params })
return request.get({ url: '/setting.storage/detail', params })
}

View File

@@ -2,45 +2,50 @@ import request from '@/utils/request'
// 获取系统环境
export function systemInfo() {
return request.get({ url: '/monitor/server' })
return request.get({ url: '/setting.system.system/info' })
}
// 获取系统日志列表
export function systemLogLists(params: any) {
return request.get({ url: '/system/log/operate', params })
return request.get({ url: '/setting.system.log/lists', params }, { ignoreCancelToken: true })
}
// 系统缓存监控
export function systemCache() {
return request.get({ url: '/monitor/cache' })
// 清除系统缓存
export function systemCacheClear() {
return request.post({ url: '/setting.system.cache/clear' })
}
// 定时任务列表
export function crontabLists(params: any) {
return request.get({ url: '/crontab/list', params })
return request.get({ url: '/crontab.crontab/lists', params })
}
// 添加定时任务
export function crontabAdd(params: any) {
return request.post({ url: '/crontab/add', params })
return request.post({ url: '/crontab.crontab/add', params })
}
// 定时任务详情
export function crontabDetail(params: any) {
return request.get({ url: '/crontab/detail', params })
return request.get({ url: '/crontab.crontab/detail', params })
}
// 编辑定时任务
export function crontabEdit(params: any) {
return request.post({ url: '/crontab/edit', params })
return request.post({ url: '/crontab.crontab/edit', params })
}
// 删除定时任务
export function crontabDel(params: any) {
return request.post({ url: '/crontab/del', params })
return request.post({ url: '/crontab.crontab/delete', params })
}
// 获取登录日志列表
export function loginLogLists(params: any) {
return request.get({ url: '/system/log/login', params })
// 获取规则执行时间
export function crontabExpression(params: any) {
return request.get({ url: '/crontab.crontab/expression', params })
}
// 操作定时任务
export function srontabOperate(params: any) {
return request.post({ url: '/crontab.crontab/operate', params })
}

View File

@@ -5,16 +5,16 @@ import request from '@/utils/request'
* @description 获取用户设置
*/
export function getUserSetup() {
return request.get({ url: '/setting/user/detail' })
return request.get({ url: '/setting.user.user/getConfig' })
}
/**
* @return { Promise }
* @param { string } defaultAvatar 默认用户头像
* @param { string } default_avatar 默认用户头像
* @description 设置用户设置
*/
export function setUserSetup(params: { defaultAvatar: string }) {
return request.post({ url: '/setting/user/save', params })
export function setUserSetup(params: { default_avatar: string }) {
return request.post({ url: '/setting.user.user/setConfig', params })
}
/**
@@ -22,15 +22,16 @@ export function setUserSetup(params: { defaultAvatar: string }) {
* @description 设置登录注册规则
*/
export function getLogin() {
return request.get({ url: '/setting/login/detail' })
return request.get({ url: '/setting.user.user/getRegisterConfig' })
}
export interface LoginSetup {
loginWay: number[] | any // 登录方式, 逗号隔开
forceBindMobile: number // 强制绑定手机 0/1
openAgreement: number // 是否开启协议 0/1
openOtherAuth: number // 第三方登录 0/1
autoLoginAuth: number[] | any // 第三方自动登录 逗号隔开
login_way: number[] | any // 登录方式, 逗号隔开
coerce_mobile: number // 强制绑定手机 0/1
login_agreement: number // 是否开启协议 0/1
third_auth: number // 第三方登录 0/1
wechat_auth: number // 微信授权登录 0-关闭 1-开启
qq_auth: number // qq授权登录 0-关闭 1-开启
}
/**
* @return { Promise }
@@ -38,5 +39,5 @@ export interface LoginSetup {
* @description 设置登录注册规则
*/
export function setLogin(params: LoginSetup) {
return request.post({ url: '/setting/login/save', params })
return request.post({ url: '/setting.user.user/setRegisterConfig', params })
}

View File

@@ -2,26 +2,26 @@ import request from '@/utils/request'
// 获取备案信息
export function getCopyright() {
return request.get({ url: '/setting/copyright/detail' })
return request.get({ url: '/setting.web.web_setting/getCopyright' })
}
// 设置备案信息
export function setCopyright(params: any) {
return request.post({ url: '/setting/copyright/save', params })
return request.post({ url: '/setting.web.web_setting/setCopyright', params })
}
// 获取网站信息
export function getWebsite() {
return request.get({ url: '/setting/website/detail' })
return request.get({ url: '/setting.web.web_setting/getWebsite' })
}
// 设置网站信息
export function setWebsite(params: any) {
return request.post({ url: '/setting/website/save', params })
return request.post({ url: '/setting.web.web_setting/setWebsite', params })
}
// 获取政策协议
export function getProtocol() {
return request.get({ url: '/setting/protocol/detail' })
return request.get({ url: '/setting.web.web_setting/getAgreement' })
}
// 设置政策协议
export function setProtocol(params: any) {
return request.post({ url: '/setting/protocol/save', params })
return request.post({ url: '/setting.web.web_setting/setAgreement', params })
}

View File

@@ -2,74 +2,50 @@ import request from '@/utils/request'
// 代码生成已选数据表列表接口
export function generateTable(params: any) {
return request.get({ url: '/gen/list', params })
return request.get({ url: '/tools.generator/generateTable', params })
}
// 数据表列表接口
export function dataTable(params: any) {
return request.get({ url: '/gen/db', params })
return request.get({ url: '/tools.generator/dataTable', params })
}
// 数据表所有列表接口
export function dataTableAll() {
return request.get({ url: '/gen/dbAll' })
}
//表名查字段
export function dataTableToColumn(params: any) {
return request.get({ url: '/gen/dbColumn', params })
}
//选择要生成代码的数据表
export function selectTable(params: any) {
return request.post(
{ url: '/gen/importTable', params },
{
isParamsToData: false
}
)
return request.post({ url: '/tools.generator/selectTable', params })
}
// 已选择的数据表详情
export function tableDetail(params: any) {
return request.get({ url: '/gen/detail', params })
return request.get({ url: '/tools.generator/detail', params })
}
//同步字段
export function syncColumn(params: any) {
return request.post(
{ url: '/gen/syncTable', params },
{
isParamsToData: false
}
)
return request.post({ url: '/tools.generator/syncColumn', params })
}
//删除已选择的数据表
export function generateDelete(params: any) {
return request.post({ url: '/gen/delTable', params })
return request.post({ url: '/tools.generator/delete', params })
}
//编辑已选表字段
export function generateEdit(params: any) {
return request.post({ url: '/gen/editTable', params })
return request.post({ url: '/tools.generator/edit', params })
}
//预览代码
export function generatePreview(params: any) {
return request.get({ url: '/gen/previewCode', params })
return request.post({ url: '/tools.generator/preview', params })
}
//生成代码
export function generateCode(params: any) {
return request.get({ url: '/gen/genCode', params })
return request.post({ url: '/tools.generator/generate', params })
}
//下载代码
export function downloadCode(params: any) {
return request.get(
{ responseType: 'blob', url: '/gen/downloadCode', params },
{
isTransformResponse: false
}
)
//获取模型
export function getModels() {
return request.get({ url: '/tools.generator/getModels' })
}

View File

@@ -3,30 +3,20 @@ import request from '@/utils/request'
// 登录
export function login(params: Record<string, any>) {
return request.post({ url: '/system/login', params: { ...params, terminal: config.terminal } })
}
// 登录
export function loginCaptcha() {
return request.get({ url: '/system/captcha' })
return request.post({ url: '/login/account', params: { ...params, terminal: config.terminal } })
}
// 退出登录
export function logout() {
return request.post({ url: '/system/logout' })
return request.post({ url: '/login/logout' })
}
// 用户信息
export function getUserInfo() {
return request.get({ url: '/system/admin/self' })
}
// 菜单路由
export function getMenu() {
return request.get({ url: '/system/menu/route' })
return request.get({ url: '/auth.admin/mySelf' })
}
// 编辑管理员信息
export function setUserInfo(params: any) {
return request.post({ url: '/system/admin/upInfo', params })
return request.post({ url: '/auth.admin/editSelf', params })
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M11.28 9.53L8.81 12l2.47 2.47a.749.749 0 0 1-.326 1.275a.75.75 0 0 1-.734-.215l-3-3a.75.75 0 0 1 0-1.06l3-3a.749.749 0 0 1 1.275.326a.75.75 0 0 1-.215.734"/><path fill="currentColor" d="M3.75 2h16.5c.966 0 1.75.784 1.75 1.75v16.5A1.75 1.75 0 0 1 20.25 22H3.75A1.75 1.75 0 0 1 2 20.25V3.75C2 2.784 2.784 2 3.75 2M3.5 3.75v16.5c0 .138.112.25.25.25H15v-17H3.75a.25.25 0 0 0-.25.25m13 16.75h3.75a.25.25 0 0 0 .25-.25V3.75a.25.25 0 0 0-.25-.25H16.5Z"/></svg>

After

Width:  |  Height:  |  Size: 565 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M7.22 14.47L9.69 12L7.22 9.53a.749.749 0 0 1 .326-1.275a.75.75 0 0 1 .734.215l3 3a.75.75 0 0 1 0 1.06l-3 3a.75.75 0 0 1-1.042-.018a.75.75 0 0 1-.018-1.042"/><path fill="currentColor" d="M3.75 2h16.5c.966 0 1.75.784 1.75 1.75v16.5A1.75 1.75 0 0 1 20.25 22H3.75A1.75 1.75 0 0 1 2 20.25V3.75C2 2.784 2.784 2 3.75 2M3.5 3.75v16.5c0 .138.112.25.25.25H15v-17H3.75a.25.25 0 0 0-.25.25m13 16.75h3.75a.25.25 0 0 0 .25-.25V3.75a.25.25 0 0 0-.25-.25H16.5Z"/></svg>

After

Width:  |  Height:  |  Size: 565 B

View File

Before

Width:  |  Height:  |  Size: 498 B

After

Width:  |  Height:  |  Size: 498 B

View File

Before

Width:  |  Height:  |  Size: 488 B

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 735 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

View File

@@ -9,6 +9,7 @@
* @description 兼容第三方页面的跳转
*/
import { isExternal } from '@/utils/validate'
interface Props {
to: string | Record<string, string>
replace?: boolean

View File

@@ -1,33 +1,33 @@
<template>
<div class="color-picker flex flex-1">
<el-color-picker v-model="color" :predefine="predefineColors" />
<el-input v-model="color" class="mx-[10px] flex-1" type="text" readonly />
<div class="color-select flex flex-1">
<el-color-picker v-model="color" :predefine="predefineColors"></el-color-picker>
<el-input v-model="color" class="mx-[10px] flex-1" type="text" readonly></el-input>
<el-button type="text" @click="reset">重置</el-button>
</div>
</template>
<script lang="ts" setup>
<script setup lang="ts">
import { useVModel } from '@vueuse/core'
const props = defineProps({
modelValue: {
type: String
type: String,
default: ''
},
defaultColor: {
type: String
resetColor: {
type: String,
default: ''
}
})
const emit = defineEmits<{
(event: 'update:modelValue', value: any): void
(event: 'update:modelValue', value: number): void
}>()
const color = computed({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})
const predefineColors = ['#409EFF', '#28C76F', '#EA5455', '#FF9F43', '#01CFE8', '#4A5DFF']
const color = useVModel(props, 'modelValue', emit)
const predefineColors = ['#FF2C3C', '#f7971e', '#fa444d', '#e0a356', '#2f80ed', '#2ec840']
const reset = () => {
color.value = props.defaultColor
color.value = props.resetColor
}
</script>

View File

@@ -1,18 +1,17 @@
<template>
<el-date-picker
v-model="content"
type="daterange"
type="datetimerange"
range-separator="-"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
start-placeholder="开始时间"
end-placeholder="结束时间"
value-format="YYYY-MM-DD HH:mm:ss"
clearable
></el-date-picker>
</template>
<script lang="ts" setup>
import { withDefaults, computed } from 'vue'
import { computed, withDefaults } from 'vue'
/* Props S */
const props = withDefaults(

View File

@@ -1,7 +1,7 @@
<template>
<div>
<template v-for="(item, index) in getOptions" :key="index">
<span>{{ index != 0 ? '、' : '' }}{{ item.name }}</span>
<span>{{ index != 0 ? '、' : '' }}{{ item[config.label] }}</span>
</template>
</div>
</template>
@@ -10,9 +10,14 @@ const props = withDefaults(
defineProps<{
options: any[]
value: any
config: Record<string, string>
}>(),
{
options: () => []
options: () => [],
config: () => ({
label: 'name',
value: 'value'
})
}
)
@@ -25,6 +30,6 @@ const values = computed(() => {
})
const getOptions = computed(() => {
return props.options.filter((item) => values.value.includes(item.value))
return props.options.filter((item) => values.value.includes(item[props.config.value]))
})
</script>

View File

@@ -7,7 +7,7 @@
:mode="mode"
/>
<w-editor
class="overflow-y-auto flex-1"
class="flex-1 overflow-hidden"
v-model="valueHtml"
:defaultConfig="editorConfig"
:mode="mode"
@@ -24,11 +24,13 @@
</template>
<script setup lang="ts">
import '@wangeditor/editor/dist/css/style.css' // 引入 css
import { Editor as WEditor, Toolbar } from '@wangeditor/editor-for-vue'
import type { IEditorConfig, IToolbarConfig } from '@wangeditor/editor'
import { Editor as WEditor, Toolbar } from '@wangeditor/editor-for-vue'
import type { CSSProperties } from 'vue'
import MaterialPicker from '@/components/material/picker.vue'
import { addUnit } from '@/utils/util'
import type { CSSProperties } from 'vue'
const props = withDefaults(
defineProps<{

View File

@@ -0,0 +1,151 @@
<template>
<div class="export-data">
<popup
ref="popupRef"
title="导出设置"
width="500px"
confirm-button-text="确认导出"
@confirm="handleConfirm"
:async="true"
@open="getData"
>
<template #trigger>
<el-button>导出</el-button>
</template>
<div>
<el-form ref="formRef" :model="formData" label-width="120px" :rules="formRules">
<el-form-item label="数据量:">
预计导出{{ exportData.count }}条数据 {{ exportData.sum_page }}每页{{
exportData.page_size
}}条数据
</el-form-item>
<el-form-item label="导出限制:">
每次导出最大允许{{ exportData.max_page }}{{
exportData.all_max_size
}}条数据
</el-form-item>
<el-form-item prop="page_type" label="导出范围:" required>
<el-radio-group v-model="formData.page_type">
<el-radio :label="0">全部导出</el-radio>
<el-radio :label="1">分页导出</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="分页范围:" v-if="formData.page_type == 1">
<div class="flex">
<el-form-item prop="page_start">
<el-input
style="width: 140px"
v-model.number="formData.page_start"
placeholder=""
></el-input>
</el-form-item>
<span class="flex-none ml-2 mr-2"></span>
<el-form-item prop="page_end">
<el-input
style="width: 140px"
v-model.number="formData.page_end"
placeholder=""
></el-input>
</el-form-item>
</div>
</el-form-item>
<el-form-item label="导出文件名称:" prop="file_name">
<el-input
v-model="formData.file_name"
placeholder="请输入导出文件名称"
></el-input>
</el-form-item>
</el-form>
</div>
</popup>
</div>
</template>
<script lang="ts" setup>
import type { FormInstance } from 'element-plus'
import Popup from '@/components/popup/index.vue'
import feedback from '@/utils/feedback'
const formRef = shallowRef<FormInstance>()
const props = defineProps({
params: {
type: Object,
default: () => ({})
},
pageSize: {
type: Number,
default: 25
},
fetchFun: {
type: Function,
required: true
}
})
const popupRef = shallowRef<InstanceType<typeof Popup>>()
const formData = reactive({
page_type: 0,
page_start: 1,
page_end: 200,
file_name: ''
})
const formRules = {
page_start: [
{ required: true, message: '请输入起始页码' },
{ type: 'number', message: '页码必须是整数' },
{
validator: (rule: any, value: any, callback: any) => {
if (value <= 0) return callback(new Error('页码必须大于0'))
callback()
}
}
],
page_end: [
{ required: true, message: '请输入结束页码' },
{ type: 'number', message: '页码必须是整数' },
{
validator: (rule: any, value: any, callback: any) => {
if (value <= 0) return callback(new Error('页码必须大于0'))
callback()
}
}
]
}
const exportData = reactive({
count: 0,
sum_page: 0,
page_size: 0,
max_page: 0,
all_max_size: 0
})
const getData = async () => {
const res = await props.fetchFun({
...props.params,
page_size: props.pageSize,
export: 1
})
Object.assign(exportData, res)
formData.file_name = res.file_name
formData.page_end = res.page_end
formData.page_start = res.page_start
}
const handleConfirm = async () => {
await formRef.value?.validate()
feedback.loading('正在导出中...')
try {
await props.fetchFun({
...props.params,
...formData,
page_size: props.pageSize,
export: 2
})
popupRef.value?.close()
feedback.closeLoading()
} catch (error) {
feedback.closeLoading()
}
}
getData()
</script>

View File

@@ -1,8 +1,10 @@
<script lang="ts">
import { createVNode } from 'vue'
import { ElIcon } from 'element-plus'
import { createVNode, defineComponent, h, resolveComponent } from 'vue'
import { EL_ICON_PREFIX, LOCAL_ICON_PREFIX } from './index'
import svgIcon from './svg-icon.vue'
export default defineComponent({
name: 'Icon',
props: {
@@ -20,28 +22,33 @@ export default defineComponent({
}
},
setup(props) {
if (props.name.indexOf(EL_ICON_PREFIX) === 0) {
// el-icon
return () =>
createVNode(
return () => {
if (props.name.indexOf(EL_ICON_PREFIX) === 0) {
// el-icon
return createVNode(
ElIcon,
{
size: props.size,
color: props.color
},
() => [createVNode(resolveComponent(props.name.replace(EL_ICON_PREFIX, '')))]
{
default: () =>
createVNode(resolveComponent(props.name.replace(EL_ICON_PREFIX, '')))
}
)
}
if (props.name.indexOf(LOCAL_ICON_PREFIX) === 0) {
// 本地icon
return () =>
h(
}
if (props.name.indexOf(LOCAL_ICON_PREFIX) === 0) {
// 本地icon
return h(
'i',
{
class: ['local-icon']
},
createVNode(svgIcon, { ...props })
)
}
// 如果name不符合预期的前缀返回null
return null
}
}
})

View File

@@ -77,10 +77,12 @@
</template>
<script lang="ts" setup>
import { computed, nextTick, onMounted, reactive, shallowRef, watch } from 'vue'
import { useEventListener } from '@vueuse/core'
import { ElInput } from 'element-plus'
import { computed, nextTick, onMounted, reactive, shallowRef, watch } from 'vue'
import { getElementPlusIconNames, getLocalIconNames } from './index'
interface Props {
modelValue: string
disabled?: boolean

View File

@@ -5,9 +5,10 @@
</template>
<script lang="ts">
import { addUnit } from '@/utils/util'
import type { CSSProperties } from 'vue'
import { addUnit } from '@/utils/util'
export default defineComponent({
props: {
name: {

View File

@@ -3,10 +3,12 @@
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import type { CSSProperties } from 'vue'
import { addUnit } from '@/utils/util'
import { imageProps } from 'element-plus'
import type { CSSProperties } from 'vue'
import { computed } from 'vue'
import { addUnit } from '@/utils/util'
const props = defineProps({
width: {
type: [String, Number],
@@ -20,11 +22,7 @@ const props = defineProps({
type: [String, Number],
default: 0
},
...imageProps,
hideOnClickModal: {
type: Boolean,
default: true
}
...imageProps
})
const styles = computed<CSSProperties>(() => {

View File

@@ -0,0 +1,146 @@
<template>
<div class="article-list">
<el-form ref="formRef" :model="queryParams" :inline="true">
<el-form-item label="文章名称">
<el-input
class="w-[280px]"
v-model="queryParams.name"
placeholder="请输入"
clearable
@keyup.enter="resetPage"
>
</el-input>
<el-button type="primary" class="ml-4" :icon="Search" @click="resetPage" />
</el-form-item>
</el-form>
<!-- 表格 -->
<el-table
size="large"
v-loading="pager.loading"
:data="pager.lists"
height="432px"
@row-click="handleSelectItem"
>
<el-table-column label="选择" min-width="50">
<template #default="{ row }">
<div class="flex row-center">
<el-checkbox
:model-value="getSelectItem(row.id)"
size="large"
@change="handleSelectItem(row)"
></el-checkbox>
</div>
</template>
</el-table-column>
<el-table-column label="文章名称" min-width="180">
<template #default="{ row }">
<div class="flex items-center">
<el-image
fit="cover"
:src="row.image"
class="flex-none w-[58px] h-[58px]"
/>
<div class="ml-4 overflow-hidden">
<el-tooltip effect="dark" :content="row.title" placement="top">
<div class="text-base line-clamp-2">
{{ row.title }}
</div>
</el-tooltip>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="创建时间" prop="create_time" min-width="140" />
</el-table>
<div class="flex justify-end mt-4">
<pagination v-model="pager" @change="getLists" />
</div>
</div>
</template>
<script lang="ts" setup>
import { Search } from '@element-plus/icons-vue'
import type { PropType } from 'vue'
import { articleLists } from '@/api/article'
import { usePaging } from '@/hooks/usePaging'
import { LinkTypeEnum } from '.'
//TODO TODO
const props = defineProps({
modelValue: {
type: Object as PropType<any>,
default: () => ({})
}
})
const emit = defineEmits<{
(event: 'update:modelValue', value: any): void
}>()
const selectData = ref<any>({
path: '/pages/news_detail/news_detail',
name: '',
query: {},
type: LinkTypeEnum.ARTICLE_LIST
})
const queryParams = reactive<any>({
name: '',
is_show: 1
})
const { pager, getLists, resetPage } = usePaging({
fetchFun: articleLists,
params: queryParams
})
const getSelectItem = (id: number) => {
return id == Number(selectData.value.id)
}
/**
* @description 选择
*/
const handleSelectItem = (event: any) => {
selectData.value = {
id: event.id,
name: event.title,
path: '/pages/news_detail/news_detail',
query: {
id: event.id
},
type: LinkTypeEnum.ARTICLE_LIST
}
emit('update:modelValue', selectData.value)
}
watch(
() => props.modelValue,
(value) => {
if (value.type != LinkTypeEnum.ARTICLE_LIST) {
return (selectData.value = {
id: '',
name: '',
path: '/pages/news_detail/news_detail',
type: LinkTypeEnum.SHOP_PAGES
})
}
selectData.value = value
},
{
immediate: true
}
)
getLists()
</script>
<style lang="scss" scoped>
:deep(.el-input-group__append) {
.el-button {
margin: 0 0;
}
}
</style>

View File

@@ -1,16 +1,18 @@
<template>
<div class="custom-link mt-[30px]">
<div class="flex flex-wrap items-center">
自定义链接
<div class="custom-link h-[530px]">
<div class="text-xl font-medium">自定义链接</div>
<div class="flex flex-wrap items-center mt-4">
<div class="w-[86px] text-right">自定义链接</div>
<div class="ml-4 flex-1 min-w-[100px]">
<el-input
class="max-w-[320px]"
:model-value="modelValue.query?.url"
placeholder="请输入链接地址"
@input="handleInput"
/>
</div>
</div>
<div class="form-tips">
<div class="form-tips ml-[101px] max-w-[320px]">
请填写完整的带有https://”或“http://”的链接地址,链接的域名必须在微信公众平台设置业务域名
</div>
</div>
@@ -18,7 +20,8 @@
<script lang="ts" setup>
import type { PropType } from 'vue'
import { LinkTypeEnum, type Link } from '.'
import { type Link, LinkTypeEnum } from '.'
defineProps({
modelValue: {

View File

@@ -1,6 +1,14 @@
export enum MenuTypeEnum {
'SHOP_PAGES' = 'shop',
'APPTOOL' = 'application_tool',
'OTHER_LINK' = 'other_link'
}
export enum LinkTypeEnum {
'SHOP_PAGES' = 'shop',
'CUSTOM_LINK' = 'custom'
'ARTICLE_LIST' = 'article',
'CUSTOM_LINK' = 'custom',
'MINI_PROGRAM' = 'mini_program'
}
export interface Link {

View File

@@ -2,25 +2,45 @@
<div class="link flex">
<el-menu
:default-active="activeMenu"
class="w-[160px] min-h-[350px] link-menu"
class="flex-none w-[180px] min-h-[350px] link-menu"
:default-openeds="[
MenuTypeEnum.SHOP_PAGES,
MenuTypeEnum.APPTOOL,
MenuTypeEnum.OTHER_LINK
]"
@select="handleSelect"
>
<el-menu-item v-for="(item, index) in menus" :index="item.type" :key="index">
<span>{{ item.name }}</span>
</el-menu-item>
<el-sub-menu v-for="(item, index) in menus" :index="item.type" :key="index">
<template #title>
<span>{{ item.name }}</span>
</template>
<el-menu-item
v-for="(sitem, sindex) in item.children"
:index="sitem.type"
:key="sindex"
style="min-width: 160px"
>
<span>{{ sitem.name }}</span>
</el-menu-item>
</el-sub-menu>
</el-menu>
<div class="flex-1 pl-4">
<div class="flex-1 ml-4 link-content">
<shop-pages v-model="activeLink" v-if="LinkTypeEnum.SHOP_PAGES == activeMenu" />
<article-list v-model="activeLink" v-if="LinkTypeEnum.ARTICLE_LIST == activeMenu" />
<custom-link v-model="activeLink" v-if="LinkTypeEnum.CUSTOM_LINK == activeMenu" />
<mini-program v-model="activeLink" v-if="LinkTypeEnum.MINI_PROGRAM == activeMenu" />
</div>
</div>
</template>
<script lang="ts" setup>
import type { PropType } from 'vue'
import { LinkTypeEnum, type Link } from '.'
import ShopPages from './shop-pages.vue'
import { type Link, LinkTypeEnum, MenuTypeEnum } from '.'
import ArticleList from './article-list.vue'
import CustomLink from './custom-link.vue'
import MiniProgram from './mini-program.vue'
import ShopPages from './shop-pages.vue'
const props = defineProps({
modelValue: {
@@ -35,25 +55,60 @@ const emit = defineEmits<{
const menus = ref([
{
name: '商城页面',
type: LinkTypeEnum.SHOP_PAGES,
link: {}
type: MenuTypeEnum.SHOP_PAGES,
children: [
{
name: '基础页面',
type: LinkTypeEnum.SHOP_PAGES,
link: {}
}
]
},
{
name: '自定义链接',
type: LinkTypeEnum.CUSTOM_LINK,
link: {}
name: '应用工具',
type: MenuTypeEnum.APPTOOL,
children: [
{
name: '文章资讯',
type: LinkTypeEnum.ARTICLE_LIST,
link: {}
}
]
},
{
name: '其他',
type: MenuTypeEnum.OTHER_LINK,
children: [
{
name: '自定义链接',
type: LinkTypeEnum.CUSTOM_LINK,
link: {}
},
{
name: '跳转小程序',
type: LinkTypeEnum.MINI_PROGRAM,
link: {}
}
]
}
])
const activeLink = computed({
get() {
return menus.value.find((item) => item.type == activeMenu.value)?.link as Link
let linkStoreage: any = {}
menus.value.forEach((item) => {
const res = item.children.find((citem) => citem.type == activeMenu.value)
if (res) linkStoreage = res
})
return linkStoreage.link
},
set(value) {
menus.value.forEach((item) => {
if (item.type == activeMenu.value) {
item.link = value
}
item.children.forEach((citem) => {
if (citem.type == activeMenu.value) {
citem.link = value
}
})
})
}
})
@@ -64,10 +119,14 @@ const handleSelect = (index: string) => {
activeMenu.value = index
}
watch(activeLink, (value) => {
if (!value.type) return
emit('update:modelValue', value)
})
watch(
activeLink,
(value) => {
if (!value.type) return
emit('update:modelValue', value)
},
{ deep: true }
)
watch(
() => props.modelValue,
@@ -82,15 +141,28 @@ watch(
</script>
<style lang="scss" scoped>
.link-menu {
--el-menu-item-height: 40px;
:deep(.el-menu-item) {
border-color: transparent;
&.is-active {
border-right-width: 2px;
border-color: var(--el-color-primary);
background-color: var(--el-color-primary-light-9);
.link {
.link-menu {
--el-menu-item-height: 40px;
border-radius: 8px;
border: 1px solid var(--el-border-color);
:deep(.el-menu-item) {
border-color: transparent;
&.is-active {
border-right-width: 2px;
border-color: var(--el-color-primary);
background-color: var(--el-color-primary-light-9);
}
}
}
.link-content {
padding: 20px;
box-sizing: border-box;
border-radius: 8px;
border: 1px solid var(--el-border-color);
}
}
</style>

View File

@@ -0,0 +1,116 @@
<template>
<div class="mini-program h-[530px]">
<div class="text-xl font-medium">跳转小程序</div>
<div class="flex flex-wrap items-center mt-4">
<div class="w-[86px] text-right">小程序APPID</div>
<div class="ml-4 flex-1 min-w-[100px]">
<el-input
class="max-w-[320px]"
:model-value="modelValue.query?.appId"
placeholder="请输入小程序appId"
@input="(value) => handleInput('appId', value)"
/>
</div>
</div>
<div class="flex flex-wrap items-center mt-4">
<div class="w-[86px] text-right">小程序路径</div>
<div class="ml-4 flex-1 min-w-[100px]">
<el-input
class="max-w-[320px]"
:model-value="modelValue.query?.path"
placeholder="请输入小程序路径链接地址"
@input="(value) => handleInput('path', value)"
/>
</div>
</div>
<div class="flex flex-wrap items-center mt-4">
<div class="w-[86px] text-right">传递参数</div>
<div class="ml-4 flex-1 min-w-[100px]">
<el-input
class="max-w-[320px]"
:model-value="modelValue.query?.query"
placeholder="请输入小程序跳转参数(选填)"
@input="(value) => handleInput('query', value)"
/>
</div>
</div>
<div class="form-tips ml-[100px] max-w-[320px]">
<div>示例id=2&ustm=jiny&name=234</div>
<div class="text-error">
注意不允许输入中文特殊字符等如果出现对不起当前页面无法访问大概率是跳转参数的问题
</div>
</div>
<div class="flex flex-wrap items-center mt-4">
<div class="w-[86px] text-right">小程序版本</div>
<div class="ml-4 flex-1 min-w-[100px]">
<el-radio-group
:model-value="modelValue.query?.env_version"
@change="(value) => handleInput('env_version', value)"
>
<el-radio label="release">正式版</el-radio>
<el-radio label="trial">体验版</el-radio>
<el-radio label="develop">开发版</el-radio>
</el-radio-group>
</div>
</div>
<div>
<div class="form-tips ml-[100px] max-w-[320px]">
<div class="mt-4">
1.
小程序APPID和小程序路径链接地址小程序路径链接地址请填写小程序的页面路径pages/index/index
</div>
<div class="mt-2">
<span>2. 如果是H5(浏览器)中需要跳转到小程序则需要以下配置---></span>
<a
href="https://mp.weixin.qq.com/"
class="text-primary"
target="_blank"
rel="nofollow"
>
小程序管理后台 -&gt; 设置 -&gt; 隐私与安全 -&gt; 明文 scheme 拉起此小程序
点击跳转去配置
</a>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import type { PropType } from 'vue'
import { type Link, LinkTypeEnum } from '.'
const props = defineProps({
modelValue: {
type: Object as PropType<Link>,
default: () => ({})
}
})
const emit = defineEmits<{
(event: 'update:modelValue', value: Link): void
}>()
const handleInput = (key: 'appId' | 'path' | 'env_version' | 'query', value: string) => {
emit('update:modelValue', {
...props.modelValue,
name: '小程序跳转',
query: {
...props.modelValue.query,
[key]: value
},
type: LinkTypeEnum.MINI_PROGRAM
})
}
watch(
() => props.modelValue,
(value) => {
if (!value.query?.env_version) {
handleInput('env_version', 'release')
}
},
{ immediate: true }
)
</script>

View File

@@ -10,16 +10,18 @@
/>
</template>
</el-input>
<popup ref="popupRef" width="700px" title="链接选择" @confirm="handleConfirm">
<popup ref="popupRef" width="1050px" title="链接选择" @confirm="handleConfirm">
<link-content v-model="activeLink" />
</popup>
</div>
</template>
<script lang="ts" setup>
import { LinkTypeEnum, type Link } from '.'
import LinkContent from './index.vue'
import Popup from '@/components/popup/index.vue'
import { type Link, LinkTypeEnum } from '.'
import LinkContent from './index.vue'
const props = defineProps({
modelValue: {
type: Object
@@ -43,6 +45,8 @@ const getLink = computed(() => {
switch (props.modelValue?.type) {
case LinkTypeEnum.SHOP_PAGES:
return props.modelValue.name
case LinkTypeEnum.ARTICLE_LIST:
return props.modelValue.name
case LinkTypeEnum.CUSTOM_LINK:
return props.modelValue.query?.url
default:

View File

@@ -1,5 +1,5 @@
<template>
<div class="shop-pages">
<div class="shop-pages h-[530px]">
<div class="link-list flex flex-wrap">
<div
class="link-item border border-br px-5 py-[5px] rounded-[3px] cursor-pointer mr-[10px] mb-[10px]"
@@ -19,7 +19,8 @@
<script lang="ts" setup>
import type { PropType } from 'vue'
import { LinkTypeEnum, type Link } from '.'
import { type Link, LinkTypeEnum } from '.'
defineProps({
modelValue: {
@@ -35,17 +36,20 @@ const linkList = ref([
{
path: '/pages/index/index',
name: '商城首页',
type: LinkTypeEnum.SHOP_PAGES
type: LinkTypeEnum.SHOP_PAGES,
canTab: true
},
{
path: '/pages/news/news',
name: '文章资讯',
type: LinkTypeEnum.SHOP_PAGES
type: LinkTypeEnum.SHOP_PAGES,
canTab: true
},
{
path: '/pages/user/user',
name: '个人中心',
type: LinkTypeEnum.SHOP_PAGES
type: LinkTypeEnum.SHOP_PAGES,
canTab: true
},
{
path: '/pages/collection/collection',

View File

@@ -1,8 +1,16 @@
<template>
<div>
<div class="file-item relative" :style="{ height: fileSize, width: fileSize }">
<div
class="file-item relative"
:style="{ height: height || fileSize, width: width || fileSize }"
>
<el-image class="image" v-if="type == 'image'" fit="contain" :src="uri"></el-image>
<video class="video" v-else-if="type == 'video'" :src="uri"></video>
<el-image
class="image"
v-else
src="https://img95.699pic.com/element/40103/3946.png_860.png"
></el-image>
<div
v-if="type == 'video'"
class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] rounded-full w-5 h-5 flex justify-center items-center bg-[rgba(0,0,0,0.3)]"
@@ -16,6 +24,7 @@
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
props: {
// 图片地址
@@ -27,6 +36,16 @@ export default defineComponent({
type: String,
default: '100px'
},
// 选择器尺寸-宽度不传则是使用size
width: {
type: String,
default: ''
},
// 选择器尺寸-高度不传则是使用size
height: {
type: String,
default: ''
},
// 文件类型
type: {
type: String,

View File

@@ -1,3 +1,6 @@
import { type CheckboxValueType, ElMessage, ElTree } from 'element-plus'
import { type Ref, shallowRef } from 'vue'
import {
fileCateAdd,
fileCateDelete,
@@ -10,8 +13,6 @@ import {
} from '@/api/file'
import { usePaging } from '@/hooks/usePaging'
import feedback from '@/utils/feedback'
import { ElMessage, ElTree, type CheckboxValueType } from 'element-plus'
import { shallowRef, type Ref } from 'vue'
// 左侧分组的钩子函数
export function useCate(type: number) {
@@ -25,6 +26,7 @@ export function useCate(type: number) {
// 获取分组列表
const getCateLists = async () => {
const data = await fileCateLists({
page_type: 0,
type
})
const item: any[] = [
@@ -37,7 +39,7 @@ export function useCate(type: number) {
id: 0
}
]
cateLists.value = data
cateLists.value = data.lists
cateLists.value.unshift(...item)
setTimeout(() => {
treeRef.value?.setCurrentKey(cateId.value)
@@ -54,6 +56,15 @@ export function useCate(type: number) {
getCateLists()
}
const handleAddChildCate = async (value: string, pid: number) => {
await fileCateAdd({
type,
name: value,
pid: pid
})
getCateLists()
}
// 编辑分组
const handleEditCate = async (value: string, id: number) => {
await fileCateEdit({
@@ -64,8 +75,12 @@ export function useCate(type: number) {
}
// 删除分组
const handleDeleteCate = async (id: number) => {
await feedback.confirm('确定要删除?')
const handleDeleteCate = async (id: number, children?: number) => {
if (children) {
await feedback.confirm('删除文件夹将会永久删除文件夹及其所有内容。您确定要继续吗?')
} else {
await feedback.confirm('确定要删除?')
}
await fileCateDelete({ id })
cateId.value = ''
getCateLists()
@@ -81,6 +96,7 @@ export function useCate(type: number) {
cateId,
cateLists,
handleAddCate,
handleAddChildCate,
handleEditCate,
handleDeleteCate,
getCateLists,
@@ -104,7 +120,8 @@ export function useFile(
const fileParams = reactive({
name: '',
type: type,
cid: cateId
cid: cateId,
source: ''
})
const { pager, getLists, resetPage } = usePaging({
fetchFun: fileList,
@@ -178,10 +195,10 @@ export function useFile(
clearSelect()
}
const handleFileRename = async (value: string, id: number) => {
const handleFileRename = async (name: string, id: number) => {
await fileRename({
id,
name: value
name
})
getFileList()
}

View File

@@ -23,16 +23,11 @@
<span class="flex-1 truncate mr-2">
<overflow-tooltip :content="data.name" />
</span>
<el-dropdown
v-perms="['albums:cateRename', 'albums:cateDel']"
v-if="data.id > 0"
:hide-on-click="false"
>
<el-dropdown v-if="data.id > 0" :hide-on-click="false">
<span class="muted m-r-10">···</span>
<template #dropdown>
<el-dropdown-menu>
<popover-input
v-perms="['albums:cateRename']"
@confirm="handleEditCate($event, data.id)"
size="default"
:value="data.name"
@@ -47,9 +42,27 @@
</el-dropdown-item>
</div>
</popover-input>
<popover-input
@confirm="handleAddChildCate($event, data.id)"
size="default"
width="400px"
:limit="20"
show-limit
teleported
>
<div>
<el-dropdown-item>
添加分组
</el-dropdown-item>
</div>
</popover-input>
<div
v-perms="['albums:cateDel']"
@click="handleDeleteCate(data.id)"
@click="
handleDeleteCate(
data.id,
data?.children?.length
)
"
>
<el-dropdown-item>删除分组</el-dropdown-item>
</div>
@@ -65,7 +78,6 @@
<div class="flex justify-center p-2 border-t border-br">
<popover-input
v-perms="['albums:cateAdd']"
@confirm="handleAddCate"
size="default"
width="400px"
@@ -82,7 +94,6 @@
<div class="flex-1 flex">
<upload
v-if="type == 'image'"
v-perms="['upload:image']"
class="mr-3"
:data="{ cid: cateId }"
:type="type"
@@ -93,17 +104,25 @@
</upload>
<upload
v-if="type == 'video'"
v-perms="['upload:video']"
class="mr-3"
:data="{ cid: cateId }"
:type="type"
:show-progress="true"
@change="refresh"
@allSuccess="refresh"
>
<el-button type="primary">本地上传</el-button>
</upload>
<upload
v-if="type == 'file'"
class="mr-3"
:data="{ cid: cateId }"
:type="type"
:show-progress="true"
@allSuccess="refresh"
>
<el-button type="primary">本地上传</el-button>
</upload>
<el-button
v-perms="['albums:albumDel']"
v-if="mode == 'page'"
:disabled="!select.length"
@click.stop="batchFileDelete()"
@@ -112,7 +131,6 @@
</el-button>
<popup
v-perms="['albums:albumMove']"
v-if="mode == 'page'"
class="ml-3"
@confirm="batchFileMove"
@@ -137,6 +155,20 @@
</div>
</popup>
</div>
<el-select
v-model="fileParams.source"
placeholder="请选择文件来源"
clearable
style="margin-right: 20px"
class="w-50"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-input
class="w-60"
placeholder="请输入名称"
@@ -151,6 +183,7 @@
</el-button>
</template>
</el-input>
<div class="flex items-center ml-2">
<el-tooltip content="列表视图" placement="top">
<div
@@ -197,7 +230,7 @@
>
<del-wrap @close="batchFileDelete([item.id])">
<file-item
:uri="item.uri"
:uri="item.url"
:file-size="fileSize"
:type="type"
@click="selectFile(item)"
@@ -211,7 +244,6 @@
<overflow-tooltip class="mt-1" :content="item.name" />
<div class="operation-btns flex items-center">
<popover-input
v-perms="['albums:albumRename']"
@confirm="handleFileRename($event, item.id)"
size="default"
:value="item.name"
@@ -222,9 +254,32 @@
>
<el-button type="primary" link> 重命名 </el-button>
</popover-input>
<el-button type="primary" link @click="handlePreview(item.uri)">
<el-button
v-if="item.type === 10 || item.type === 20"
type="primary"
link
@click="handlePreview(item.url)"
>
查看
</el-button>
<el-button
v-if="item.type === 10 || item.type === 20"
type="primary"
link
@click="textCopy(item.url)"
style="margin-left: 1px"
>地址</el-button
>
<el-link
v-else
type="primary"
:underline="false"
style="margin-left: 25px"
:href="item.url"
>下载</el-link
>
</div>
</li>
</ul>
@@ -247,20 +302,20 @@
</el-table-column>
<el-table-column label="图片" width="100">
<template #default="{ row }">
<file-item :uri="row.uri" file-size="50px" :type="type"></file-item>
<file-item :uri="row.url" file-size="50px" :type="type"></file-item>
</template>
</el-table-column>
<el-table-column label="名称" min-width="100" show-overflow-tooltip>
<template #default="{ row }">
<el-link @click.stop="handlePreview(row.uri)" :underline="false">
<el-link @click.stop="handlePreview(row.url)" :underline="false">
{{ row.name }}
</el-link>
</template>
</el-table-column>
<el-table-column prop="createTime" label="上传时间" min-width="100" />
<el-table-column prop="create_time" label="上传时间" min-width="100" />
<el-table-column label="操作" width="150" fixed="right">
<template #default="{ row }">
<div class="inline-block" v-perms="['albums:albumRename']">
<div class="inline-block">
<popover-input
@confirm="handleFileRename($event, row.id)"
size="default"
@@ -274,11 +329,11 @@
</popover-input>
</div>
<div class="inline-block">
<el-button type="primary" link @click.stop="handlePreview(row.uri)">
<el-button type="primary" link @click.stop="handlePreview(row.url)">
查看
</el-button>
</div>
<div class="inline-block" v-perms="['albums:albumDel']">
<div class="inline-block">
<el-button
type="primary"
link
@@ -311,15 +366,10 @@
当页全选
</el-checkbox>
</span>
<el-button
v-perms="['albums:albumDel']"
:disabled="!select.length"
@click="batchFileDelete()"
>
<el-button :disabled="!select.length" @click="batchFileDelete()">
删除
</el-button>
<popup
v-perms="['albums:albumMove']"
class="ml-3 inline"
@confirm="batchFileMove"
:disabled="!select.length"
@@ -366,7 +416,7 @@
<div class="select-item">
<del-wrap @close="cancelSelete(item.id)">
<file-item
:uri="item.uri"
:uri="item.url"
file-size="100px"
:type="type"
></file-item>
@@ -378,14 +428,18 @@
</div>
</div>
<preview v-model="showPreview" :url="previewUrl" :type="type" />
<input ref="textCopys" id="textCopys" value="" style="opacity: 0; position: absolute" />
</div>
</template>
<script lang="ts" setup>
import { useCate, useFile } from './hook'
import FileItem from './file.vue'
import Preview from './preview.vue'
import { ElMessage } from 'element-plus'
import type { Ref } from 'vue'
import FileItem from './file.vue'
import { useCate, useFile } from './hook'
import Preview from './preview.vue'
const props = defineProps({
fileSize: {
type: String,
@@ -422,7 +476,18 @@ const typeValue = computed<number>(() => {
return 0
}
})
const visible: Ref<boolean> = inject('visible')!
const options = [
{
value: '0',
label: '后台上传'
},
{
value: '1',
label: '前端上传'
}
]
const visible: Ref<boolean> = inject('visible', ref<boolean>(false))!
const previewUrl = ref('')
const showPreview = ref(false)
const {
@@ -430,6 +495,7 @@ const {
cateId,
cateLists,
handleAddCate,
handleAddChildCate,
handleEditCate,
handleDeleteCate,
getCateLists,
@@ -468,7 +534,7 @@ const handlePreview = (url: string) => {
showPreview.value = true
}
watch(
visible,
() => visible.value,
async (val: boolean) => {
if (val) {
getData()
@@ -511,6 +577,19 @@ onMounted(() => {
defineExpose({
clearSelect
})
const textCopys = ref()
const textCopy = (uri: string) => {
const text = uri // 复制文本内容
const input = textCopys.value
input.value = text // 修改input的内容
input.select() // 选中文本
document.execCommand('copy') // 浏览器复制
ElMessage({
message: '地址复制成功',
type: 'success'
})
}
</script>
<style scoped lang="scss">
@@ -520,6 +599,11 @@ defineExpose({
@apply border-r border-br flex flex-col w-[200px];
:deep(.el-tree-node__content) {
height: 36px;
.el-tree-node__label {
display: flex;
flex: 1;
min-width: 0;
}
}
}
&__center {

View File

@@ -2,7 +2,7 @@
<div class="material-select">
<popup
ref="popupRef"
width="830px"
width="1050px"
custom-class="body-padding"
:title="`选择${tipsText}`"
@confirm="handleConfirm"
@@ -24,6 +24,8 @@
<file-item
:uri="excludeDomain ? getImageUrl(element) : element"
:file-size="size"
:width="width"
:height="height"
:type="type"
></file-item>
</del-wrap>
@@ -49,8 +51,8 @@
<div
class="upload-btn"
:style="{
width: size,
height: size
width: width || size,
height: height || size
}"
>
<icon :size="25" name="el-icon-Plus" />
@@ -77,13 +79,15 @@
</template>
<script lang="ts">
import { useThrottleFn } from '@vueuse/core'
import Draggable from 'vuedraggable'
import Popup from '@/components/popup/index.vue'
import useAppStore from '@/stores/modules/app'
import FileItem from './file.vue'
import Material from './index.vue'
import Preview from './preview.vue'
import useAppStore from '@/stores/modules/app'
import { useThrottleFn } from '@vueuse/shared'
export default defineComponent({
components: {
Popup,
@@ -107,6 +111,16 @@ export default defineComponent({
type: String,
default: '100px'
},
// 选择器尺寸-宽度不传则是使用size
width: {
type: String,
default: ''
},
// 选择器尺寸-高度不传则是使用size
height: {
type: String,
default: ''
},
// 文件尺寸
fileSize: {
type: String,
@@ -174,7 +188,7 @@ export default defineComponent({
const handleConfirm = useThrottleFn(
() => {
const selectUri = select.value.map((item) =>
props.excludeDomain ? item.path : item.uri
props.excludeDomain ? item.uri : item.url
)
if (!isAdd.value) {
fileList.value.splice(currentIndex.value, 1, selectUri.shift())
@@ -297,7 +311,7 @@ export default defineComponent({
}
.material-wrap {
min-width: 720px;
height: 430px;
height: 560px;
@apply border-t border-b border-br;
}
</style>

View File

@@ -14,7 +14,7 @@
<script lang="ts" setup>
import { useEventListener } from '@vueuse/core'
import { useTooltipContentProps, type Placement } from 'element-plus'
import { type Placement, useTooltipContentProps } from 'element-plus'
import type { PropType } from 'vue'
const props = defineProps({

View File

@@ -6,7 +6,7 @@
</div>
<el-dialog
v-model="visible"
:custom-class="customClass"
:class="customClass"
:center="center"
:append-to-body="true"
:width="width"

View File

@@ -1,6 +1,7 @@
<template>
<div class="upload">
<el-upload
v-model:file-list="fileList"
ref="uploadRefs"
:action="action"
:multiple="multiple"
@@ -14,7 +15,7 @@
:on-error="handleError"
:accept="getAccept"
>
<slot></slot>
<slot />
</el-upload>
<el-dialog
v-if="showProgress && fileList.length"
@@ -30,7 +31,7 @@
<div class="mb-5">
<div>{{ item.name }}</div>
<div class="flex-1">
<el-progress :percentage="parseInt(item.percentage)"></el-progress>
<el-progress :percentage="parseInt(item.percentage)" />
</div>
</div>
</template>
@@ -40,12 +41,14 @@
</template>
<script lang="ts">
import { computed, defineComponent, ref, shallowRef } from 'vue'
import useUserStore from '@/stores/modules/user'
import config from '@/config'
import feedback from '@/utils/feedback'
import type { ElUpload } from 'element-plus'
import { computed, defineComponent, ref, shallowRef } from 'vue'
import config from '@/config'
import { RequestCodeEnum } from '@/enums/requestEnums'
import useUserStore from '@/stores/modules/user'
import feedback from '@/utils/feedback'
export default defineComponent({
components: {},
props: {
@@ -75,55 +78,64 @@ export default defineComponent({
default: false
}
},
emits: ['change', 'error'],
emits: ['change', 'error', 'success', 'allSuccess'],
setup(props, { emit }) {
const userStore = useUserStore()
const uploadRefs = shallowRef<InstanceType<typeof ElUpload>>()
const action = ref(`${config.baseUrl}${config.urlPrefix}/upload/${props.type}`)
const headers = computed(() => ({
['like-admin']: userStore.token,
token: userStore.token,
version: config.version
}))
const visible = ref(false)
const fileList = ref<any[]>([])
const handleProgress = (event: any, file: any, fileLists: any[]) => {
const handleProgress = () => {
visible.value = true
fileList.value = toRaw(fileLists)
}
const handleSuccess = (response: any, file: any, fileLists: any[]) => {
const allSuccess = fileLists.every((item) => item.status == 'success')
if (allSuccess) {
uploadRefs.value?.clearFiles()
visible.value = false
emit('change')
let uploadLen = 0
const handleSuccess = (response: any, file: any) => {
uploadLen++
if (uploadLen == fileList.value.length) {
uploadLen = 0
fileList.value = []
emit('allSuccess')
}
if (response.code == RequestCodeEnum.FAILED && response.msg) {
emit('change', file)
if (response.code == RequestCodeEnum.SUCCESS) {
emit('success', response)
}
if (response.code == RequestCodeEnum.FAIL && response.msg) {
feedback.msgError(response.msg)
}
}
const handleError = (event: any, file: any) => {
uploadLen++
if (uploadLen == fileList.value.length) {
uploadLen = 0
fileList.value = []
emit('allSuccess')
}
feedback.msgError(`${file.name}文件上传失败`)
uploadRefs.value?.abort(file)
visible.value = false
emit('change')
emit('error')
emit('change', file)
emit('error', file)
}
const handleExceed = () => {
feedback.msgError(`超出上传上限${props.limit},请重新上传`)
}
const handleClose = () => {
uploadRefs.value?.clearFiles()
fileList.value = []
visible.value = false
}
const getAccept = computed(() => {
switch (props.type) {
case 'image':
return '.jpj,.png,.gif,.jpeg,.ico,.bmp'
return '.jpg,.png,.gif,.jpeg,.ico'
case 'video':
return '.wmv,.avi,.mov,.mp4,.flv,.rmvb'
return '.wmv,.avi,.mpg,.mpeg,.3gp,.mov,.mp4,.flv,.rmvb,.mkv'
default:
return '*'
}

View File

@@ -13,9 +13,11 @@
</template>
<script setup lang="ts">
import { reactive, shallowRef } from 'vue'
import 'vue3-video-play/dist/style.css'
import { reactive, shallowRef } from 'vue'
import VideoPlay from 'vue3-video-play'
const props = defineProps({
src: {
type: String,

View File

@@ -1,9 +1,9 @@
const config = {
terminal: 1, //终端
title: '后台管理系统', //网站默认标题
version: '1.4.0', //版本号
version: '1.9.1', //版本号
baseUrl: `${import.meta.env.VITE_APP_BASE_URL || ''}/`, //请求接口域名
urlPrefix: 'api', //请求默认前缀
urlPrefix: 'adminapi', //请求默认前缀
timeout: 10 * 1000 //请求超时时长
}

View File

@@ -13,6 +13,4 @@ const defaultSetting = {
errorTheme: '#f56c6c', //错误主题色
infoTheme: '#909399' //信息主题色
}
//以上各种主题色分别对应element-plus的几种行为主题
export default defaultSetting

View File

@@ -3,7 +3,5 @@ export enum PageEnum {
LOGIN = '/login',
//无权限页面
ERROR_403 = '/403',
// 404
ERROR_404 = '/:pathMatch(.*)*',
INDEX = '/'
}

View File

@@ -11,19 +11,8 @@ export enum RequestMethodsEnum {
}
export enum RequestCodeEnum {
SUCCESS = 200, //成功
FAILED = 300, // 失败
PARAMS_VALID_ERROR = 310, //参数校验错误
PARAMS_TYPE_ERROR = 311, //参数类型错误
REQUEST_METHOD_ERROR = 312, //请求方法错误
ASSERT_ARGUMENT_ERROR = 313, //断言参数错误
ASSERT_MYBATIS_ERROR = 314, //断言mybatis错误
LOGIN_ACCOUNT_ERROR = 330, //登陆账号或密码错误
LOGIN_DISABLE_ERROR = 331, //登陆账号已被禁用
TOKEN_EMPTY = 332, // TOKEN参数为空
TOKEN_INVALID = 333, // TOKEN参数无效
VERIFICATION_CODE_ERROR = 334, // 验证码错误
NO_PERMISSTION = 403, //无相关权限
REQUEST_404_ERROR = 404, //请求接口不存在
SYSTEM_ERROR = 500 //系统错误
SUCCESS = 1,
FAIL = 0,
LOGIN_FAILURE = -1,
OPEN_NEW_PAGE = 2
}

View File

@@ -1,6 +1,7 @@
import { dictDataAll } from '@/api/setting/dict'
import { reactive, toRaw } from 'vue'
import { getDictData } from '@/api/app'
interface Options {
[propName: string]: {
api: PromiseFun
@@ -46,24 +47,22 @@ export function useDictOptions<T = any>(options: Options) {
}
}
// useDictOptions<{
// useDictData<{
// dict: any[]
// }>({
// dict: dictData
// })
// }>(['dict'])
export function useDictData<T = any>(dict: string[]) {
const options: Options = {}
for (const type of dict) {
options[type] = {
api: dictDataAll,
params: {
dictType: type
}
}
export function useDictData<T = any>(dict: string) {
const dictData: any = reactive({})
const refresh = async () => {
const data = await getDictData({
type: dict
})
Object.assign(dictData, data)
}
const { optionsData } = useDictOptions<T>(options)
refresh()
return {
dictData: optionsData
dictData: dictData as T,
refresh
}
}

View File

@@ -1,4 +1,3 @@
import { isFunction } from 'lodash'
import { reactive, toRaw } from 'vue'
// 分页钩子函数
@@ -7,9 +6,8 @@ interface Options {
size?: number
fetchFun: (_arg: any) => Promise<any>
params?: Record<any, any>
fixedParams?: Record<any, any>
firstLoading?: boolean
beforeRequest?(params: Record<any, any>): Record<any, any>
afterRequest?(res: Record<any, any>): void
}
export function usePaging(options: Options) {
@@ -18,9 +16,8 @@ export function usePaging(options: Options) {
size = 15,
fetchFun,
params = {},
firstLoading = false,
beforeRequest,
afterRequest
fixedParams = {},
firstLoading = false
} = options
// 记录分页初始参数
const paramsInit: Record<any, any> = Object.assign({}, toRaw(params))
@@ -31,27 +28,21 @@ export function usePaging(options: Options) {
loading: firstLoading,
count: 0,
lists: [] as any[],
extend: {} as Record<any, any>
extend: {} as Record<string, any>
})
// 请求分页接口
const getLists = () => {
pager.loading = true
let requestParams = params
if (isFunction(beforeRequest)) {
requestParams = beforeRequest(params)
}
return fetchFun({
pageNo: pager.page,
pageSize: pager.size,
...requestParams
page_no: pager.page,
page_size: pager.size,
...params,
...fixedParams
})
.then((res: any) => {
pager.count = res?.count
pager.lists = res?.lists
pager.extend = res?.extend
if (isFunction(afterRequest)) {
afterRequest(res)
}
return Promise.resolve(res)
})
.catch((err: any) => {

View File

@@ -4,8 +4,10 @@
* <el-button v-perms="['auth.menu/edit']">编辑</el-button>
*/
import feedback from '@/utils/feedback'
import useClipboard from 'vue-clipboard3'
import feedback from '@/utils/feedback'
const clipboard = 'data-clipboard-text'
export default {
mounted: (el: HTMLElement, binding: any) => {

View File

@@ -5,6 +5,7 @@
*/
import useUserStore from '@/stores/modules/user'
export default {
mounted: (el: HTMLElement, binding: any) => {
const { value } = binding

View File

@@ -1,4 +1,5 @@
import type { App } from 'vue'
const modules = import.meta.glob('./**/*', { eager: true })
// 安装方法,执行某一类相同操作

View File

@@ -1,39 +1,37 @@
//引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口。
import * as echarts from 'echarts/core'
//引入柱状图图表,图表后缀都为 Chart
import {
BarChart,
LineChart,
PieChart,
MapChart,
PictorialBarChart,
PieChart,
RadarChart,
ScatterChart,
GaugeChart
ScatterChart
} from 'echarts/charts'
// 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component
import {
TitleComponent,
TooltipComponent,
GridComponent,
PolarComponent,
AriaComponent,
ParallelComponent,
LegendComponent,
RadarComponent,
ToolboxComponent,
DataZoomComponent,
VisualMapComponent,
TimelineComponent,
CalendarComponent,
GraphicComponent
DataZoomComponent,
GraphicComponent,
GridComponent,
LegendComponent,
ParallelComponent,
PolarComponent,
RadarComponent,
TimelineComponent,
TitleComponent,
ToolboxComponent,
TooltipComponent,
VisualMapComponent
} from 'echarts/components'
//引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
import { CanvasRenderer } from 'echarts/renderers'
import * as echarts from 'echarts/core'
//标签自动布局,全局过渡动画等特性
import { LabelLayout, UniversalTransition } from 'echarts/features'
//引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
import { CanvasRenderer } from 'echarts/renderers'
// 注册必须的组件
echarts.use([
@@ -60,6 +58,5 @@ echarts.use([
ScatterChart,
CanvasRenderer,
LabelLayout,
UniversalTransition,
GaugeChart
UniversalTransition
])

View File

@@ -1,8 +1,9 @@
import * as ElementPlusIcons from '@element-plus/icons-vue'
import type { App } from 'vue'
//https://github.com/element-plus/element-plus/issues/7293
import 'element-plus/es/components/dialog/style/css'
import * as ElementPlusIcons from '@element-plus/icons-vue'
import type { App } from 'vue'
export default (app: App<Element>) => {
// 全局注册ElementPlus图标
for (const [key, component] of Object.entries(ElementPlusIcons)) {

Some files were not shown because too many files have changed in this diff Show More