feat 同步前端代码
feat 同步PC代码 feat 增加1.9DB feat 同步逻辑
@@ -1,4 +1,4 @@
|
||||
NODE_ENV = 'development'
|
||||
|
||||
# 请求域名
|
||||
# Base API
|
||||
VITE_APP_BASE_URL=''
|
||||
@@ -1,4 +1,3 @@
|
||||
NODE_ENV = 'production'
|
||||
|
||||
# 请求域名
|
||||
# Base API
|
||||
VITE_APP_BASE_URL=''
|
||||
4
admin/.eslintignore
Normal file
@@ -0,0 +1,4 @@
|
||||
.vscode
|
||||
.idea
|
||||
dist/
|
||||
node_modules/
|
||||
@@ -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
@@ -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
@@ -0,0 +1,4 @@
|
||||
.vscode
|
||||
.idea
|
||||
dist/
|
||||
node_modules/
|
||||
11
admin/.prettierrc
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"printWidth": 100,
|
||||
"proseWrap": "preserve",
|
||||
"bracketSameLine": false,
|
||||
"endOfLine": "lf",
|
||||
"tabWidth": 4,
|
||||
"useTabs": false,
|
||||
"trailingComma": "none"
|
||||
}
|
||||
3
admin/.vscode/extensions.json
vendored
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
|
||||
}
|
||||
11
admin/.vscode/settings.json
vendored
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
125
admin/index.html
@@ -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
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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' })
|
||||
}
|
||||
|
||||
11
admin/src/api/channel/open_setting.ts
Normal 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' })
|
||||
}
|
||||
@@ -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' })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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' })
|
||||
}
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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' })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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' })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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' })
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
1
admin/src/assets/icons/collapse.svg
Normal 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 |
1
admin/src/assets/icons/expand.svg
Normal 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 |
|
Before Width: | Height: | Size: 498 B After Width: | Height: | Size: 498 B |
|
Before Width: | Height: | Size: 488 B After Width: | Height: | Size: 488 B |
BIN
admin/src/assets/images/blue1.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
admin/src/assets/images/blue2.png
Normal file
|
After Width: | Height: | Size: 788 KiB |
BIN
admin/src/assets/images/blue3.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
admin/src/assets/images/green1.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
admin/src/assets/images/green2.png
Normal file
|
After Width: | Height: | Size: 739 KiB |
BIN
admin/src/assets/images/green3.png
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
admin/src/assets/images/pink1.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
admin/src/assets/images/pink2.png
Normal file
|
After Width: | Height: | Size: 788 KiB |
BIN
admin/src/assets/images/pink3.png
Normal file
|
After Width: | Height: | Size: 106 KiB |
BIN
admin/src/assets/images/purple1.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
admin/src/assets/images/purple2.png
Normal file
|
After Width: | Height: | Size: 735 KiB |
BIN
admin/src/assets/images/purple3.png
Normal file
|
After Width: | Height: | Size: 108 KiB |
BIN
admin/src/assets/images/red1.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
admin/src/assets/images/red2.png
Normal file
|
After Width: | Height: | Size: 733 KiB |
BIN
admin/src/assets/images/red3.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
admin/src/assets/images/yellow1.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
admin/src/assets/images/yellow2.png
Normal file
|
After Width: | Height: | Size: 745 KiB |
BIN
admin/src/assets/images/yellow3.png
Normal file
|
After Width: | Height: | Size: 107 KiB |
@@ -9,6 +9,7 @@
|
||||
* @description 兼容第三方页面的跳转
|
||||
*/
|
||||
import { isExternal } from '@/utils/validate'
|
||||
|
||||
interface Props {
|
||||
to: string | Record<string, string>
|
||||
replace?: boolean
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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<{
|
||||
|
||||
151
admin/src/components/export-data/index.vue
Normal 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>
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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>(() => {
|
||||
|
||||
146
admin/src/components/link/article-list.vue
Normal 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>
|
||||
@@ -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: {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
116
admin/src/components/link/mini-program.vue
Normal 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"
|
||||
>
|
||||
小程序管理后台 -> 设置 -> 隐私与安全 -> 明文 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>
|
||||
@@ -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:
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</div>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
:custom-class="customClass"
|
||||
:class="customClass"
|
||||
:center="center"
|
||||
:append-to-body="true"
|
||||
:width="width"
|
||||
|
||||
@@ -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 '*'
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 //请求超时时长
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,4 @@ const defaultSetting = {
|
||||
errorTheme: '#f56c6c', //错误主题色
|
||||
infoTheme: '#909399' //信息主题色
|
||||
}
|
||||
//以上各种主题色分别对应element-plus的几种行为主题
|
||||
|
||||
export default defaultSetting
|
||||
|
||||
@@ -3,7 +3,5 @@ export enum PageEnum {
|
||||
LOGIN = '/login',
|
||||
//无权限页面
|
||||
ERROR_403 = '/403',
|
||||
// 404
|
||||
ERROR_404 = '/:pathMatch(.*)*',
|
||||
INDEX = '/'
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import useUserStore from '@/stores/modules/user'
|
||||
|
||||
export default {
|
||||
mounted: (el: HTMLElement, binding: any) => {
|
||||
const { value } = binding
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { App } from 'vue'
|
||||
|
||||
const modules = import.meta.glob('./**/*', { eager: true })
|
||||
|
||||
// 安装方法,执行某一类相同操作
|
||||
|
||||
@@ -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
|
||||
])
|
||||
|
||||
@@ -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)) {
|
||||
|
||||