mirror of
https://github.com/TangSengDaoDao/TangSengDaoDaoManager
synced 2025-06-03 23:58:10 +00:00
commit
42094a1e16
@ -13,6 +13,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.1.0",
|
"@element-plus/icons-vue": "^2.1.0",
|
||||||
|
"@fancyapps/ui": "^5.0.22",
|
||||||
"@icon-park/vue-next": "^1.4.2",
|
"@icon-park/vue-next": "^1.4.2",
|
||||||
"@lottiefiles/lottie-player": "^2.0.2",
|
"@lottiefiles/lottie-player": "^2.0.2",
|
||||||
"@vueuse/core": "^10.1.2",
|
"@vueuse/core": "^10.1.2",
|
||||||
|
26
pnpm-lock.yaml
generated
26
pnpm-lock.yaml
generated
@ -8,6 +8,9 @@ dependencies:
|
|||||||
'@element-plus/icons-vue':
|
'@element-plus/icons-vue':
|
||||||
specifier: ^2.1.0
|
specifier: ^2.1.0
|
||||||
version: 2.1.0(vue@3.3.4)
|
version: 2.1.0(vue@3.3.4)
|
||||||
|
'@fancyapps/ui':
|
||||||
|
specifier: ^5.0.22
|
||||||
|
version: 5.0.22
|
||||||
'@icon-park/vue-next':
|
'@icon-park/vue-next':
|
||||||
specifier: ^1.4.2
|
specifier: ^1.4.2
|
||||||
version: 1.4.2(vue@3.3.4)
|
version: 1.4.2(vue@3.3.4)
|
||||||
@ -1033,6 +1036,10 @@ packages:
|
|||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@fancyapps/ui@5.0.22:
|
||||||
|
resolution: {integrity: sha512-44A5/Hm59mn53FqZRyM4HO/R7UWE79UxgNyHmaudSe+HuU5Kl1g6lxR4Ol1QFaqNS97Pbdytlu4SxYsOX1BTxw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@floating-ui/core@1.3.1:
|
/@floating-ui/core@1.3.1:
|
||||||
resolution: {integrity: sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g==}
|
resolution: {integrity: sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g==}
|
||||||
dev: false
|
dev: false
|
||||||
@ -3988,7 +3995,7 @@ packages:
|
|||||||
lodash-es: 4.17.21
|
lodash-es: 4.17.21
|
||||||
vanilla-jsoneditor: 0.17.8
|
vanilla-jsoneditor: 0.17.8
|
||||||
vue: 3.3.4
|
vue: 3.3.4
|
||||||
vue-demi: 0.14.5(vue@3.3.4)
|
vue-demi: 0.14.6(vue@3.3.4)
|
||||||
vue-global-config: 0.4.0(vue@3.3.4)
|
vue-global-config: 0.4.0(vue@3.3.4)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@ -5750,6 +5757,21 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
vue: 3.3.4
|
vue: 3.3.4
|
||||||
|
|
||||||
|
/vue-demi@0.14.6(vue@3.3.4):
|
||||||
|
resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
hasBin: true
|
||||||
|
requiresBuild: true
|
||||||
|
peerDependencies:
|
||||||
|
'@vue/composition-api': ^1.0.0-rc.1
|
||||||
|
vue: ^3.0.0-0 || ^2.6.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@vue/composition-api':
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
vue: 3.3.4
|
||||||
|
dev: true
|
||||||
|
|
||||||
/vue-eslint-parser@9.3.1(eslint@8.40.0):
|
/vue-eslint-parser@9.3.1(eslint@8.40.0):
|
||||||
resolution: {integrity: sha512-Clr85iD2XFZ3lJ52/ppmUDG/spxQu6+MAeHXjjyI4I1NUYZ9xmenQp4N0oaHJhrA8OOxltCVxMRfANGa70vU0g==}
|
resolution: {integrity: sha512-Clr85iD2XFZ3lJ52/ppmUDG/spxQu6+MAeHXjjyI4I1NUYZ9xmenQp4N0oaHJhrA8OOxltCVxMRfANGa70vU0g==}
|
||||||
engines: {node: ^14.17.0 || >=16.0.0}
|
engines: {node: ^14.17.0 || >=16.0.0}
|
||||||
@ -5772,7 +5794,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-283vpYOhVHJCpMkjNVEwZdgaAb+Y93zFaXGAWTI378MLoNuwQydjD/BAy1e81QYEmyA+JbxqcmMZVWcM9rbriw==}
|
resolution: {integrity: sha512-283vpYOhVHJCpMkjNVEwZdgaAb+Y93zFaXGAWTI378MLoNuwQydjD/BAy1e81QYEmyA+JbxqcmMZVWcM9rbriw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint-config-vue-global-api: 0.4.1
|
eslint-config-vue-global-api: 0.4.1
|
||||||
vue-demi: 0.14.5(vue@3.3.4)
|
vue-demi: 0.14.6(vue@3.3.4)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@vue/composition-api'
|
- '@vue/composition-api'
|
||||||
- vue
|
- vue
|
||||||
|
36
src/api/command.ts
Normal file
36
src/api/command.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import request from '@/utils/axios';
|
||||||
|
|
||||||
|
// 获取口令列表
|
||||||
|
export function commandGet(params?: any) {
|
||||||
|
return request({
|
||||||
|
url: '/manager/web3/laboratory',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增口令
|
||||||
|
export function commandPost(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/manager/web3/laboratory',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑口令
|
||||||
|
export function commandPut(data: any, id: string) {
|
||||||
|
return request({
|
||||||
|
url: `/manager/web3/laboratory/${id}`,
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除口令
|
||||||
|
export function commandDelete(id: string) {
|
||||||
|
return request({
|
||||||
|
url: `/manager/web3/laboratory/${id}`,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
}
|
36
src/api/workplace/app.ts
Normal file
36
src/api/workplace/app.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import request from '@/utils/axios';
|
||||||
|
|
||||||
|
// 获取应用
|
||||||
|
export function appGet(params?: any) {
|
||||||
|
return request({
|
||||||
|
url: '/manager/workplace/app',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增应用
|
||||||
|
export function appPost(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/manager/workplace/app',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑应用
|
||||||
|
export function appPut(data: any, app_id: string) {
|
||||||
|
return request({
|
||||||
|
url: `/manager/workplace/apps/${app_id}`,
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除应用
|
||||||
|
export function appDelete(app_id: string) {
|
||||||
|
return request({
|
||||||
|
url: `/manager/workplace/apps/${app_id}`,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
}
|
45
src/api/workplace/banner.ts
Normal file
45
src/api/workplace/banner.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import request from '@/utils/axios';
|
||||||
|
|
||||||
|
// 获取轮播
|
||||||
|
export function bannerGet(params?: any) {
|
||||||
|
return request({
|
||||||
|
url: '/manager/workplace/banner',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增轮播
|
||||||
|
export function bannerPost(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/manager/workplace/banner',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑轮播
|
||||||
|
export function bannerPut(data: any, banner_no: string) {
|
||||||
|
return request({
|
||||||
|
url: `/manager/workplace/banners/${banner_no}`,
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除轮播
|
||||||
|
export function bannerDelete(banner_no: string) {
|
||||||
|
return request({
|
||||||
|
url: `/manager/workplace/banners/${banner_no}`,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 轮播排序
|
||||||
|
export function bannerReorderPut(data: any) {
|
||||||
|
return request({
|
||||||
|
url: `/manager/workplace/banner/reorder`,
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
79
src/api/workplace/category.ts
Normal file
79
src/api/workplace/category.ts
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import request from '@/utils/axios';
|
||||||
|
|
||||||
|
// 获取分类
|
||||||
|
export function categoryGet(params?: any) {
|
||||||
|
return request({
|
||||||
|
url: '/manager/workplace/category',
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增分类
|
||||||
|
export function categoryPost(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/manager/workplace/category',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分类编辑
|
||||||
|
export function categoryPut(data: any, category_no: string) {
|
||||||
|
return request({
|
||||||
|
url: `/manager/workplace/categorys/${category_no}`,
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除分类
|
||||||
|
export function categoryDelete(category_no: string) {
|
||||||
|
return request({
|
||||||
|
url: `/manager/workplace/categorys/${category_no}`,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分类排序
|
||||||
|
export function categoryReorderPut(data: any) {
|
||||||
|
return request({
|
||||||
|
url: '/manager/workplace/category/reorder',
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分类获取应用
|
||||||
|
export function categoryAppGet(category_no: string) {
|
||||||
|
return request({
|
||||||
|
url: `/manager/workplace/categorys/${category_no}/app`,
|
||||||
|
method: 'get'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分类新增应用
|
||||||
|
export function categoryAppPost(data: any, category_no: string) {
|
||||||
|
return request({
|
||||||
|
url: `/manager/workplace/categorys/${category_no}/app`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分类删除应用
|
||||||
|
export function categoryAppDelete(category_no: string, app_id: string) {
|
||||||
|
return request({
|
||||||
|
url: `/manager/workplace/categorys/${category_no}/apps/${app_id}`,
|
||||||
|
method: 'delete'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分类应用排序
|
||||||
|
export function categorysAppsReorderPut(data: any, category_no: string) {
|
||||||
|
return request({
|
||||||
|
url: `/manager/workplace/categorys/${category_no}/app/reorder`,
|
||||||
|
method: 'put',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
@ -5,13 +5,31 @@
|
|||||||
{{ msg['content'] }}
|
{{ msg['content'] }}
|
||||||
</span>
|
</span>
|
||||||
<!-- 图片 -->
|
<!-- 图片 -->
|
||||||
<img v-else-if="msg.type == 2" class="w-120px" :src="`${url}${msg['url']}`" />
|
<img
|
||||||
|
v-else-if="msg.type == 2"
|
||||||
|
class="w-120px cursor-pointer"
|
||||||
|
:src="`${url}${msg['url']}`"
|
||||||
|
@click="previewPicture(`${url}${msg['url']}`, 'image')"
|
||||||
|
/>
|
||||||
<!-- GIF -->
|
<!-- GIF -->
|
||||||
<img v-else-if="msg.type == 3" class="w-120px" :src="`${url}${msg['url']}`" />
|
<img
|
||||||
|
v-else-if="msg.type == 3"
|
||||||
|
class="w-120px cursor-pointer"
|
||||||
|
:src="`${url}${msg['url']}`"
|
||||||
|
@click="previewPicture(`${url}${msg['url']}`, 'image')"
|
||||||
|
/>
|
||||||
<!-- 语音 -->
|
<!-- 语音 -->
|
||||||
<audio v-else-if="msg.type == 4" :src="`${url}${msg['url']}`"></audio>
|
<audio v-else-if="msg.type == 4" :src="`${url}${msg['url']}`"></audio>
|
||||||
<!-- 视频 -->
|
<!-- 视频 -->
|
||||||
<video v-else-if="msg.type == 5" controls :src="`${url}${msg['url']}`" class="w-220px h-100px"></video>
|
<video
|
||||||
|
v-else-if="msg.type == 5"
|
||||||
|
controls
|
||||||
|
controlsList="nofullscreen nodownload noplaybackrate noremote footbar"
|
||||||
|
disablePictureInPicture
|
||||||
|
:src="`${url}${msg['url']}`"
|
||||||
|
class="w-220px h-100px cursor-pointer"
|
||||||
|
@click="previewPicture(`${url}${msg['url']}`, 'image')"
|
||||||
|
></video>
|
||||||
<!-- 位置 -->
|
<!-- 位置 -->
|
||||||
<div v-else-if="msg.type == 6">
|
<div v-else-if="msg.type == 6">
|
||||||
<div>位置标题:{{ msg['title'] }}</div>
|
<div>位置标题:{{ msg['title'] }}</div>
|
||||||
@ -73,6 +91,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="tsx" name="BdMsg" setup>
|
<script lang="tsx" name="BdMsg" setup>
|
||||||
|
import { Fancybox } from '@fancyapps/ui';
|
||||||
import '@lottiefiles/lottie-player/dist/tgs-player';
|
import '@lottiefiles/lottie-player/dist/tgs-player';
|
||||||
import { BU_DOU_CONFIG } from '@/config';
|
import { BU_DOU_CONFIG } from '@/config';
|
||||||
interface IProps {
|
interface IProps {
|
||||||
@ -80,4 +99,37 @@ interface IProps {
|
|||||||
}
|
}
|
||||||
defineProps<IProps>();
|
defineProps<IProps>();
|
||||||
const url = BU_DOU_CONFIG.APP_URL;
|
const url = BU_DOU_CONFIG.APP_URL;
|
||||||
|
|
||||||
|
// 图片预览
|
||||||
|
const previewPicture = (url: string, type: string) => {
|
||||||
|
const imgList = [];
|
||||||
|
imgList.push({ src: url, defaultType: type });
|
||||||
|
Fancybox.show(imgList, {
|
||||||
|
Toolbar: {
|
||||||
|
display: {
|
||||||
|
left: ['infobar'],
|
||||||
|
middle: ['zoomIn', 'zoomOut', 'toggle1to1', 'rotateCCW', 'rotateCW', 'flipX', 'flipY'],
|
||||||
|
right: ['slideshow', 'thumbs', 'close']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
video::-webkit-media-controls-timeline {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
video::-webkit-media-controls-mute-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
video::-webkit-media-controls-toggle-closed-captions-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
video::-webkit-media-controls-volume-slider {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
video::-webkit-media-controls-fullscreen-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -10,25 +10,6 @@
|
|||||||
:class="tabsMenuValue === item.path ? 'chrome-tab_active' : ''"
|
:class="tabsMenuValue === item.path ? 'chrome-tab_active' : ''"
|
||||||
@click.stop="tabClick(item)"
|
@click.stop="tabClick(item)"
|
||||||
>
|
>
|
||||||
<!-- <div class="chrome-tab__bg">
|
|
||||||
<svg style="width: 100%; height: 100%">
|
|
||||||
<defs>
|
|
||||||
<symbol id="geometry-left" viewBox="0 0 214 36">
|
|
||||||
<path d="M17 0h197v36H0v-2c4.5 0 9-3.5 9-8V8c0-4.5 3.5-8 8-8z"></path>
|
|
||||||
</symbol>
|
|
||||||
<symbol id="geometry-right" viewBox="0 0 214 36"><use xlink:href="#geometry-left"></use></symbol>
|
|
||||||
<clipPath><rect width="100%" height="100%" x="0"></rect></clipPath>
|
|
||||||
</defs>
|
|
||||||
<svg width="51%" height="100%">
|
|
||||||
<use xlink:href="#geometry-left" width="214" height="36" fill="currentColor"></use>
|
|
||||||
</svg>
|
|
||||||
<g transform="scale(-1, 1)">
|
|
||||||
<svg width="51%" height="100%" x="-100%" y="0">
|
|
||||||
<use xlink:href="#geometry-right" width="214" height="36" fill="currentColor"></use>
|
|
||||||
</svg>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</div> -->
|
|
||||||
<div v-if="item.icon && tabsIcon">
|
<div v-if="item.icon && tabsIcon">
|
||||||
<component :is="'i-bd-add-text'" theme="outline" size="16" class="cursor-pointer" />
|
<component :is="'i-bd-add-text'" theme="outline" size="16" class="cursor-pointer" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -19,6 +19,7 @@ import 'vue-global-api';
|
|||||||
import 'element-plus/dist/index.css';
|
import 'element-plus/dist/index.css';
|
||||||
import 'element-plus/theme-chalk/dark/css-vars.css';
|
import 'element-plus/theme-chalk/dark/css-vars.css';
|
||||||
import '@icon-park/vue-next/styles/index.css';
|
import '@icon-park/vue-next/styles/index.css';
|
||||||
|
import '@fancyapps/ui/dist/fancybox/fancybox.css';
|
||||||
import '@/styles/index.scss';
|
import '@/styles/index.scss';
|
||||||
import 'uno.css';
|
import 'uno.css';
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ const home: Menu.MenuOptions = {
|
|||||||
isHide: false,
|
isHide: false,
|
||||||
isKeepAlive: true,
|
isKeepAlive: true,
|
||||||
isLink: '',
|
isLink: '',
|
||||||
index: 8,
|
index: 9,
|
||||||
title: '设置'
|
title: '设置'
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
@ -9,7 +9,7 @@ const home: Menu.MenuOptions = {
|
|||||||
isHide: false,
|
isHide: false,
|
||||||
isKeepAlive: true,
|
isKeepAlive: true,
|
||||||
isLink: '',
|
isLink: '',
|
||||||
index: 7,
|
index: 8,
|
||||||
title: '工具'
|
title: '工具'
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
@ -27,6 +27,20 @@ const home: Menu.MenuOptions = {
|
|||||||
title: 'APP升级'
|
title: 'APP升级'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
component: '/tool/command',
|
||||||
|
name: 'toolCommand',
|
||||||
|
path: '/tool/command',
|
||||||
|
meta: {
|
||||||
|
icon: 'i-bd-command',
|
||||||
|
isAffix: false,
|
||||||
|
isFull: false,
|
||||||
|
isHide: false,
|
||||||
|
isKeepAlive: true,
|
||||||
|
isLink: '',
|
||||||
|
title: '口令管理'
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
component: '/tool/systemrobotmenu',
|
component: '/tool/systemrobotmenu',
|
||||||
name: 'toolSystemrobotmenu',
|
name: 'toolSystemrobotmenu',
|
||||||
|
43
src/menu/modules/workplace.ts
Normal file
43
src/menu/modules/workplace.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
const home: Menu.MenuOptions = {
|
||||||
|
name: 'tool',
|
||||||
|
path: '/workplace',
|
||||||
|
meta: {
|
||||||
|
icon: 'i-bd-all-application',
|
||||||
|
isAffix: false,
|
||||||
|
isFull: false,
|
||||||
|
isHide: false,
|
||||||
|
isKeepAlive: true,
|
||||||
|
isLink: '',
|
||||||
|
index: 7,
|
||||||
|
title: '工作台'
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: 'workplaceManage',
|
||||||
|
path: '/workplace/manage',
|
||||||
|
meta: {
|
||||||
|
icon: 'i-bd-application',
|
||||||
|
isAffix: false,
|
||||||
|
isFull: false,
|
||||||
|
isHide: false,
|
||||||
|
isKeepAlive: true,
|
||||||
|
isLink: '',
|
||||||
|
title: '应用管理'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'workplaceConfiguration',
|
||||||
|
path: '/workplace/configuration',
|
||||||
|
meta: {
|
||||||
|
icon: 'i-bd-setting-config',
|
||||||
|
isAffix: false,
|
||||||
|
isFull: false,
|
||||||
|
isHide: false,
|
||||||
|
isKeepAlive: true,
|
||||||
|
isLink: '',
|
||||||
|
title: '工作台设置'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
export default home;
|
@ -35,8 +35,8 @@
|
|||||||
<template v-else-if="item.formatter">
|
<template v-else-if="item.formatter">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else-if="item.prop">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@ -32,8 +32,8 @@
|
|||||||
<template v-else-if="item.formatter">
|
<template v-else-if="item.formatter">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else-if="item.prop">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@ -35,8 +35,8 @@
|
|||||||
<template v-else-if="item.formatter">
|
<template v-else-if="item.formatter">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else-if="item.prop">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -198,8 +198,8 @@ const getUserList = () => {
|
|||||||
loadTable.value = true;
|
loadTable.value = true;
|
||||||
messageRecordpersonalGet(queryFrom).then((res: any) => {
|
messageRecordpersonalGet(queryFrom).then((res: any) => {
|
||||||
loadTable.value = false;
|
loadTable.value = false;
|
||||||
tableData.value = res.list;
|
tableData.value = res?.list ? res?.list : [];
|
||||||
total.value = res.count;
|
total.value = res?.count ? res?.count : 0;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -225,6 +225,7 @@ const msgDel = (data: any) => {
|
|||||||
const formData = {
|
const formData = {
|
||||||
channel_id: route.query.uid,
|
channel_id: route.query.uid,
|
||||||
channel_type: 1,
|
channel_type: 1,
|
||||||
|
from_uid: route.query.touid,
|
||||||
list
|
list
|
||||||
};
|
};
|
||||||
messageDelete(formData).then((res: any) => {
|
messageDelete(formData).then((res: any) => {
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@ -32,8 +32,8 @@
|
|||||||
<template v-else-if="item.formatter">
|
<template v-else-if="item.formatter">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else-if="item.prop">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
<template v-else-if="item.formatter">
|
<template v-else-if="item.formatter">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else-if="item.prop">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
<template v-else-if="item.formatter">
|
<template v-else-if="item.formatter">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else-if="item.prop">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@ -29,8 +29,8 @@
|
|||||||
<template v-else-if="item.formatter">
|
<template v-else-if="item.formatter">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else-if="item.prop">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
146
src/pages/tool/command/components/CommandDialog.vue
Normal file
146
src/pages/tool/command/components/CommandDialog.vue
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:model-value="value"
|
||||||
|
:width="600"
|
||||||
|
:align-center="true"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
:draggable="true"
|
||||||
|
:z-index="99"
|
||||||
|
:title="title"
|
||||||
|
@close="onClose"
|
||||||
|
>
|
||||||
|
<el-form :model="formData" label-width="96px">
|
||||||
|
<el-form-item label="口令">
|
||||||
|
<el-input v-model="formData.short_url" placeholder="请输入口令" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="地址">
|
||||||
|
<el-input v-model="formData.url" placeholder="请输入地址" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-space>
|
||||||
|
<el-button @click="onClose">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="loaging" @click="onConfirm">保存</el-button>
|
||||||
|
</el-space>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" name="CommandDialog" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
// API 接口
|
||||||
|
import { commandPost, commandPut } from '@/api/command';
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
value: boolean;
|
||||||
|
title: string;
|
||||||
|
type: 'add' | 'edit';
|
||||||
|
data: object;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<IProps>(), {
|
||||||
|
value: false,
|
||||||
|
title: '新增口令',
|
||||||
|
type: 'add'
|
||||||
|
});
|
||||||
|
|
||||||
|
const content = ref('');
|
||||||
|
const loaging = ref<boolean>(false);
|
||||||
|
const formData = ref({
|
||||||
|
short_url: '',
|
||||||
|
url: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: 'update:value', item: boolean): void;
|
||||||
|
(e: 'ok', item: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(n, _o) => {
|
||||||
|
if (n && props.type === 'edit') {
|
||||||
|
formData.value = props.data as any;
|
||||||
|
}
|
||||||
|
if (!n) {
|
||||||
|
formData.value = {
|
||||||
|
short_url: '',
|
||||||
|
url: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 取消
|
||||||
|
const onClose = () => {
|
||||||
|
emits('update:value', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增口令
|
||||||
|
const addBanner = () => {
|
||||||
|
loaging.value = true;
|
||||||
|
commandPost(formData.value)
|
||||||
|
.then((res: any) => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (res.status == 200) {
|
||||||
|
ElMessage.success('新增成功!');
|
||||||
|
content.value = '';
|
||||||
|
onClose();
|
||||||
|
emits('ok', true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (err.status == 400) {
|
||||||
|
ElMessage.error(err.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑口令
|
||||||
|
const editBanner = () => {
|
||||||
|
loaging.value = true;
|
||||||
|
commandPut(formData.value, (props.data as any).id)
|
||||||
|
.then((res: any) => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (res.status == 200) {
|
||||||
|
ElMessage.success('编辑成功!');
|
||||||
|
content.value = '';
|
||||||
|
onClose();
|
||||||
|
emits('ok', true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (err.status == 400) {
|
||||||
|
ElMessage.error(err.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 保存
|
||||||
|
const onConfirm = () => {
|
||||||
|
if (props.type === 'add') {
|
||||||
|
addBanner();
|
||||||
|
}
|
||||||
|
if (props.type === 'edit') {
|
||||||
|
editBanner();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.bd-uplod {
|
||||||
|
::v-deep(.el-upload--picture-card) {
|
||||||
|
height: 78px;
|
||||||
|
width: 78px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
height: 78px;
|
||||||
|
width: 78px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
220
src/pages/tool/command/index.vue
Normal file
220
src/pages/tool/command/index.vue
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
<template>
|
||||||
|
<bd-page class="flex-col">
|
||||||
|
<div class="flex-1 el-card border-none flex-col box-border overflow-hidden">
|
||||||
|
<div class="h-50px pl-12px pr-12px box-border flex items-center justify-between bd-title">
|
||||||
|
<div class="bd-title-left">
|
||||||
|
<p class="m-0 font-600">口令管理</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center h-50px">
|
||||||
|
<el-form inline>
|
||||||
|
<el-form-item class="mb-0 !mr-16px">
|
||||||
|
<el-input v-model="queryFrom.keyword" placeholder="名称" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item class="mb-0 !mr-16px">
|
||||||
|
<el-button type="primary" @click="getTableList">查询</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item class="mb-0 !mr-0">
|
||||||
|
<el-button type="primary" @click="onCommandAddClick">新增口令</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex-1 overflow-hidden p-12px">
|
||||||
|
<el-table v-loading="loadTable" :data="tableData" :border="true" style="width: 100%; height: 100%">
|
||||||
|
<el-table-column type="index" :width="42" :align="'center'" :fixed="'left'">
|
||||||
|
<template #header>
|
||||||
|
<i-bd-drag class="cursor-pointer" size="16" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column v-for="item in column" v-bind="item" :key="item.prop">
|
||||||
|
<template #default="scope">
|
||||||
|
<template v-if="item.render">
|
||||||
|
<component :is="item.render" :row="scope.row"> </component>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="item.formatter">
|
||||||
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="item.prop">
|
||||||
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<div class="bd-card-footer pl-12px pr-12px mb-12px flex items-center justify-between">
|
||||||
|
<div></div>
|
||||||
|
<el-pagination
|
||||||
|
v-model:current-page="queryFrom.page_index"
|
||||||
|
v-model:page-size="queryFrom.page_size"
|
||||||
|
:page-sizes="[15, 20, 30, 50, 100]"
|
||||||
|
:background="true"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="total"
|
||||||
|
@size-change="onSizeChange"
|
||||||
|
@current-change="onCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 口令操作 -->
|
||||||
|
<CommandDialog
|
||||||
|
v-model:value="commandDialogValue"
|
||||||
|
:title="commandDialogTitle"
|
||||||
|
:type="commandDialogType"
|
||||||
|
:data="commandDialogData"
|
||||||
|
@ok="onCommandOk"
|
||||||
|
/>
|
||||||
|
</bd-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<route lang="yaml">
|
||||||
|
meta:
|
||||||
|
title: 口令管理
|
||||||
|
isAffix: false
|
||||||
|
</route>
|
||||||
|
|
||||||
|
<script lang="tsx" name="command" setup>
|
||||||
|
import { ElButton, ElSpace, ElMessage, ElMessageBox } from 'element-plus';
|
||||||
|
import CommandDialog from './components/CommandDialog.vue';
|
||||||
|
|
||||||
|
// API接口
|
||||||
|
import { commandGet, commandDelete } from '@/api/command';
|
||||||
|
/**
|
||||||
|
* 表格
|
||||||
|
*/
|
||||||
|
const column = reactive<Column.ColumnOptions[]>([
|
||||||
|
{
|
||||||
|
prop: 'short_url',
|
||||||
|
label: '口令名称'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'url',
|
||||||
|
label: '地址'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'create_at',
|
||||||
|
label: '创建时间'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'operation',
|
||||||
|
label: '操作',
|
||||||
|
width: 150,
|
||||||
|
align: 'center',
|
||||||
|
render: (scope: any) => {
|
||||||
|
return (
|
||||||
|
<ElSpace>
|
||||||
|
<ElButton type="primary" onClick={() => onCommandEidt(scope.row)}>
|
||||||
|
编辑
|
||||||
|
</ElButton>
|
||||||
|
<ElButton type="danger" onClick={() => onCommandDel(scope.row)}>
|
||||||
|
删除
|
||||||
|
</ElButton>
|
||||||
|
</ElSpace>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
const tableData = ref<any[]>([]);
|
||||||
|
const loadTable = ref<boolean>(false);
|
||||||
|
// 分页
|
||||||
|
const total = ref(0);
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const queryFrom = reactive({
|
||||||
|
keyword: '',
|
||||||
|
page_size: 15,
|
||||||
|
page_index: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
// 搜索
|
||||||
|
const getTableList = () => {
|
||||||
|
loadTable.value = true;
|
||||||
|
commandGet(queryFrom)
|
||||||
|
.then((res: any) => {
|
||||||
|
loadTable.value = false;
|
||||||
|
tableData.value = res.list;
|
||||||
|
total.value = res.count;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loadTable.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页page-size
|
||||||
|
const onSizeChange = (size: number) => {
|
||||||
|
queryFrom.page_size = size;
|
||||||
|
getTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页page-size
|
||||||
|
const onCurrentChange = (current: number) => {
|
||||||
|
queryFrom.page_index = current;
|
||||||
|
getTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增口令
|
||||||
|
const commandDialogValue = ref(false);
|
||||||
|
const commandDialogTitle = ref('新增口令');
|
||||||
|
const commandDialogType = ref<'add' | 'edit'>('add');
|
||||||
|
const onCommandAddClick = () => {
|
||||||
|
commandDialogTitle.value = '新增口令';
|
||||||
|
commandDialogType.value = 'add';
|
||||||
|
commandDialogValue.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑口令
|
||||||
|
const commandDialogData = ref({});
|
||||||
|
const onCommandEidt = (item: any) => {
|
||||||
|
commandDialogTitle.value = `编辑${item.short_url}`;
|
||||||
|
commandDialogData.value = item;
|
||||||
|
commandDialogType.value = 'edit';
|
||||||
|
commandDialogValue.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存口令
|
||||||
|
const onCommandOk = () => {
|
||||||
|
getTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除口令
|
||||||
|
const onCommandDel = (item: any) => {
|
||||||
|
ElMessageBox.confirm(`确定要对该口令吗?`, `操作提示`, {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
closeOnClickModal: false,
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
commandDelete(item.id)
|
||||||
|
.then((_res: any) => {
|
||||||
|
getTableList();
|
||||||
|
ElMessage({
|
||||||
|
type: 'success',
|
||||||
|
message: `口令删除成功!`
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
if (err.status == 400) {
|
||||||
|
ElMessage.error(err.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
ElMessage({
|
||||||
|
type: 'info',
|
||||||
|
message: '取消成功!'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getTableList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 样式
|
||||||
|
.bd-title {
|
||||||
|
border-bottom: 1px solid var(--el-card-border-color);
|
||||||
|
}
|
||||||
|
</style>
|
@ -23,8 +23,8 @@
|
|||||||
<template v-else-if="item.formatter">
|
<template v-else-if="item.formatter">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else-if="item.prop">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@ -32,8 +32,8 @@
|
|||||||
<template v-else-if="item.formatter">
|
<template v-else-if="item.formatter">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else-if="item.prop">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@ -36,8 +36,8 @@
|
|||||||
<template v-else-if="item.formatter">
|
<template v-else-if="item.formatter">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else-if="item.prop">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@ -35,8 +35,8 @@
|
|||||||
<template v-else-if="item.formatter">
|
<template v-else-if="item.formatter">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else-if="item.prop">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
@ -33,8 +33,8 @@
|
|||||||
<template v-else-if="item.formatter">
|
<template v-else-if="item.formatter">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else-if="item.prop">
|
||||||
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop] }}</slot>
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -81,7 +81,7 @@ const userStore = useUserStore();
|
|||||||
const column = reactive<Column.ColumnOptions[]>([
|
const column = reactive<Column.ColumnOptions[]>([
|
||||||
{
|
{
|
||||||
prop: 'name',
|
prop: 'name',
|
||||||
label: '用户名',
|
label: '昵称',
|
||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
width: 140
|
width: 140
|
||||||
},
|
},
|
||||||
@ -91,6 +91,11 @@ const column = reactive<Column.ColumnOptions[]>([
|
|||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
width: 120
|
width: 120
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
prop: 'username',
|
||||||
|
label: '用户',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
{
|
{
|
||||||
prop: 'avatar',
|
prop: 'avatar',
|
||||||
label: '头像',
|
label: '头像',
|
||||||
|
192
src/pages/workplace/configuration/components/AppDialog.vue
Normal file
192
src/pages/workplace/configuration/components/AppDialog.vue
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:model-value="value"
|
||||||
|
:width="780"
|
||||||
|
:align-center="true"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
:draggable="true"
|
||||||
|
:z-index="99"
|
||||||
|
title="添加应用"
|
||||||
|
@close="onClose"
|
||||||
|
>
|
||||||
|
<div class="h-540px flex-col">
|
||||||
|
<el-input v-model="queryFrom.keyword" class="mb-12px" placeholder="请输入应用名称" clearable @keyup.enter="onSearch" />
|
||||||
|
<!-- 表格 -->
|
||||||
|
<div class="flex-1 overflow-hidden">
|
||||||
|
<el-table
|
||||||
|
v-loading="loadTable"
|
||||||
|
:data="tableData"
|
||||||
|
row-key="app_id"
|
||||||
|
:show-header="false"
|
||||||
|
style="width: 100%; height: 100%"
|
||||||
|
@selection-change="onSelectionChange"
|
||||||
|
>
|
||||||
|
<el-table-column v-for="(col, index) in column" v-bind="col" :key="index">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<template v-if="col.render">
|
||||||
|
<component :is="col.render" :row="row"> </component>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="col.formatter">
|
||||||
|
<slot :name="col.prop" :row="row">{{ col.formatter(row) }}</slot>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="col.prop">
|
||||||
|
<slot :name="col.prop" :row="row">{{ row[col.prop] }}</slot>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<!-- 分页 -->
|
||||||
|
<div class="bd-card-footer mt-12px flex items-center justify-between">
|
||||||
|
<div></div>
|
||||||
|
<el-pagination
|
||||||
|
v-model:current-page="queryFrom.page_index"
|
||||||
|
v-model:page-size="queryFrom.page_size"
|
||||||
|
:page-sizes="[15, 20, 30, 50, 100]"
|
||||||
|
:background="true"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="total"
|
||||||
|
@size-change="onSizeChange"
|
||||||
|
@current-change="onCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<el-space>
|
||||||
|
<el-button @click="onClose">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="loaging" @click="onConfirm">确定</el-button>
|
||||||
|
</el-space>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" name="AppDialog" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
// API 接口
|
||||||
|
import { categoryAppPost } from '@/api/workplace/category';
|
||||||
|
import { appGet } from '@/api/workplace/app';
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
value: boolean;
|
||||||
|
data: {
|
||||||
|
category_no: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const props = withDefaults(defineProps<IProps>(), {
|
||||||
|
value: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const loaging = ref<boolean>(false);
|
||||||
|
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: 'update:value', item: boolean): void;
|
||||||
|
(e: 'ok', item: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(n, _o) => {
|
||||||
|
props.value = n;
|
||||||
|
if (n) {
|
||||||
|
getTableList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格
|
||||||
|
*/
|
||||||
|
const column = reactive<Column.ColumnOptions[]>([
|
||||||
|
{
|
||||||
|
prop: 'name',
|
||||||
|
label: '名称'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'description',
|
||||||
|
label: '描述'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'selection'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
const tableData = ref<any[]>([]);
|
||||||
|
const loadTable = ref<boolean>(false);
|
||||||
|
const selectionData = ref<string[]>([]);
|
||||||
|
const queryFrom = reactive({
|
||||||
|
keyword: '',
|
||||||
|
page_size: 15,
|
||||||
|
page_index: 1
|
||||||
|
});
|
||||||
|
const total = ref(0);
|
||||||
|
// 获取表格数据
|
||||||
|
const getTableList = () => {
|
||||||
|
loadTable.value = true;
|
||||||
|
appGet(queryFrom)
|
||||||
|
.then((res: any) => {
|
||||||
|
loadTable.value = false;
|
||||||
|
tableData.value = res.list || [];
|
||||||
|
total.value = res.count || 0;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loadTable.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 搜索
|
||||||
|
const onSearch = () => {
|
||||||
|
queryFrom.page_index = 1;
|
||||||
|
queryFrom.page_size = 15;
|
||||||
|
getTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSelectionChange = (val: any[]) => {
|
||||||
|
const opt: string[] = [];
|
||||||
|
val.map(item => {
|
||||||
|
opt.push(item.app_id);
|
||||||
|
});
|
||||||
|
selectionData.value = opt;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页page-size
|
||||||
|
const onSizeChange = (size: number) => {
|
||||||
|
queryFrom.page_size = size;
|
||||||
|
getTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页page-size
|
||||||
|
const onCurrentChange = (current: number) => {
|
||||||
|
queryFrom.page_index = current;
|
||||||
|
getTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onClose = () => {
|
||||||
|
emits('update:value', false);
|
||||||
|
};
|
||||||
|
// 保存
|
||||||
|
const onConfirm = () => {
|
||||||
|
if (selectionData.value.length === 0) {
|
||||||
|
return ElMessage.info('请输入分类!');
|
||||||
|
}
|
||||||
|
const fromData = {
|
||||||
|
app_ids: selectionData.value
|
||||||
|
};
|
||||||
|
loaging.value = true;
|
||||||
|
categoryAppPost(fromData, props.data.category_no)
|
||||||
|
.then((res: any) => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (res.status == 200) {
|
||||||
|
ElMessage.success('新增应用成功!');
|
||||||
|
onClose();
|
||||||
|
emits('ok', true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (err.status == 400) {
|
||||||
|
ElMessage.error(err.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
265
src/pages/workplace/configuration/components/Banner.vue
Normal file
265
src/pages/workplace/configuration/components/Banner.vue
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
<template>
|
||||||
|
<bd-page class="flex-col !p-0">
|
||||||
|
<div class="flex-1 el-card border-none flex-col box-border overflow-hidden">
|
||||||
|
<div class="h-50px pl-12px pr-12px box-border flex items-center justify-between bd-title">
|
||||||
|
<div class="bd-title-left"></div>
|
||||||
|
<div class="flex items-center h-50px">
|
||||||
|
<el-form inline>
|
||||||
|
<el-form-item class="mb-0 !mr-0">
|
||||||
|
<el-button type="primary" @click="onBannerDialogValue">新增轮播</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex-1 overflow-hidden p-12px">
|
||||||
|
<el-table v-loading="loadTable" :data="tableData" row-key="banner_no" :border="true" style="width: 100%; height: 100%">
|
||||||
|
<el-table-column type="index" :width="42" :align="'center'" :fixed="'left'">
|
||||||
|
<template #header>
|
||||||
|
<i-bd-drag class="cursor-pointer" size="16" />
|
||||||
|
</template>
|
||||||
|
<template #default>
|
||||||
|
<i-bd-drag class="bd-drag cursor-pointer" size="16" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column v-for="item in column" v-bind="item" :key="item.prop">
|
||||||
|
<template #default="scope">
|
||||||
|
<template v-if="item.render">
|
||||||
|
<component :is="item.render" :row="scope.row"> </component>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="item.formatter">
|
||||||
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="item.prop">
|
||||||
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 轮播 -->
|
||||||
|
<BannerDialog
|
||||||
|
v-model:value="bannerDialogValue"
|
||||||
|
:title="bannerDialogTitle"
|
||||||
|
:type="bannerDialogType"
|
||||||
|
:data="bannerDialogData"
|
||||||
|
@ok="onBannerOk"
|
||||||
|
/>
|
||||||
|
</bd-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="tsx" name="Banner" setup>
|
||||||
|
import { ElButton, ElSpace, ElMessageBox, ElMessage } from 'element-plus';
|
||||||
|
import { Fancybox } from '@fancyapps/ui';
|
||||||
|
import Sortable from 'sortablejs';
|
||||||
|
import BannerDialog from './BannerDialog.vue';
|
||||||
|
import { BU_DOU_CONFIG } from '@/config';
|
||||||
|
|
||||||
|
// API接口
|
||||||
|
import { bannerGet, bannerDelete, bannerReorderPut } from '@/api/workplace/banner';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格
|
||||||
|
*/
|
||||||
|
// 图片预览
|
||||||
|
const previewPicture = (url: string) => {
|
||||||
|
const imgList = [];
|
||||||
|
imgList.push({ src: url });
|
||||||
|
Fancybox.show(imgList, {
|
||||||
|
Toolbar: {
|
||||||
|
display: {
|
||||||
|
left: ['infobar'],
|
||||||
|
middle: ['zoomIn', 'zoomOut', 'toggle1to1', 'rotateCCW', 'rotateCW', 'flipX', 'flipY'],
|
||||||
|
right: ['slideshow', 'thumbs', 'close']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const column = reactive<Column.ColumnOptions[]>([
|
||||||
|
{
|
||||||
|
prop: 'title',
|
||||||
|
label: '名称'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'cover',
|
||||||
|
label: '图片',
|
||||||
|
width: 146,
|
||||||
|
render: (scope: any) => {
|
||||||
|
let img_url = '';
|
||||||
|
if (scope.row['cover']) {
|
||||||
|
img_url = `${BU_DOU_CONFIG.APP_URL}${scope.row.cover}`;
|
||||||
|
}
|
||||||
|
return <img src={img_url} class={'w-120px h-60px cursor-pointer'} onClick={() => previewPicture(img_url)} />;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'route',
|
||||||
|
label: '地址'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'status',
|
||||||
|
label: '打开方式',
|
||||||
|
formatter(row: any) {
|
||||||
|
return row.status === 0 ? '网页' : '原生';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'description',
|
||||||
|
label: '描述'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'created_at',
|
||||||
|
label: '创建时间',
|
||||||
|
width: 180
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'operation',
|
||||||
|
label: '操作',
|
||||||
|
width: 150,
|
||||||
|
align: 'center',
|
||||||
|
render: (scope: any) => {
|
||||||
|
return (
|
||||||
|
<ElSpace>
|
||||||
|
<ElButton type="primary" onClick={() => onBannerEidt(scope.row)}>
|
||||||
|
编辑
|
||||||
|
</ElButton>
|
||||||
|
<ElButton type="danger" onClick={() => onDelBanner(scope.row)}>
|
||||||
|
删除
|
||||||
|
</ElButton>
|
||||||
|
</ElSpace>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
const tableData = ref<any[]>([]);
|
||||||
|
const loadTable = ref<boolean>(false);
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const queryFrom = reactive({
|
||||||
|
keyword: '',
|
||||||
|
page_size: 15,
|
||||||
|
page_index: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
// 搜索
|
||||||
|
const getTableList = () => {
|
||||||
|
loadTable.value = true;
|
||||||
|
bannerGet(queryFrom)
|
||||||
|
.then((res: any) => {
|
||||||
|
loadTable.value = false;
|
||||||
|
tableData.value = res;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loadTable.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增轮播
|
||||||
|
const bannerDialogValue = ref(false);
|
||||||
|
const bannerDialogTitle = ref('新增轮播');
|
||||||
|
const bannerDialogType = ref<'add' | 'edit'>('add');
|
||||||
|
const onBannerDialogValue = () => {
|
||||||
|
bannerDialogTitle.value = `新增轮播`;
|
||||||
|
bannerDialogType.value = 'add';
|
||||||
|
bannerDialogValue.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑轮播
|
||||||
|
const bannerDialogData = ref({});
|
||||||
|
const onBannerEidt = (item: any) => {
|
||||||
|
bannerDialogTitle.value = `编辑${item.title}`;
|
||||||
|
bannerDialogData.value = item;
|
||||||
|
bannerDialogType.value = 'edit';
|
||||||
|
bannerDialogValue.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存轮播
|
||||||
|
const onBannerOk = () => {
|
||||||
|
getTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除轮播
|
||||||
|
const onDelBanner = (item: any) => {
|
||||||
|
ElMessageBox.confirm(`确定要对该轮播吗?`, `操作提示`, {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
closeOnClickModal: false,
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
bannerDelete(item.banner_no)
|
||||||
|
.then((_res: any) => {
|
||||||
|
getTableList();
|
||||||
|
ElMessage({
|
||||||
|
type: 'success',
|
||||||
|
message: `轮播删除成功!`
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
if (err.status == 400) {
|
||||||
|
ElMessage.error(err.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
ElMessage({
|
||||||
|
type: 'info',
|
||||||
|
message: '取消成功!'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const bannerReorder = (newIndex: string, oldIndex: string) => {
|
||||||
|
const fromData = {
|
||||||
|
banner_nos: [newIndex, oldIndex]
|
||||||
|
};
|
||||||
|
bannerReorderPut(fromData).then(res => {
|
||||||
|
if (res.status == 200) {
|
||||||
|
getTableList();
|
||||||
|
ElMessage({
|
||||||
|
type: 'success',
|
||||||
|
message: `轮播排序成功`
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ElMessage({
|
||||||
|
type: 'info',
|
||||||
|
message: '轮播排序失败!'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// tree 拖拽排序
|
||||||
|
const tableDrop = () => {
|
||||||
|
Sortable.create(document.querySelector('.el-table__body-wrapper tbody') as HTMLElement, {
|
||||||
|
handle: '.bd-drag',
|
||||||
|
animation: 300,
|
||||||
|
onEnd(evt: any) {
|
||||||
|
const { newIndex, oldIndex } = evt;
|
||||||
|
const tablesList = [...tableData.value];
|
||||||
|
const currRow = tablesList.splice(oldIndex as number, 1)[0];
|
||||||
|
tablesList.splice(newIndex as number, 0, currRow);
|
||||||
|
if (oldIndex > newIndex) {
|
||||||
|
// 向上排序
|
||||||
|
bannerReorder(tablesList[newIndex].banner_no, tablesList[oldIndex].banner_no);
|
||||||
|
} else {
|
||||||
|
// 向下排序
|
||||||
|
bannerReorder(tablesList[oldIndex].banner_no, tablesList[newIndex].banner_no);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getTableList();
|
||||||
|
tableDrop();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 样式
|
||||||
|
.bd-title {
|
||||||
|
border-bottom: 1px solid var(--el-card-border-color);
|
||||||
|
}
|
||||||
|
</style>
|
212
src/pages/workplace/configuration/components/BannerDialog.vue
Normal file
212
src/pages/workplace/configuration/components/BannerDialog.vue
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:model-value="value"
|
||||||
|
:width="600"
|
||||||
|
:align-center="true"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
:draggable="true"
|
||||||
|
:z-index="99"
|
||||||
|
:title="title"
|
||||||
|
@close="onClose"
|
||||||
|
>
|
||||||
|
<el-form :model="formData" label-width="96px">
|
||||||
|
<el-form-item label="标题">
|
||||||
|
<el-input v-model="formData.title" placeholder="请输入标题" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="图片">
|
||||||
|
<el-upload
|
||||||
|
ref="upload"
|
||||||
|
class="bd-upload"
|
||||||
|
:action="actionURL"
|
||||||
|
list-type="picture-card"
|
||||||
|
:show-file-list="false"
|
||||||
|
:headers="headers"
|
||||||
|
:before-upload="beforeUploadFile"
|
||||||
|
:on-success="onFileSuccess"
|
||||||
|
>
|
||||||
|
<img v-if="formData.cover" :src="`${BU_DOU_CONFIG.APP_URL}${formData.cover}`" class="avatar" />
|
||||||
|
<el-icon v-else><Plus /></el-icon>
|
||||||
|
</el-upload>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="打开方式">
|
||||||
|
<el-radio-group v-model="formData.jump_type">
|
||||||
|
<el-radio :label="0">网页</el-radio>
|
||||||
|
<el-radio :label="1">APP</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="地址">
|
||||||
|
<el-input v-model="formData.route" placeholder="请输入地址" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="描述">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.description"
|
||||||
|
type="textarea"
|
||||||
|
:autosize="{ minRows: 6, maxRows: 8 }"
|
||||||
|
placeholder="请输入描述"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-space>
|
||||||
|
<el-button @click="onClose">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="loaging" @click="onConfirm">保存</el-button>
|
||||||
|
</el-space>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" name="BannerDialog" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { Plus } from '@element-plus/icons-vue';
|
||||||
|
import { useUserStore } from '@/stores/modules/user';
|
||||||
|
// API 接口
|
||||||
|
import { bannerPost, bannerPut } from '@/api/workplace/banner';
|
||||||
|
import { feileGet } from '@/api/file';
|
||||||
|
|
||||||
|
import { BU_DOU_CONFIG } from '@/config';
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
value: boolean;
|
||||||
|
title: string;
|
||||||
|
type: 'add' | 'edit';
|
||||||
|
data: object;
|
||||||
|
}
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const props = withDefaults(defineProps<IProps>(), {
|
||||||
|
value: false,
|
||||||
|
title: '新增轮播',
|
||||||
|
type: 'add'
|
||||||
|
});
|
||||||
|
|
||||||
|
const content = ref('');
|
||||||
|
const loaging = ref<boolean>(false);
|
||||||
|
const formData = ref({
|
||||||
|
cover: '',
|
||||||
|
title: '',
|
||||||
|
description: '',
|
||||||
|
route: '',
|
||||||
|
jump_type: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: 'update:value', item: boolean): void;
|
||||||
|
(e: 'ok', item: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(n, _o) => {
|
||||||
|
if (n && props.type === 'edit') {
|
||||||
|
formData.value = props.data as any;
|
||||||
|
}
|
||||||
|
if (!n) {
|
||||||
|
formData.value = {
|
||||||
|
cover: '',
|
||||||
|
title: '',
|
||||||
|
description: '',
|
||||||
|
route: '',
|
||||||
|
jump_type: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传图片
|
||||||
|
*/
|
||||||
|
const headers = {
|
||||||
|
token: userStore.token
|
||||||
|
};
|
||||||
|
const actionURL = ref('');
|
||||||
|
// 图片上传前获取上传地址
|
||||||
|
const beforeUploadFile = async (rawFile: any) => {
|
||||||
|
const fileData = {
|
||||||
|
path: `/${rawFile.uid}/${rawFile.name}`,
|
||||||
|
type: 'report'
|
||||||
|
};
|
||||||
|
const res = (await feileGet(fileData)) as any;
|
||||||
|
if (res.url) {
|
||||||
|
actionURL.value = res.url;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 图片上传成功获取地址
|
||||||
|
const onFileSuccess = (response: any, _uploadFile: any) => {
|
||||||
|
formData.value.cover = response.path;
|
||||||
|
};
|
||||||
|
// 取消
|
||||||
|
const onClose = () => {
|
||||||
|
emits('update:value', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增轮播
|
||||||
|
const addBanner = () => {
|
||||||
|
loaging.value = true;
|
||||||
|
bannerPost(formData.value)
|
||||||
|
.then((res: any) => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (res.status == 200) {
|
||||||
|
ElMessage.success('新增成功!');
|
||||||
|
content.value = '';
|
||||||
|
onClose();
|
||||||
|
emits('ok', true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (err.status == 400) {
|
||||||
|
ElMessage.error(err.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑轮播
|
||||||
|
const editBanner = () => {
|
||||||
|
loaging.value = true;
|
||||||
|
const banner_no = (props.data as any).banner_no;
|
||||||
|
bannerPut(formData.value, banner_no)
|
||||||
|
.then((res: any) => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (res.status == 200) {
|
||||||
|
ElMessage.success('编辑成功!');
|
||||||
|
content.value = '';
|
||||||
|
onClose();
|
||||||
|
emits('ok', true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (err.status == 400) {
|
||||||
|
ElMessage.error(err.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 发送
|
||||||
|
const onConfirm = () => {
|
||||||
|
if (props.type === 'add') {
|
||||||
|
addBanner();
|
||||||
|
}
|
||||||
|
if (props.type === 'edit') {
|
||||||
|
editBanner();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.bd-upload {
|
||||||
|
::v-deep(.el-upload--picture-card) {
|
||||||
|
height: 78px;
|
||||||
|
width: 78px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
height: 78px;
|
||||||
|
width: 78px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
133
src/pages/workplace/configuration/components/CategoryDialog.vue
Normal file
133
src/pages/workplace/configuration/components/CategoryDialog.vue
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:model-value="value"
|
||||||
|
:width="400"
|
||||||
|
:align-center="true"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
:draggable="true"
|
||||||
|
:z-index="99"
|
||||||
|
title="新增分类"
|
||||||
|
@close="onClose"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<el-input v-model="content" placeholder="请输入分类" />
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<el-space>
|
||||||
|
<el-button @click="onClose">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="loaging" @click="onSend">保存</el-button>
|
||||||
|
</el-space>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" name="CategoryDialog" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
// API 接口
|
||||||
|
import { categoryPost, categoryPut } from '@/api/workplace/category';
|
||||||
|
interface IProps {
|
||||||
|
value: boolean;
|
||||||
|
type: 'add' | 'edit';
|
||||||
|
data: {
|
||||||
|
category_no?: string;
|
||||||
|
name?: string;
|
||||||
|
sort_num?: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const props = withDefaults(defineProps<IProps>(), {
|
||||||
|
value: false,
|
||||||
|
title: '新增分类',
|
||||||
|
type: 'add'
|
||||||
|
});
|
||||||
|
|
||||||
|
const content = ref('');
|
||||||
|
const loaging = ref<boolean>(false);
|
||||||
|
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: 'update:value', item: boolean): void;
|
||||||
|
(e: 'ok', item: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(n, _o) => {
|
||||||
|
console.log(props.value);
|
||||||
|
props.value = n;
|
||||||
|
if (n && props.type == 'edit') {
|
||||||
|
content.value = props.data?.name || '';
|
||||||
|
}
|
||||||
|
if (!n) {
|
||||||
|
content.value = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// 取消
|
||||||
|
const onClose = () => {
|
||||||
|
emits('update:value', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增分类
|
||||||
|
const addCategor = () => {
|
||||||
|
const fromData = {
|
||||||
|
name: content.value
|
||||||
|
};
|
||||||
|
loaging.value = true;
|
||||||
|
categoryPost(fromData)
|
||||||
|
.then((res: any) => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (res.status == 200) {
|
||||||
|
ElMessage.success('编辑分类成功!');
|
||||||
|
content.value = '';
|
||||||
|
onClose();
|
||||||
|
emits('ok', true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (err.status == 400) {
|
||||||
|
ElMessage.error(err.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 编辑分类
|
||||||
|
const editCategor = () => {
|
||||||
|
const fromData = {
|
||||||
|
name: content.value
|
||||||
|
};
|
||||||
|
loaging.value = true;
|
||||||
|
const category_no = (props.data as any).category_no;
|
||||||
|
categoryPut(fromData, category_no)
|
||||||
|
.then((res: any) => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (res.status == 200) {
|
||||||
|
ElMessage.success('编辑分类成功!');
|
||||||
|
content.value = '';
|
||||||
|
onClose();
|
||||||
|
emits('ok', true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (err.status == 400) {
|
||||||
|
ElMessage.error(err.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 保存
|
||||||
|
const onSend = () => {
|
||||||
|
if (!content.value) {
|
||||||
|
return ElMessage.info('请输入分类!');
|
||||||
|
}
|
||||||
|
// 新增
|
||||||
|
if (props.type === 'add') {
|
||||||
|
addCategor();
|
||||||
|
}
|
||||||
|
// 编辑
|
||||||
|
if (props.type === 'edit') {
|
||||||
|
editCategor();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
447
src/pages/workplace/configuration/components/CustomGroup.vue
Normal file
447
src/pages/workplace/configuration/components/CustomGroup.vue
Normal file
@ -0,0 +1,447 @@
|
|||||||
|
<template>
|
||||||
|
<bd-page class="flex !p-0">
|
||||||
|
<!-- S 左侧分类 -->
|
||||||
|
<div class="bd-sort min-w-200px max-w-200px h-full box-border flex flex-col">
|
||||||
|
<div class="h-50px pl-12px pr-12px box-border flex items-center justify-between bd-title">
|
||||||
|
<div class="bd-title-left font-500 text-14px">分组</div>
|
||||||
|
<div class="flex items-center h-50px">
|
||||||
|
<i-bd-add :size="22" class="cursor-pointer" @click="onCategoryAdd" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="m-12px">
|
||||||
|
<el-input v-model="keyword" placeholder="搜索分类/按回车键搜索" clearable />
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 overflow-hidden">
|
||||||
|
<el-scrollbar>
|
||||||
|
<div class="tree-warp p-12px pt-0">
|
||||||
|
<div
|
||||||
|
v-for="item in dataTree"
|
||||||
|
:key="item.category_no"
|
||||||
|
class="bd-tree-item"
|
||||||
|
:class="{ 'bd-tree-activate': item.category_no === optTree }"
|
||||||
|
@click="onOptTreeClick(item.category_no)"
|
||||||
|
>
|
||||||
|
<div class="mr-4px">
|
||||||
|
<i-bd-drag class="bd-drag cursor-pointer" size="14" />
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 text">{{ item.name }}</div>
|
||||||
|
<div class="bd-opt">
|
||||||
|
<i-bd-editor :size="16" class="cursor-pointer pr-4px" @click.stop="onCategoryEdit(item)" />
|
||||||
|
<i-bd-delete :size="16" class="cursor-pointer" @click.stop="onCategoryDelete(item)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- E 左侧分类 -->
|
||||||
|
|
||||||
|
<!-- S 右侧 表格 -->
|
||||||
|
<div class="flex-1 h-full flex flex-col">
|
||||||
|
<div class="h-50px pl-12px pr-12px box-border flex items-center justify-between bd-title">
|
||||||
|
<div class="bd-title-left"></div>
|
||||||
|
<div class="flex items-center h-50px">
|
||||||
|
<el-form inline>
|
||||||
|
<el-form-item class="mb-0 !mr-0">
|
||||||
|
<el-button type="primary" @click="appDialogValue = true">新增应用</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 表格 -->
|
||||||
|
<div class="flex-1 overflow-hidden p-12px">
|
||||||
|
<el-table v-loading="loadTable" :data="tableData" row-key="app_id" :border="true" style="width: 100%; height: 100%">
|
||||||
|
<el-table-column type="index" :width="42" :align="'center'" :fixed="'left'">
|
||||||
|
<template #header>
|
||||||
|
<i-bd-drag class="cursor-pointer" size="16" />
|
||||||
|
</template>
|
||||||
|
<template #default>
|
||||||
|
<i-bd-drag class="bd-drag cursor-pointer" size="16" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column v-for="item in column" v-bind="item" :key="item.prop">
|
||||||
|
<template #default="scope">
|
||||||
|
<template v-if="item.render">
|
||||||
|
<component :is="item.render" :row="scope.row"> </component>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="item.formatter">
|
||||||
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- E 右侧 表格 -->
|
||||||
|
|
||||||
|
<!-- 新增分类 -->
|
||||||
|
<CategoryDialog
|
||||||
|
v-model:value="categoryValue"
|
||||||
|
:type="categoryType"
|
||||||
|
:title="categoryTitle"
|
||||||
|
:data="categoryData"
|
||||||
|
@ok="onCategoryOk"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 添加应用 -->
|
||||||
|
<AppDialog v-model:value="appDialogValue" :data="appDialogData" @ok="onAppDialogOk" />
|
||||||
|
</bd-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="tsx" name="CustomGroup" setup>
|
||||||
|
import { ElButton, ElSpace, ElImage, ElMessageBox, ElMessage } from 'element-plus';
|
||||||
|
import Sortable from 'sortablejs';
|
||||||
|
import CategoryDialog from './CategoryDialog.vue';
|
||||||
|
import AppDialog from './AppDialog.vue';
|
||||||
|
import { BU_DOU_CONFIG } from '@/config';
|
||||||
|
|
||||||
|
// API接口
|
||||||
|
import {
|
||||||
|
categoryGet,
|
||||||
|
categoryDelete,
|
||||||
|
categoryReorderPut,
|
||||||
|
categoryAppGet,
|
||||||
|
categoryAppDelete,
|
||||||
|
categorysAppsReorderPut
|
||||||
|
} from '@/api/workplace/category';
|
||||||
|
|
||||||
|
interface Tree {
|
||||||
|
category_no: string;
|
||||||
|
name: string;
|
||||||
|
sort_num: number;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 左侧分类
|
||||||
|
*/
|
||||||
|
const dataTree = ref<Tree[]>([]);
|
||||||
|
const optTree = ref('');
|
||||||
|
const keyword = ref('');
|
||||||
|
// 获取分类
|
||||||
|
const getCategoryData = () => {
|
||||||
|
categoryGet().then((res: any) => {
|
||||||
|
if (res.length > 0) {
|
||||||
|
dataTree.value = res;
|
||||||
|
if (!optTree.value) {
|
||||||
|
optTree.value = res[0].category_no;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选中
|
||||||
|
const onOptTreeClick = (no: string) => {
|
||||||
|
optTree.value = no;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 确定添加应用
|
||||||
|
const onCategoryOk = () => {
|
||||||
|
getCategoryData();
|
||||||
|
};
|
||||||
|
// 分类排序
|
||||||
|
const categoryReorder = (newIndex: string, oldIndex: string) => {
|
||||||
|
const fromData = {
|
||||||
|
category_nos: [newIndex, oldIndex]
|
||||||
|
};
|
||||||
|
categoryReorderPut(fromData).then(res => {
|
||||||
|
if (res.status == 200) {
|
||||||
|
getCategoryData();
|
||||||
|
ElMessage({
|
||||||
|
type: 'success',
|
||||||
|
message: `分类排序成功`
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ElMessage({
|
||||||
|
type: 'info',
|
||||||
|
message: '分类排序失败!'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分类拖拽排序
|
||||||
|
const treesDrop = () => {
|
||||||
|
Sortable.create(document.querySelector('.tree-warp') as HTMLElement, {
|
||||||
|
handle: '.bd-drag',
|
||||||
|
animation: 300,
|
||||||
|
onEnd({ newIndex, oldIndex }: any) {
|
||||||
|
const treesList = [...dataTree.value];
|
||||||
|
const currRow = treesList.splice(oldIndex as number, 1)[0];
|
||||||
|
treesList.splice(newIndex as number, 0, currRow);
|
||||||
|
if (oldIndex > newIndex) {
|
||||||
|
// 向上排序
|
||||||
|
categoryReorder(treesList[newIndex].category_no, treesList[oldIndex].category_no);
|
||||||
|
} else {
|
||||||
|
// 向下排序
|
||||||
|
categoryReorder(treesList[oldIndex].category_no, treesList[newIndex].category_no);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const categoryValue = ref(false);
|
||||||
|
const categoryTitle = ref('新增分类');
|
||||||
|
const categoryType = ref<'add' | 'edit'>('add');
|
||||||
|
const categoryData = ref({});
|
||||||
|
|
||||||
|
// 分类新增
|
||||||
|
const onCategoryAdd = () => {
|
||||||
|
categoryValue.value = true;
|
||||||
|
categoryTitle.value = '新增分类';
|
||||||
|
categoryType.value = 'add';
|
||||||
|
categoryData.value = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分类编辑
|
||||||
|
const onCategoryEdit = (item: any) => {
|
||||||
|
console.log(item);
|
||||||
|
categoryValue.value = true;
|
||||||
|
categoryTitle.value = '编辑分类';
|
||||||
|
categoryType.value = 'edit';
|
||||||
|
categoryData.value = { ...item };
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分类删除
|
||||||
|
const onCategoryDelete = (item: any) => {
|
||||||
|
ElMessageBox.confirm(`确定要对该分类吗?`, `操作提示`, {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
closeOnClickModal: false,
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
categoryDelete(item.category_no)
|
||||||
|
.then((_res: any) => {
|
||||||
|
getCategoryData();
|
||||||
|
ElMessage({
|
||||||
|
type: 'success',
|
||||||
|
message: `轮播删除成功!`
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
if (err.status == 400) {
|
||||||
|
ElMessage.error(err.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
ElMessage({
|
||||||
|
type: 'info',
|
||||||
|
message: '取消成功!'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加应用
|
||||||
|
*/
|
||||||
|
const appDialogValue = ref(false);
|
||||||
|
const appDialogData = ref({
|
||||||
|
category_no: ''
|
||||||
|
});
|
||||||
|
watch(
|
||||||
|
() => optTree.value,
|
||||||
|
() => {
|
||||||
|
appDialogData.value = {
|
||||||
|
category_no: optTree.value
|
||||||
|
};
|
||||||
|
queryFrom.category_no = optTree.value;
|
||||||
|
getTableList();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// 确定添加应用
|
||||||
|
const onAppDialogOk = () => {
|
||||||
|
getTableList();
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 表格
|
||||||
|
*/
|
||||||
|
const column = reactive<Column.ColumnOptions[]>([
|
||||||
|
{
|
||||||
|
prop: 'icon',
|
||||||
|
label: '应用LOGO',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
render: (scope: any) => {
|
||||||
|
let img_url = '';
|
||||||
|
if (scope.row['icon']) {
|
||||||
|
img_url = `${BU_DOU_CONFIG.APP_URL}${scope.row.icon}`;
|
||||||
|
}
|
||||||
|
return <ElImage src={img_url} fit={'scale-down'} class={'w-60px h-60px'} />;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'name',
|
||||||
|
label: '应用名称',
|
||||||
|
width: 160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'app_id',
|
||||||
|
label: '应用APP ID',
|
||||||
|
width: 290
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'description',
|
||||||
|
label: '描述'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'operation',
|
||||||
|
label: '操作',
|
||||||
|
align: 'center',
|
||||||
|
width: 80,
|
||||||
|
render: (scope: any) => {
|
||||||
|
return (
|
||||||
|
<ElSpace>
|
||||||
|
<ElButton type="danger" onClick={() => onDelApply(scope.row)}>
|
||||||
|
删除
|
||||||
|
</ElButton>
|
||||||
|
</ElSpace>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
const tableData = ref<any[]>([]);
|
||||||
|
const loadTable = ref<boolean>(false);
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const queryFrom = reactive({
|
||||||
|
category_no: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 搜索
|
||||||
|
const getTableList = () => {
|
||||||
|
loadTable.value = true;
|
||||||
|
categoryAppGet(queryFrom.category_no)
|
||||||
|
.then((res: any) => {
|
||||||
|
loadTable.value = false;
|
||||||
|
tableData.value = res;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loadTable.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 移除应用
|
||||||
|
const onDelApply = (item: any) => {
|
||||||
|
ElMessageBox.confirm(`确定要对该应用移除吗?`, `操作提示`, {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
closeOnClickModal: false,
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
categoryAppDelete(optTree.value, item.app_id)
|
||||||
|
.then((_res: any) => {
|
||||||
|
getTableList();
|
||||||
|
ElMessage({
|
||||||
|
type: 'success',
|
||||||
|
message: `应用移除成功!`
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
if (err.status == 400) {
|
||||||
|
ElMessage.error(err.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
ElMessage({
|
||||||
|
type: 'info',
|
||||||
|
message: '取消成功!'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const categorysAppsReorder = (new_app_id: string, old_app_id: string) => {
|
||||||
|
const fromData = {
|
||||||
|
app_ids: [new_app_id, old_app_id]
|
||||||
|
};
|
||||||
|
categorysAppsReorderPut(fromData, queryFrom.category_no).then(res => {
|
||||||
|
if (res.status == 200) {
|
||||||
|
getTableList();
|
||||||
|
ElMessage({
|
||||||
|
type: 'success',
|
||||||
|
message: `应用排序成功`
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ElMessage({
|
||||||
|
type: 'info',
|
||||||
|
message: '应用排序失败!'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// table 拖拽排序
|
||||||
|
const tableDrop = () => {
|
||||||
|
Sortable.create(document.querySelector('.el-table__body-wrapper tbody') as HTMLElement, {
|
||||||
|
handle: '.bd-drag',
|
||||||
|
animation: 300,
|
||||||
|
onEnd({ newIndex, oldIndex }: any) {
|
||||||
|
const tablesList = [...tableData.value];
|
||||||
|
const currRow = tablesList.splice(oldIndex as number, 1)[0];
|
||||||
|
tablesList.splice(newIndex as number, 0, currRow);
|
||||||
|
tableData.value = tablesList;
|
||||||
|
if (oldIndex > newIndex) {
|
||||||
|
// 向上排序
|
||||||
|
categorysAppsReorder(tablesList[newIndex].app_id, tablesList[oldIndex].app_id);
|
||||||
|
} else {
|
||||||
|
// 向下排序
|
||||||
|
categorysAppsReorder(tablesList[oldIndex].app_id, tablesList[newIndex].app_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 初始化数据
|
||||||
|
*/
|
||||||
|
onMounted(() => {
|
||||||
|
getCategoryData();
|
||||||
|
treesDrop();
|
||||||
|
tableDrop();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 分类
|
||||||
|
.bd-sort {
|
||||||
|
border-right: 1px solid var(--el-card-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-tree-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
height: 26px;
|
||||||
|
padding: 0 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
|
||||||
|
.bd-opt {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--el-menu-active-bg-color);
|
||||||
|
color: var(--el-menu-active-color);
|
||||||
|
.bd-opt {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-tree-activate {
|
||||||
|
background-color: var(--el-menu-active-bg-color);
|
||||||
|
.text {
|
||||||
|
color: var(--el-menu-active-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-title {
|
||||||
|
border-bottom: 1px solid var(--el-card-border-color);
|
||||||
|
}
|
||||||
|
</style>
|
161
src/pages/workplace/configuration/components/Recommend.vue
Normal file
161
src/pages/workplace/configuration/components/Recommend.vue
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
<template>
|
||||||
|
<bd-page class="flex-col !p-0">
|
||||||
|
<div class="flex-1 el-card border-none flex-col box-border overflow-hidden">
|
||||||
|
<div class="h-50px pl-12px pr-12px box-border flex items-center justify-between bd-title">
|
||||||
|
<div class="bd-title-left"></div>
|
||||||
|
<div class="flex items-center h-50px">
|
||||||
|
<el-form inline>
|
||||||
|
<el-form-item class="mb-0 !mr-16px">
|
||||||
|
<el-input v-model="queryFrom.keyword" placeholder="名称" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item class="mb-0 !mr-0">
|
||||||
|
<el-button type="primary">新增推荐应用</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex-1 overflow-hidden p-12px">
|
||||||
|
<el-table v-loading="loadTable" :data="tableData" :border="true" style="width: 100%; height: 100%">
|
||||||
|
<el-table-column type="index" :width="42" :align="'center'" :fixed="'left'">
|
||||||
|
<template #header>
|
||||||
|
<i-bd-drag class="cursor-pointer" size="16" />
|
||||||
|
</template>
|
||||||
|
<template #default>
|
||||||
|
<i-bd-drag class="bd-drag cursor-pointer" size="16" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column v-for="item in column" v-bind="item" :key="item.prop">
|
||||||
|
<template #default="scope">
|
||||||
|
<template v-if="item.render">
|
||||||
|
<component :is="item.render" :row="scope.row"> </component>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="item.formatter">
|
||||||
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="item.prop">
|
||||||
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<div class="bd-card-footer pl-12px pr-12px mb-12px flex items-center justify-between">
|
||||||
|
<div></div>
|
||||||
|
<el-pagination
|
||||||
|
v-model:current-page="queryFrom.page_index"
|
||||||
|
v-model:page-size="queryFrom.page_size"
|
||||||
|
:page-sizes="[15, 20, 30, 50, 100]"
|
||||||
|
:background="true"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="total"
|
||||||
|
@size-change="onSizeChange"
|
||||||
|
@current-change="onCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</bd-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="tsx" name="Recommend" setup>
|
||||||
|
import { ElButton, ElSpace, ElImage } from 'element-plus';
|
||||||
|
import Sortable from 'sortablejs';
|
||||||
|
import { BU_DOU_CONFIG } from '@/config';
|
||||||
|
/**
|
||||||
|
* 表格
|
||||||
|
*/
|
||||||
|
const column = reactive<Column.ColumnOptions[]>([
|
||||||
|
{
|
||||||
|
prop: 'icon',
|
||||||
|
label: '应用LOGO',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
render: (scope: any) => {
|
||||||
|
let img_url = '';
|
||||||
|
if (scope.row['icon']) {
|
||||||
|
img_url = `${BU_DOU_CONFIG.APP_URL}${scope.row.icon}`;
|
||||||
|
}
|
||||||
|
return <ElImage src={img_url} fit={'scale-down'} class={'w-60px h-60px'} />;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'name',
|
||||||
|
label: '应用名称',
|
||||||
|
width: 160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'app_id',
|
||||||
|
label: '应用APP ID',
|
||||||
|
width: 290
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'description',
|
||||||
|
label: '描述'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'operation',
|
||||||
|
label: '操作',
|
||||||
|
align: 'center',
|
||||||
|
render: (_scope: any) => {
|
||||||
|
return (
|
||||||
|
<ElSpace>
|
||||||
|
<ElButton type="primary">配置</ElButton>
|
||||||
|
</ElSpace>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
const tableData = ref<any[]>([]);
|
||||||
|
const loadTable = ref<boolean>(false);
|
||||||
|
// 分页
|
||||||
|
const total = ref(0);
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const queryFrom = reactive({
|
||||||
|
keyword: '',
|
||||||
|
page_size: 15,
|
||||||
|
page_index: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
// 搜索
|
||||||
|
const getTableList = () => {};
|
||||||
|
|
||||||
|
// 分页page-size
|
||||||
|
const onSizeChange = (size: number) => {
|
||||||
|
queryFrom.page_size = size;
|
||||||
|
getTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页page-size
|
||||||
|
const onCurrentChange = (current: number) => {
|
||||||
|
queryFrom.page_index = current;
|
||||||
|
getTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增版本
|
||||||
|
|
||||||
|
// table 拖拽排序
|
||||||
|
const tableDrop = () => {
|
||||||
|
Sortable.create(document.querySelector('.el-table__body-wrapper tbody') as HTMLElement, {
|
||||||
|
// draggable: '.bd-drag',
|
||||||
|
animation: 300,
|
||||||
|
onEnd({ newIndex, oldIndex }: any) {
|
||||||
|
const tablesList = [...tableData.value];
|
||||||
|
const currRow = tablesList.splice(oldIndex as number, 1)[0];
|
||||||
|
tablesList.splice(newIndex as number, 0, currRow);
|
||||||
|
tableData.value = tablesList;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
tableDrop();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 样式
|
||||||
|
.bd-title {
|
||||||
|
border-bottom: 1px solid var(--el-card-border-color);
|
||||||
|
}
|
||||||
|
</style>
|
41
src/pages/workplace/configuration/index.vue
Normal file
41
src/pages/workplace/configuration/index.vue
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<template>
|
||||||
|
<bd-page class="flex-col">
|
||||||
|
<div class="flex-1 el-card border-none flex-col box-border overflow-hidden">
|
||||||
|
<el-tabs v-model="activeName" class="bd-tabs">
|
||||||
|
<el-tab-pane v-for="item in tabsData" :key="item.name" :label="item.label" :name="item.name">
|
||||||
|
<component :is="item.render" v-if="item.name === activeName" />
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</div>
|
||||||
|
</bd-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<route lang="yaml">
|
||||||
|
meta:
|
||||||
|
title: 工作台设置
|
||||||
|
isAffix: false
|
||||||
|
</route>
|
||||||
|
|
||||||
|
<script lang="tsx" setup>
|
||||||
|
import Banner from './components/Banner.vue';
|
||||||
|
import CustomGroup from './components/CustomGroup.vue';
|
||||||
|
|
||||||
|
const activeName = ref('banner');
|
||||||
|
|
||||||
|
const tabsData = reactive([
|
||||||
|
{
|
||||||
|
name: 'banner',
|
||||||
|
label: '轮播',
|
||||||
|
render: () => {
|
||||||
|
return <Banner />;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'custom-group',
|
||||||
|
label: '自定义分组',
|
||||||
|
render: () => {
|
||||||
|
return <CustomGroup />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
</script>
|
230
src/pages/workplace/manage/components/Apply.vue
Normal file
230
src/pages/workplace/manage/components/Apply.vue
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:model-value="value"
|
||||||
|
:width="600"
|
||||||
|
:align-center="true"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
:draggable="true"
|
||||||
|
:z-index="99"
|
||||||
|
:title="title"
|
||||||
|
@close="onClose"
|
||||||
|
>
|
||||||
|
<el-form :model="formData" label-width="96px">
|
||||||
|
<el-form-item label="应用名称">
|
||||||
|
<el-input v-model="formData.name" placeholder="请输入应用名称" maxlength="10" show-word-limit />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="应用图标">
|
||||||
|
<el-upload
|
||||||
|
ref="upload"
|
||||||
|
class="bd-upload"
|
||||||
|
:action="actionURL"
|
||||||
|
list-type="picture-card"
|
||||||
|
:show-file-list="false"
|
||||||
|
:headers="headers"
|
||||||
|
:before-upload="beforeUploadFile"
|
||||||
|
:on-success="onFileSuccess"
|
||||||
|
>
|
||||||
|
<img v-if="formData.icon" :src="`${BU_DOU_CONFIG.APP_URL}${formData.icon}`" class="avatar" />
|
||||||
|
<el-icon v-else><Plus /></el-icon>
|
||||||
|
</el-upload>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="打开方式">
|
||||||
|
<el-radio-group v-model="formData.jump_type">
|
||||||
|
<el-radio :label="0">网页</el-radio>
|
||||||
|
<el-radio :label="1">APP</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="网页地址">
|
||||||
|
<el-input v-model="formData.web_route" placeholder="请输入网页地址" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="APP地址">
|
||||||
|
<el-input v-model="formData.app_route" placeholder="请输入APP地址" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="付款">
|
||||||
|
<el-radio-group v-model="formData.is_paid_app">
|
||||||
|
<el-radio :label="0">免费</el-radio>
|
||||||
|
<el-radio :label="1">付费</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="应用描述">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.description"
|
||||||
|
type="textarea"
|
||||||
|
:autosize="{ minRows: 6, maxRows: 8 }"
|
||||||
|
placeholder="请输入应用描述"
|
||||||
|
show-word-limit
|
||||||
|
maxlength="500"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-space>
|
||||||
|
<el-button @click="onClose">取消</el-button>
|
||||||
|
<el-button type="primary" :loading="loaging" @click="onConfirm">保存</el-button>
|
||||||
|
</el-space>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" name="Apply" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { Plus } from '@element-plus/icons-vue';
|
||||||
|
import { useUserStore } from '@/stores/modules/user';
|
||||||
|
// API 接口
|
||||||
|
import { appPost, appPut } from '@/api/workplace/app';
|
||||||
|
import { feileGet } from '@/api/file';
|
||||||
|
|
||||||
|
import { BU_DOU_CONFIG } from '@/config';
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
value: boolean;
|
||||||
|
title: string;
|
||||||
|
type: 'add' | 'edit';
|
||||||
|
data: object;
|
||||||
|
}
|
||||||
|
const props = withDefaults(defineProps<IProps>(), {
|
||||||
|
value: false,
|
||||||
|
title: '新增应用',
|
||||||
|
type: 'add'
|
||||||
|
});
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
const content = ref('');
|
||||||
|
const loaging = ref<boolean>(false);
|
||||||
|
const formData = ref({
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
jump_type: 0,
|
||||||
|
description: '',
|
||||||
|
app_route: '',
|
||||||
|
web_route: '',
|
||||||
|
is_paid_app: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: 'update:value', item: boolean): void;
|
||||||
|
(e: 'ok', item: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.value,
|
||||||
|
(n, _o) => {
|
||||||
|
props.value = n;
|
||||||
|
if (n && props.type == 'edit') {
|
||||||
|
formData.value = props.data as any;
|
||||||
|
}
|
||||||
|
if (!n) {
|
||||||
|
formData.value = {
|
||||||
|
icon: '',
|
||||||
|
name: '',
|
||||||
|
jump_type: 0,
|
||||||
|
description: '',
|
||||||
|
app_route: '',
|
||||||
|
web_route: '',
|
||||||
|
is_paid_app: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传图片
|
||||||
|
*/
|
||||||
|
const headers = {
|
||||||
|
token: userStore.token
|
||||||
|
};
|
||||||
|
const actionURL = ref('');
|
||||||
|
// 图片上传前获取上传地址
|
||||||
|
const beforeUploadFile = async (rawFile: any) => {
|
||||||
|
const fileData = {
|
||||||
|
path: `/${rawFile.uid}/${rawFile.name}`,
|
||||||
|
type: 'report'
|
||||||
|
};
|
||||||
|
const res = (await feileGet(fileData)) as any;
|
||||||
|
if (res.url) {
|
||||||
|
actionURL.value = res.url;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 图片上传成功获取地址
|
||||||
|
const onFileSuccess = (response: any, _uploadFile: any) => {
|
||||||
|
formData.value.icon = response.path;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消
|
||||||
|
const onClose = () => {
|
||||||
|
emits('update:value', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增应用
|
||||||
|
const addApp = () => {
|
||||||
|
loaging.value = true;
|
||||||
|
appPost(formData.value)
|
||||||
|
.then((res: any) => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (res.status == 200) {
|
||||||
|
ElMessage.success('新增成功!');
|
||||||
|
content.value = '';
|
||||||
|
onClose();
|
||||||
|
emits('ok', true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (err.status == 400) {
|
||||||
|
ElMessage.error(err.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
const editApp = () => {
|
||||||
|
loaging.value = true;
|
||||||
|
const app_id = (props.data as any).app_id;
|
||||||
|
appPut(formData.value, app_id)
|
||||||
|
.then((res: any) => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (res.status == 200) {
|
||||||
|
ElMessage.success('编辑成功!');
|
||||||
|
content.value = '';
|
||||||
|
onClose();
|
||||||
|
emits('ok', true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
loaging.value = false;
|
||||||
|
if (err.status == 400) {
|
||||||
|
ElMessage.error(err.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 发送
|
||||||
|
const onConfirm = () => {
|
||||||
|
// 新增
|
||||||
|
if (props.type === 'add') {
|
||||||
|
addApp();
|
||||||
|
}
|
||||||
|
// 编辑
|
||||||
|
if (props.type === 'edit') {
|
||||||
|
editApp();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.bd-upload {
|
||||||
|
::v-deep(.el-upload--picture-card) {
|
||||||
|
height: 78px;
|
||||||
|
width: 78px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
height: 78px;
|
||||||
|
width: 78px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
256
src/pages/workplace/manage/index.vue
Normal file
256
src/pages/workplace/manage/index.vue
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
<template>
|
||||||
|
<bd-page class="flex-col">
|
||||||
|
<div class="flex-1 el-card border-none flex-col box-border overflow-hidden">
|
||||||
|
<div class="h-50px pl-12px pr-12px box-border flex items-center justify-between bd-title">
|
||||||
|
<div class="bd-title-left">
|
||||||
|
<p class="m-0 font-600">应用管理</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center h-50px">
|
||||||
|
<el-form inline>
|
||||||
|
<el-form-item class="mb-0 !mr-16px">
|
||||||
|
<el-input v-model="queryFrom.keyword" placeholder="应用名称" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item class="mb-0 !mr-16px">
|
||||||
|
<el-button type="primary" @click="getTableList">查询</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item class="mb-0 !mr-0">
|
||||||
|
<el-button type="primary" @click="onAppVersionAdd">新增应用</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex-1 overflow-hidden p-12px">
|
||||||
|
<el-table v-loading="loadTable" :data="tableData" :border="true" style="width: 100%; height: 100%">
|
||||||
|
<el-table-column type="index" :width="42" :align="'center'" :fixed="'left'">
|
||||||
|
<template #header>
|
||||||
|
<i-bd-setting class="cursor-pointer" size="16" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column v-for="item in column" v-bind="item" :key="item.prop">
|
||||||
|
<template #default="scope">
|
||||||
|
<template v-if="item.render">
|
||||||
|
<component :is="item.render" :row="scope.row"> </component>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="item.formatter">
|
||||||
|
<slot :name="item.prop" :row="scope.row">{{ item.formatter(scope.row) }}</slot>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="item.prop">
|
||||||
|
<slot :name="item.prop" :row="scope.row">{{ scope.row[item.prop!] }}</slot>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<div class="bd-card-footer pl-12px pr-12px mb-12px flex items-center justify-between">
|
||||||
|
<div></div>
|
||||||
|
<el-pagination
|
||||||
|
v-model:current-page="queryFrom.page_index"
|
||||||
|
v-model:page-size="queryFrom.page_size"
|
||||||
|
:page-sizes="[15, 20, 30, 50, 100]"
|
||||||
|
:background="true"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="total"
|
||||||
|
@size-change="onSizeChange"
|
||||||
|
@current-change="onCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 应用 -->
|
||||||
|
<Apply v-model:value="applyAddValue" :type="applyType" :title="applyTitle" :data="applyData" @ok="onApplyClick" />
|
||||||
|
</bd-page>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<route lang="yaml">
|
||||||
|
meta:
|
||||||
|
title: 应用管理
|
||||||
|
isAffix: false
|
||||||
|
</route>
|
||||||
|
|
||||||
|
<script lang="tsx" setup>
|
||||||
|
import { ElButton, ElMessageBox, ElMessage, ElSpace } from 'element-plus';
|
||||||
|
import { Fancybox } from '@fancyapps/ui';
|
||||||
|
import Apply from './components/Apply.vue';
|
||||||
|
import { BU_DOU_CONFIG } from '@/config';
|
||||||
|
|
||||||
|
// API接口
|
||||||
|
import { appGet, appDelete } from '@/api/workplace/app';
|
||||||
|
/**
|
||||||
|
* 新增应用
|
||||||
|
*/
|
||||||
|
// 新增版本
|
||||||
|
const applyAddValue = ref<boolean>(false);
|
||||||
|
const applyTitle = ref('新增应用');
|
||||||
|
const applyType = ref<'add' | 'edit'>('add');
|
||||||
|
const onAppVersionAdd = () => {
|
||||||
|
applyAddValue.value = true;
|
||||||
|
applyTitle.value = '新增应用';
|
||||||
|
applyType.value = 'add';
|
||||||
|
};
|
||||||
|
|
||||||
|
// 确定应用
|
||||||
|
const onApplyClick = () => {
|
||||||
|
getTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const previewPicture = (url: string) => {
|
||||||
|
const imgList = [];
|
||||||
|
imgList.push({ src: url });
|
||||||
|
Fancybox.show(imgList, {
|
||||||
|
Toolbar: {
|
||||||
|
display: {
|
||||||
|
left: ['infobar'],
|
||||||
|
middle: ['zoomIn', 'zoomOut', 'toggle1to1', 'rotateCCW', 'rotateCW', 'flipX', 'flipY'],
|
||||||
|
right: ['slideshow', 'thumbs', 'close']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格
|
||||||
|
*/
|
||||||
|
const column = reactive<Column.ColumnOptions[]>([
|
||||||
|
{
|
||||||
|
prop: 'icon',
|
||||||
|
label: '应用LOGO',
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
render: (scope: any) => {
|
||||||
|
let img_url = '';
|
||||||
|
if (scope.row['icon']) {
|
||||||
|
img_url = `${BU_DOU_CONFIG.APP_URL}${scope.row.icon}`;
|
||||||
|
}
|
||||||
|
return <img src={img_url} class={'w-60px h-60px cursor-pointer'} onClick={() => previewPicture(img_url)} />;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'name',
|
||||||
|
label: '应用名称',
|
||||||
|
width: 160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'app_id',
|
||||||
|
label: '应用APP ID',
|
||||||
|
width: 290
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'status',
|
||||||
|
label: '应用状态',
|
||||||
|
width: 100,
|
||||||
|
formatter(row: any) {
|
||||||
|
return row.status === 1 ? '开启' : '关闭';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'description',
|
||||||
|
label: '应用描述'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'operation',
|
||||||
|
label: '操作',
|
||||||
|
width: 150,
|
||||||
|
align: 'center',
|
||||||
|
render: (scope: any) => {
|
||||||
|
return (
|
||||||
|
<ElSpace>
|
||||||
|
<ElButton type="primary" onClick={() => oApplyEidt(scope.row)}>
|
||||||
|
编辑
|
||||||
|
</ElButton>
|
||||||
|
<ElButton type="danger" onClick={() => onDelApply(scope.row)}>
|
||||||
|
删除
|
||||||
|
</ElButton>
|
||||||
|
</ElSpace>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
const tableData = ref<any[]>([]);
|
||||||
|
const loadTable = ref<boolean>(false);
|
||||||
|
// 分页
|
||||||
|
const total = ref(0);
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
const queryFrom = reactive({
|
||||||
|
keyword: '',
|
||||||
|
page_size: 15,
|
||||||
|
page_index: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
// 搜索
|
||||||
|
const getTableList = () => {
|
||||||
|
loadTable.value = true;
|
||||||
|
appGet(queryFrom)
|
||||||
|
.then((res: any) => {
|
||||||
|
loadTable.value = false;
|
||||||
|
tableData.value = res.list || [];
|
||||||
|
total.value = res.count || 0;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
loadTable.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 编辑
|
||||||
|
const applyData = ref({});
|
||||||
|
const oApplyEidt = (item: any) => {
|
||||||
|
applyTitle.value = `编辑${item.name}`;
|
||||||
|
applyData.value = item;
|
||||||
|
applyType.value = 'edit';
|
||||||
|
applyAddValue.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除应用
|
||||||
|
const onDelApply = (item: any) => {
|
||||||
|
ElMessageBox.confirm(`确定要对该应用删除吗?`, `操作提示`, {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
closeOnClickModal: false,
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
appDelete(item.app_id)
|
||||||
|
.then((_res: any) => {
|
||||||
|
getTableList();
|
||||||
|
ElMessage({
|
||||||
|
type: 'success',
|
||||||
|
message: `应用删除成功!`
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
if (err.status == 400) {
|
||||||
|
ElMessage.error(err.msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
ElMessage({
|
||||||
|
type: 'info',
|
||||||
|
message: '取消成功!'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页page-size
|
||||||
|
const onSizeChange = (size: number) => {
|
||||||
|
queryFrom.page_size = size;
|
||||||
|
getTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页page-size
|
||||||
|
const onCurrentChange = (current: number) => {
|
||||||
|
queryFrom.page_index = current;
|
||||||
|
getTableList();
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getTableList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 样式
|
||||||
|
.bd-title {
|
||||||
|
border-bottom: 1px solid var(--el-card-border-color);
|
||||||
|
}
|
||||||
|
</style>
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
/* 当前页面最大化 css */
|
/* 当前页面最大化 css */
|
||||||
.main-maximize {
|
.main-maximize {
|
||||||
|
|
||||||
.aside-split,
|
.aside-split,
|
||||||
.el-aside,
|
.el-aside,
|
||||||
.el-header,
|
.el-header,
|
||||||
@ -40,6 +41,7 @@
|
|||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-search {
|
.table-search {
|
||||||
padding: 18px 0 0 !important;
|
padding: 18px 0 0 !important;
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
@ -52,18 +54,22 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.text {
|
.text {
|
||||||
margin: 20px 0 30px;
|
margin: 20px 0 30px;
|
||||||
font-size: 23px;
|
font-size: 23px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: var(--el-text-color-regular);
|
color: var(--el-text-color-regular);
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions {
|
.el-descriptions {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 40px 0 0;
|
padding: 40px 0 0;
|
||||||
|
|
||||||
.el-descriptions__title {
|
.el-descriptions__title {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-descriptions__label {
|
.el-descriptions__label {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
@ -75,6 +81,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.table-box {
|
.table-box {
|
||||||
// 这里减去的是 treeFilter 组件宽度
|
// 这里减去的是 treeFilter 组件宽度
|
||||||
width: calc(100% - 230px);
|
width: calc(100% - 230px);
|
||||||
@ -94,8 +101,9 @@
|
|||||||
.table-search {
|
.table-search {
|
||||||
padding: 18px 18px 0;
|
padding: 18px 18px 0;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
|
||||||
.el-form {
|
.el-form {
|
||||||
.el-form-item__content > * {
|
.el-form-item__content>* {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +112,7 @@
|
|||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.operation {
|
.operation {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -117,9 +126,11 @@
|
|||||||
.header-button-lf {
|
.header-button-lf {
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-button-ri {
|
.header-button-ri {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-button {
|
.el-button {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
@ -133,6 +144,7 @@
|
|||||||
table {
|
table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-table__header th {
|
.el-table__header th {
|
||||||
height: 45px;
|
height: 45px;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
@ -140,16 +152,18 @@
|
|||||||
color: var(--el-text-color-primary);
|
color: var(--el-text-color-primary);
|
||||||
background: var(--el-fill-color-light);
|
background: var(--el-fill-color-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-table__row {
|
.el-table__row {
|
||||||
height: 45px;
|
height: 45px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
||||||
.el-table__placeholder {
|
.el-table__placeholder {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置 el-table 中 header 文字不换行,并省略
|
// 设置 el-table 中 header 文字不换行,并省略
|
||||||
.el-table__header .el-table__cell > .cell {
|
.el-table__header .el-table__cell>.cell {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +173,7 @@
|
|||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
.table-empty {
|
.table-empty {
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
}
|
}
|
||||||
@ -186,16 +201,19 @@
|
|||||||
height: 40px !important;
|
height: 40px !important;
|
||||||
font-size: 14px !important;
|
font-size: 14px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-table__row {
|
.el-table__row {
|
||||||
height: 40px !important;
|
height: 40px !important;
|
||||||
font-size: 13px !important;
|
font-size: 13px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-table--large {
|
.el-table--large {
|
||||||
.el-table__header th {
|
.el-table__header th {
|
||||||
height: 50px !important;
|
height: 50px !important;
|
||||||
font-size: 16px !important;
|
font-size: 16px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-table__row {
|
.el-table__row {
|
||||||
height: 50px !important;
|
height: 50px !important;
|
||||||
font-size: 15px !important;
|
font-size: 15px !important;
|
||||||
@ -208,12 +226,14 @@
|
|||||||
padding: 16px 20px;
|
padding: 16px 20px;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||||
|
|
||||||
span {
|
span {
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
line-height: 17px;
|
line-height: 17px;
|
||||||
color: var(--el-text-color-primary) !important;
|
color: var(--el-text-color-primary) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-drawer__footer {
|
.el-drawer__footer {
|
||||||
border-top: 1px solid var(--el-border-color-lighter);
|
border-top: 1px solid var(--el-border-color-lighter);
|
||||||
}
|
}
|
||||||
@ -227,8 +247,10 @@
|
|||||||
.drawer-multiColumn-form {
|
.drawer-multiColumn-form {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
.el-form-item {
|
.el-form-item {
|
||||||
width: 47%;
|
width: 47%;
|
||||||
|
|
||||||
&:nth-child(2n-1) {
|
&:nth-child(2n-1) {
|
||||||
margin-right: 5%;
|
margin-right: 5%;
|
||||||
}
|
}
|
||||||
@ -242,6 +264,7 @@
|
|||||||
padding: 15px 20px;
|
padding: 15px 20px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border-bottom: 1px solid var(--el-border-color-lighter);
|
border-bottom: 1px solid var(--el-border-color-lighter);
|
||||||
|
|
||||||
.el-dialog__title {
|
.el-dialog__title {
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
}
|
}
|
||||||
@ -258,12 +281,47 @@
|
|||||||
background: var(--el-fill-color-light);
|
background: var(--el-fill-color-light);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* el-menu-item */
|
/* el-menu-item */
|
||||||
.el-menu-item {
|
.el-menu-item {
|
||||||
height: 48px !important;
|
height: 48px !important;
|
||||||
line-height: 48px !important;
|
line-height: 48px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bu-button*/
|
/* bu-button*/
|
||||||
.bu-button:focus-visible {
|
.bu-button:focus-visible {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* bd-tabs */
|
||||||
|
.bd-tabs {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.el-tabs__header {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tabs__nav-wrap {
|
||||||
|
padding: 0 24px;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
height: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tabs__item {
|
||||||
|
padding: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tabs__content {
|
||||||
|
flex: 1;
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tab-pane {
|
||||||
|
flex: 1;
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
4
src/types/global.d.ts
vendored
4
src/types/global.d.ts
vendored
@ -80,8 +80,8 @@ type ObjToKeyValArray<T> = {
|
|||||||
}[keyof T];
|
}[keyof T];
|
||||||
declare namespace Column {
|
declare namespace Column {
|
||||||
interface ColumnOptions {
|
interface ColumnOptions {
|
||||||
prop: string;
|
prop?: string;
|
||||||
label: string;
|
label?: string;
|
||||||
type?: 'selection' | 'index' | 'expand';
|
type?: 'selection' | 'index' | 'expand';
|
||||||
fixed?: true | 'left' | 'right';
|
fixed?: true | 'left' | 'right';
|
||||||
width?: string | number;
|
width?: string | number;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user