Commit 22e164bd authored by hucy's avatar hucy

fix:导航tab优化

parent e0fc674c
...@@ -10,9 +10,9 @@ ...@@ -10,9 +10,9 @@
"dependencies": { "dependencies": {
"@antv/x6": "^1.32.11", "@antv/x6": "^1.32.11",
"@quasar/extras": "^1.0.0", "@quasar/extras": "^1.0.0",
"ag-grid-community": "^28.0.0", "ag-grid-community": "^28.2.1",
"ag-grid-enterprise": "^28.0.0", "ag-grid-enterprise": "^28.2.1",
"ag-grid-vue3": "^28.0.0", "ag-grid-vue3": "^28.2.1",
"animejs": "^3.2.1", "animejs": "^3.2.1",
"axios": "^0.27.2", "axios": "^0.27.2",
"core-js": "^3.6.5", "core-js": "^3.6.5",
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
}, },
"devDependencies": { "devDependencies": {
"@quasar/app-webpack": "^3.0.0", "@quasar/app-webpack": "^3.0.0",
"@quasar/quasar-app-extension-qmediaplayer": "^2.0.0-beta.6",
"@types/lodash-es": "^4.17.6", "@types/lodash-es": "^4.17.6",
"@types/node": "^12.20.21", "@types/node": "^12.20.21",
"@typescript-eslint/eslint-plugin": "^5.10.0", "@typescript-eslint/eslint-plugin": "^5.10.0",
...@@ -2428,6 +2429,37 @@ ...@@ -2428,6 +2429,37 @@
"url": "https://donate.quasar.dev" "url": "https://donate.quasar.dev"
} }
}, },
"node_modules/@quasar/quasar-app-extension-qmediaplayer": {
"version": "2.0.0-beta.6",
"resolved": "https://registry.npmjs.org/@quasar/quasar-app-extension-qmediaplayer/-/quasar-app-extension-qmediaplayer-2.0.0-beta.6.tgz",
"integrity": "sha512-Mrqqny92+/Kj5TuHzXLsbHF8j4Ltjuhwdq+tkkpx99Iw0zeE5lcFDTNzmiAllN8+W7h57FzDWiidvsh8dXPnDg==",
"dev": true,
"dependencies": {
"@quasar/quasar-ui-qmediaplayer": "^2.0.0-beta.6"
},
"engines": {
"node": ">= 10.0.0",
"npm": ">= 5.6.0",
"yarn": ">= 1.6.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/hawkeye64"
}
},
"node_modules/@quasar/quasar-ui-qmediaplayer": {
"version": "2.0.0-beta.6",
"resolved": "https://registry.npmjs.org/@quasar/quasar-ui-qmediaplayer/-/quasar-ui-qmediaplayer-2.0.0-beta.6.tgz",
"integrity": "sha512-j0Y6NCMkup/fjwpOT2kWPG+w3X1yVxmRaSHxQRtWLsWHjiSheaJLWKqZDJ9UarEKL8rtS/CUtadD+ENvcBEHHQ==",
"dev": true,
"dependencies": {
"@quasar/extras": "^1.13.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/hawkeye64"
}
},
"node_modules/@quasar/ssr-helpers": { "node_modules/@quasar/ssr-helpers": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/@quasar/ssr-helpers/-/ssr-helpers-2.2.0.tgz", "resolved": "https://registry.npmjs.org/@quasar/ssr-helpers/-/ssr-helpers-2.2.0.tgz",
...@@ -3252,23 +3284,21 @@ ...@@ -3252,23 +3284,21 @@
} }
}, },
"node_modules/ag-grid-community": { "node_modules/ag-grid-community": {
"version": "28.0.0", "version": "28.2.1",
"resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-28.0.0.tgz", "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-28.2.1.tgz",
"integrity": "sha512-ovatVo8iGbJZHQRY2ga92IXLSPiLq8zzKIHsli4DU073P/e334gGrk9aTjAD0N0qRie+iKCvkQiZFPo07Wzl1Q==", "integrity": "sha512-DMZh/xD/FqYP17qJ1M92PolTYe+hrKuEaf+A4h13O6qn2x/xZQrTRGW5DgnQLR/uLMe1XXZQPKR3UKgAlKo69A=="
"license": "MIT"
}, },
"node_modules/ag-grid-enterprise": { "node_modules/ag-grid-enterprise": {
"version": "28.0.0", "version": "28.2.1",
"resolved": "https://registry.npmjs.org/ag-grid-enterprise/-/ag-grid-enterprise-28.0.0.tgz", "resolved": "https://registry.npmjs.org/ag-grid-enterprise/-/ag-grid-enterprise-28.2.1.tgz",
"integrity": "sha512-bTyTU+Fc6aw8aXgbaIlsuDsQ9mPXjTOQpEQm3J6cg947iEhO6W/74VWh+MicYZaEKK2/wDkcchhVgDADUOpe+A==" "integrity": "sha512-FIqIiaMMO9m8eqfu64rZ7dOK8vQFqD+Dp9CTpSfjMtyUp4IoRE36c+mUpUGLX/bIix9LltpaUmr185nFM1Alrw=="
}, },
"node_modules/ag-grid-vue3": { "node_modules/ag-grid-vue3": {
"version": "28.0.0", "version": "28.2.1",
"resolved": "https://registry.npmjs.org/ag-grid-vue3/-/ag-grid-vue3-28.0.0.tgz", "resolved": "https://registry.npmjs.org/ag-grid-vue3/-/ag-grid-vue3-28.2.1.tgz",
"integrity": "sha512-qQQEuOiiJLkK1l4aHIo7PMG6iU7QHZHOMvYPnKDHjdEKvEU3NKuw6pJB4Ot7EdUnnqSBJOKx7/FMibHelerijw==", "integrity": "sha512-n7+l51zFCZm3SVT2pI0lVVwL8gsDPebqNLfEy4DS17OlV5IL7c1eNXRosv/QMu+YHOEMVcwFRWH380nIjVF/+w==",
"license": "MIT",
"dependencies": { "dependencies": {
"ag-grid-community": "~28.0.0", "ag-grid-community": "~28.2.1",
"vue": "^3.0.0" "vue": "^3.0.0"
} }
}, },
...@@ -13292,6 +13322,24 @@ ...@@ -13292,6 +13322,24 @@
"integrity": "sha512-p3JKgTjRlJ1YQXbqTw3Bsa4j0mQdt5dq+WfYvyb7MgKGdephHCKdR/kxA5PCTAmJanGJuDKqRdyGYX/hYN4KGw==", "integrity": "sha512-p3JKgTjRlJ1YQXbqTw3Bsa4j0mQdt5dq+WfYvyb7MgKGdephHCKdR/kxA5PCTAmJanGJuDKqRdyGYX/hYN4KGw==",
"dev": true "dev": true
}, },
"@quasar/quasar-app-extension-qmediaplayer": {
"version": "2.0.0-beta.6",
"resolved": "https://registry.npmjs.org/@quasar/quasar-app-extension-qmediaplayer/-/quasar-app-extension-qmediaplayer-2.0.0-beta.6.tgz",
"integrity": "sha512-Mrqqny92+/Kj5TuHzXLsbHF8j4Ltjuhwdq+tkkpx99Iw0zeE5lcFDTNzmiAllN8+W7h57FzDWiidvsh8dXPnDg==",
"dev": true,
"requires": {
"@quasar/quasar-ui-qmediaplayer": "^2.0.0-beta.6"
}
},
"@quasar/quasar-ui-qmediaplayer": {
"version": "2.0.0-beta.6",
"resolved": "https://registry.npmjs.org/@quasar/quasar-ui-qmediaplayer/-/quasar-ui-qmediaplayer-2.0.0-beta.6.tgz",
"integrity": "sha512-j0Y6NCMkup/fjwpOT2kWPG+w3X1yVxmRaSHxQRtWLsWHjiSheaJLWKqZDJ9UarEKL8rtS/CUtadD+ENvcBEHHQ==",
"dev": true,
"requires": {
"@quasar/extras": "^1.13.0"
}
},
"@quasar/ssr-helpers": { "@quasar/ssr-helpers": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/@quasar/ssr-helpers/-/ssr-helpers-2.2.0.tgz", "resolved": "https://registry.npmjs.org/@quasar/ssr-helpers/-/ssr-helpers-2.2.0.tgz",
...@@ -13934,21 +13982,21 @@ ...@@ -13934,21 +13982,21 @@
"dev": true "dev": true
}, },
"ag-grid-community": { "ag-grid-community": {
"version": "28.0.0", "version": "28.2.1",
"resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-28.0.0.tgz", "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-28.2.1.tgz",
"integrity": "sha512-ovatVo8iGbJZHQRY2ga92IXLSPiLq8zzKIHsli4DU073P/e334gGrk9aTjAD0N0qRie+iKCvkQiZFPo07Wzl1Q==" "integrity": "sha512-DMZh/xD/FqYP17qJ1M92PolTYe+hrKuEaf+A4h13O6qn2x/xZQrTRGW5DgnQLR/uLMe1XXZQPKR3UKgAlKo69A=="
}, },
"ag-grid-enterprise": { "ag-grid-enterprise": {
"version": "28.0.0", "version": "28.2.1",
"resolved": "https://registry.npmjs.org/ag-grid-enterprise/-/ag-grid-enterprise-28.0.0.tgz", "resolved": "https://registry.npmjs.org/ag-grid-enterprise/-/ag-grid-enterprise-28.2.1.tgz",
"integrity": "sha512-bTyTU+Fc6aw8aXgbaIlsuDsQ9mPXjTOQpEQm3J6cg947iEhO6W/74VWh+MicYZaEKK2/wDkcchhVgDADUOpe+A==" "integrity": "sha512-FIqIiaMMO9m8eqfu64rZ7dOK8vQFqD+Dp9CTpSfjMtyUp4IoRE36c+mUpUGLX/bIix9LltpaUmr185nFM1Alrw=="
}, },
"ag-grid-vue3": { "ag-grid-vue3": {
"version": "28.0.0", "version": "28.2.1",
"resolved": "https://registry.npmjs.org/ag-grid-vue3/-/ag-grid-vue3-28.0.0.tgz", "resolved": "https://registry.npmjs.org/ag-grid-vue3/-/ag-grid-vue3-28.2.1.tgz",
"integrity": "sha512-qQQEuOiiJLkK1l4aHIo7PMG6iU7QHZHOMvYPnKDHjdEKvEU3NKuw6pJB4Ot7EdUnnqSBJOKx7/FMibHelerijw==", "integrity": "sha512-n7+l51zFCZm3SVT2pI0lVVwL8gsDPebqNLfEy4DS17OlV5IL7c1eNXRosv/QMu+YHOEMVcwFRWH380nIjVF/+w==",
"requires": { "requires": {
"ag-grid-community": "~28.0.0", "ag-grid-community": "~28.2.1",
"vue": "^3.0.0" "vue": "^3.0.0"
} }
}, },
......
...@@ -13,9 +13,9 @@ ...@@ -13,9 +13,9 @@
"dependencies": { "dependencies": {
"@antv/x6": "^1.32.11", "@antv/x6": "^1.32.11",
"@quasar/extras": "^1.0.0", "@quasar/extras": "^1.0.0",
"ag-grid-community": "^28.0.0", "ag-grid-community": "^28.2.1",
"ag-grid-enterprise": "^28.0.0", "ag-grid-enterprise": "^28.2.1",
"ag-grid-vue3": "^28.0.0", "ag-grid-vue3": "^28.2.1",
"animejs": "^3.2.1", "animejs": "^3.2.1",
"axios": "^0.27.2", "axios": "^0.27.2",
"core-js": "^3.6.5", "core-js": "^3.6.5",
......
import { Notify } from 'quasar'; import { Notify } from 'quasar';
import ICON from 'src/config/icons';
const creatNotify = function (type: string, msg: string) { const creatNotify = function (type: string, icon: string, msg: string) {
Notify.create({ Notify.create({
position: 'top',
type, type,
icon,
textColor: 'white',
message: msg, message: msg,
position: 'top',
}); });
}; };
type IMessage = { type IMessage = {
...@@ -16,16 +19,16 @@ type IMessage = { ...@@ -16,16 +19,16 @@ type IMessage = {
const message: IMessage = { const message: IMessage = {
success: (msg: string) => { success: (msg: string) => {
creatNotify('positive', msg); creatNotify('positive', ICON.success, msg);
}, },
error: (msg: string) => { error: (msg: string) => {
creatNotify('negative', msg); creatNotify('negative', ICON.error, msg);
}, },
warn: (msg: string) => { warn: (msg: string) => {
creatNotify('warning', msg); creatNotify('warning', ICON.warn, msg);
}, },
info: (msg: string) => { info: (msg: string) => {
creatNotify('info', msg); creatNotify('info', ICON.info, msg);
}, },
}; };
......
...@@ -50,7 +50,8 @@ const usePageStore = defineStore(PAGE_STORE_KEY, { ...@@ -50,7 +50,8 @@ const usePageStore = defineStore(PAGE_STORE_KEY, {
} }
this.saveToSession(); this.saveToSession();
}, },
removePage(path: string) { removePage(params: any) {
const path = params.link;
const index = findIndex(this.tabRouterList, ['path', path]); const index = findIndex(this.tabRouterList, ['path', path]);
if (path === this.activeRouter.path) { if (path === this.activeRouter.path) {
if (index > 0) { if (index > 0) {
...@@ -59,10 +60,25 @@ const usePageStore = defineStore(PAGE_STORE_KEY, { ...@@ -59,10 +60,25 @@ const usePageStore = defineStore(PAGE_STORE_KEY, {
this.activeRouter = this.tabRouterList[index + 1]; this.activeRouter = this.tabRouterList[index + 1];
} }
} }
this.allPageKeys.splice(index, 1); if (params.keepalive) {
this.allPageKeys.splice(index, 1);
}
delArrObj(this.tabRouterList, { path: path }); delArrObj(this.tabRouterList, { path: path });
this.saveToSession(); this.saveToSession();
}, },
removeNotCurrentPage(params: any) {
const path = params.link;
if (params.keepalive) {
this.allPageKeys = [params.name];
} else {
this.allPageKeys = [];
}
this.tabRouterList = this.tabRouterList.filter((item) => {
return item.path === path;
});
this.saveToSession();
},
saveToSession() { saveToSession() {
session.setItem(PAGE_STORE_KEY, JSON.stringify(this.$state)); session.setItem(PAGE_STORE_KEY, JSON.stringify(this.$state));
}, },
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
<q-item-section> <q-item-section>
<q-item-label>{{ title }}</q-item-label> <q-item-label>{{ title }}</q-item-label>
<q-item-label caption>{{ caption }}</q-item-label> <q-item-label caption v-if="caption">{{ caption }}</q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
</template> </template>
......
export default { export default {
success: 'bi-check-circle-fill',
error: 'bi-exclamation-triangle-fill',
warn: 'bi-exclamation-circle-fill',
info: 'bi-info-circle-fill',
num0: 'fa-solid fa-0', // 数字0 num0: 'fa-solid fa-0', // 数字0
idCard: 'fa-regular fa-address-card', // 身份证 idCard: 'fa-regular fa-address-card', // 身份证
mapLocation: 'bi-pin-map-fill', // 地图定位 mapLocation: 'bi-pin-map-fill', // 地图定位
......
...@@ -33,13 +33,6 @@ a:hover { ...@@ -33,13 +33,6 @@ a:hover {
.bg-pause { .bg-pause {
background: #df7861; background: #df7861;
} }
// 导航栏激活颜色
.text-headeractive {
color: $primary-3;
}
.bg-headeractive {
background: $primary-3;
}
// tooltip样式 // tooltip样式
.com-tooltip-sty { .com-tooltip-sty {
...@@ -97,10 +90,10 @@ a:hover { ...@@ -97,10 +90,10 @@ a:hover {
// 标题列调整大小句柄颜色 // 标题列调整大小句柄颜色
--ag-header-column-resize-handle-color: var(--my-ag-grid-active) !important; --ag-header-column-resize-handle-color: var(--my-ag-grid-active) !important;
--ag-selected-row-background-color: var(--my-ag-grid-primary-2) !important; --ag-selected-row-background-color: var(--my-ag-grid-primary-5) !important;
--ag-range-selection-background-color: var(--my-ag-grid-primary-2) !important; --ag-range-selection-background-color: var(--my-ag-grid-primary-5) !important;
--ag-row-hover-color: var(--my-ag-grid-primary-1) !important; --ag-row-hover-color: var(--my-ag-grid-primary-2) !important;
--ag-column-hover-color: var(--my-ag-grid-primary-1) !important; --ag-column-hover-color: var(--my-ag-grid-primary-2) !important;
--ag-input-focus-border-color: var(--my-ag-grid-primary-1) !important; --ag-input-focus-border-color: var(--my-ag-grid-primary-1) !important;
--ag-border-color: var(--my-ag-grid-primary) !important; --ag-border-color: var(--my-ag-grid-primary) !important;
......
...@@ -25,8 +25,8 @@ $accent: #9c27b0; ...@@ -25,8 +25,8 @@ $accent: #9c27b0;
$dark: #1d1d1d; $dark: #1d1d1d;
$positive: #8bc24c; $positive: #81c784;
$negative: #d2001a; $negative: #dd4a48;
$info: #a696c8; $info: #a696c8;
$warning: #ffb200; $warning: #ffb200;
...@@ -62,6 +62,7 @@ $header-heigyht: 50px; ...@@ -62,6 +62,7 @@ $header-heigyht: 50px;
--my-ag-grid-primary-light: rgba(165, 189, 22, 0.05); --my-ag-grid-primary-light: rgba(165, 189, 22, 0.05);
--my-ag-grid-primary-1: rgba(165, 189, 22, 0.1); --my-ag-grid-primary-1: rgba(165, 189, 22, 0.1);
--my-ag-grid-primary-2: rgba(165, 189, 22, 0.2); --my-ag-grid-primary-2: rgba(165, 189, 22, 0.2);
--my-ag-grid-primary-5: rgba(165, 189, 22, 0.5);
--my-ag-grid-active: rgb(97, 112, 17); --my-ag-grid-active: rgb(97, 112, 17);
--my-ag-grid-text: #fff7f7; --my-ag-grid-text: #fff7f7;
......
...@@ -14,14 +14,8 @@ ...@@ -14,14 +14,8 @@
</q-avatar> </q-avatar>
</q-btn> </q-btn>
<q-toolbar-title> Quasar App </q-toolbar-title> <q-toolbar-title style="min-width: 140px"> Quasar App </q-toolbar-title>
<q-tabs <q-tabs v-model="defaultRouter" no-caps shrink class="my-tabs">
v-model="defaultRouter"
no-caps
shrink
active-color="white"
active-bg-color="headeractive"
>
<q-tab <q-tab
class="my-tab" class="my-tab"
v-for="page in tabsList" v-for="page in tabsList"
...@@ -31,16 +25,35 @@ ...@@ -31,16 +25,35 @@
@click.stop="clickTab(page)" @click.stop="clickTab(page)"
> >
<q-btn <q-btn
v-show="tabsList.length > 1" v-show="isShowCloseBtn"
dense dense
flat flat
round round
size="sm" size="sm"
icon="close" icon="close"
title="关闭"
@mousedown.stop="doNothing" @mousedown.stop="doNothing"
@click.stop="closeTab(page)" @click.stop="closeTab(page)"
> >
</q-btn> </q-btn>
<q-menu touch-position context-menu v-if="isShowCloseBtn">
<q-list dense style="min-width: 100px">
<q-item clickable v-close-popup>
<q-item-section @click="closeTab(page)"
>关闭当前页面</q-item-section
>
</q-item>
<q-item clickable v-close-popup>
<q-item-section @click="closeNotCurrentPage(page)"
>关闭非当前页面</q-item-section
>
</q-item>
<q-item clickable v-close-popup>
<q-item-section @click="closeAll">关闭所有</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-tab> </q-tab>
</q-tabs> </q-tabs>
...@@ -71,9 +84,16 @@ ...@@ -71,9 +84,16 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref, onMounted, reactive, toRefs } from 'vue'; import {
defineComponent,
ref,
onMounted,
reactive,
toRefs,
computed,
} from 'vue';
import { onBeforeRouteUpdate, useRouter } from 'vue-router'; import { onBeforeRouteUpdate, useRouter } from 'vue-router';
import { usePageStore } from 'src/common/hooks'; import { usePageStore, useMessage } from 'src/common/hooks';
import EssentialLink from 'components/EssentialLink.vue'; import EssentialLink from 'components/EssentialLink.vue';
// import TopLeftLoading from './TopLeftLoading.vue'; // import TopLeftLoading from './TopLeftLoading.vue';
import TopLeftLoading from './TopLeftText.vue'; import TopLeftLoading from './TopLeftText.vue';
...@@ -91,6 +111,8 @@ export default defineComponent({ ...@@ -91,6 +111,8 @@ export default defineComponent({
setup() { setup() {
const pageStore = usePageStore(); const pageStore = usePageStore();
const router = useRouter(); const router = useRouter();
const { info } = useMessage();
const leftDrawerOpen = ref(false); const leftDrawerOpen = ref(false);
const defaultRouter = ref('/page1'); const defaultRouter = ref('/page1');
const linksList = ref<any>([]); const linksList = ref<any>([]);
...@@ -106,6 +128,19 @@ export default defineComponent({ ...@@ -106,6 +128,19 @@ export default defineComponent({
} }
next(); next();
}); });
const isShowCloseBtn = computed(() => {
let flag = true;
const { tabsList } = state;
if (tabsList.length === 1) {
const target = tabsList[0];
if (target.link === '/home') {
flag = false;
}
}
return flag;
});
onMounted(() => { onMounted(() => {
getLinksList(); getLinksList();
const path = router.currentRoute.value.path; const path = router.currentRoute.value.path;
...@@ -116,12 +151,19 @@ export default defineComponent({ ...@@ -116,12 +151,19 @@ export default defineComponent({
const getLinksList = () => { const getLinksList = () => {
const lists = [ const lists = [
{
title: '主页',
caption: null,
icon: require('./menuListIcons/home.svg'),
link: '/home',
active: false,
},
{ {
title: '一', title: '一',
caption: '日历', caption: '日历',
icon: require('./menuListIcons/page1.svg'), icon: require('./menuListIcons/page1.svg'),
link: '/page1', link: '/page1',
active: true, active: false,
}, },
{ {
title: '贰', title: '贰',
...@@ -206,6 +248,7 @@ export default defineComponent({ ...@@ -206,6 +248,7 @@ export default defineComponent({
link: item.path, link: item.path,
keepalive: item.meta?.keepalive, keepalive: item.meta?.keepalive,
permission: item.meta?.permission, permission: item.meta?.permission,
name: item.name,
}; };
}); });
}; };
...@@ -215,9 +258,25 @@ export default defineComponent({ ...@@ -215,9 +258,25 @@ export default defineComponent({
}; };
const closeTab = (page: any) => { const closeTab = (page: any) => {
pageStore.removePage(page.link); const { tabsList } = state;
if (tabsList.length === 1) {
router.push('/home');
pageStore.removePage(page);
getTabsList();
} else {
pageStore.removePage(page);
getTabsList();
router.push(pageStore.activeRouter.path);
}
};
const closeNotCurrentPage = (page: any) => {
pageStore.removeNotCurrentPage(page);
getTabsList(); getTabsList();
router.push(pageStore.activeRouter.path); };
const closeAll = () => {
info('正在开发中...');
}; };
const doNothing = () => { const doNothing = () => {
...@@ -236,13 +295,19 @@ export default defineComponent({ ...@@ -236,13 +295,19 @@ export default defineComponent({
defaultRouter, defaultRouter,
clickTab, clickTab,
closeTab, closeTab,
closeNotCurrentPage,
closeAll,
doNothing, doNothing,
isShowCloseBtn,
}; };
}, },
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.my-tab { .my-tab {
box-sizing: border-box;
background-color: $primary-4;
margin: 0 2px;
:deep(.q-tab__content) { :deep(.q-tab__content) {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
...@@ -258,4 +323,12 @@ export default defineComponent({ ...@@ -258,4 +323,12 @@ export default defineComponent({
} }
} }
} }
.my-tabs {
padding: 0 36px;
box-sizing: border-box;
:deep(.q-tab--active) {
background-color: $primary-2;
}
}
</style> </style>
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1672903394187" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15179" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M119.838 786.652V581.34l18-55.742 367.084-344.66a10.322 10.322 0 0 1 14.154 0l367.084 344.66 18 55.742v205.312L512 809.88z" fill="#E7ECF1" p-id="15180"></path><path d="M504.924 144.938L119.838 507.598v73.742l385.084-362.66a10.322 10.322 0 0 1 14.154 0L904.16 581.34v-73.742L519.078 144.938a10.322 10.322 0 0 0-14.154 0zM119.838 823.814l392.162 18 392.162-18 18-18.582-18-18.58H119.838l-18 18.58z" fill="#C6D0DA" p-id="15181"></path><path d="M625.02 786.652V548.878a10.32 10.32 0 0 0-10.322-10.322H409.302a10.322 10.322 0 0 0-10.322 10.322v237.772L512 809.88z" fill="#ECB85E" p-id="15182"></path><path d="M398.98 823.814l113.02 18 113.02-18v-37.162H398.98z" fill="#EAA949" p-id="15183"></path><path d="M904.162 870.27l-392.162 18-392.162-18-18-24.332 18-22.124h784.324l18 22.124z" fill="#CF8151" p-id="15184"></path><path d="M119.838 907.43h784.324l18-19.16-18-18H119.838l-18 18.58z" fill="#BD6E45" p-id="15185"></path><path d="M1024 926.57v-141.964a10.32 10.32 0 0 0-3.292-7.558l-49.596-46.14a10.324 10.324 0 0 0-14.062 0l-49.596 46.14a10.324 10.324 0 0 0-3.292 7.558v141.964l59.92 18zM797.96 926.57v-141.964a10.32 10.32 0 0 0-3.292-7.558l-49.596-46.14a10.324 10.324 0 0 0-14.062 0l-49.596 46.14a10.318 10.318 0 0 0-3.292 7.558v141.964l59.92 18zM571.92 926.57v-141.964a10.32 10.32 0 0 0-3.292-7.558l-49.596-46.14a10.324 10.324 0 0 0-14.062 0l-49.596 46.14a10.318 10.318 0 0 0-3.292 7.558v141.964l59.92 18zM345.878 926.57v-141.964a10.32 10.32 0 0 0-3.292-7.558l-49.596-46.14a10.324 10.324 0 0 0-14.062 0l-49.596 46.14a10.318 10.318 0 0 0-3.292 7.558v141.964l59.92 18z" fill="#E2AE84" p-id="15186"></path><path d="M904.162 349.158v-141.93c0-11.402-9.244-20.646-20.646-20.646h-67.408c-11.402 0-20.646 9.244-20.646 20.646v39.562l41.926 73.71z" fill="#DC4955" p-id="15187"></path><path d="M795.464 320.532l108.698 102.368v-73.742l-108.698-102.368z" fill="#D82F3C" p-id="15188"></path><path d="M466.694 78.244L13.808 504.756A43.92 43.92 0 0 0 0 536.728c0 13.59 5.748 24.84 14.4 32.572 0 0 41.496-1.526 59.628-18.6L504.924 144.896a10.322 10.322 0 0 1 14.154 0l430.896 405.802c18.13 17.074 59.628 18.6 59.628 18.6 8.652-7.732 14.4-18.982 14.4-32.572a43.92 43.92 0 0 0-13.808-31.972L557.306 78.244c-25.45-23.968-65.162-23.968-90.612 0z" fill="#DC4955" p-id="15189"></path><path d="M504.922 107.158L14.4 569.3c15.856 14.168 41.496 16.474 59.628-0.6L504.924 162.896a10.322 10.322 0 0 1 14.154 0L949.974 568.7c18.13 17.074 43.772 14.768 59.628 0.6L519.078 107.158a10.32 10.32 0 0 0-14.156 0z" fill="#D82F3C" p-id="15190"></path><path d="M914.484 963.732h99.194a10.32 10.32 0 0 0 10.322-10.322v-26.838h-119.838v26.838a10.322 10.322 0 0 0 10.322 10.322zM688.444 963.732h99.194a10.322 10.322 0 0 0 10.322-10.322v-26.838h-119.838v26.838a10.32 10.32 0 0 0 10.322 10.322zM462.404 963.732h99.192a10.32 10.32 0 0 0 10.322-10.322v-26.838H452.08v26.838a10.324 10.324 0 0 0 10.324 10.322zM236.364 963.732h99.194a10.322 10.322 0 0 0 10.322-10.322v-26.838h-119.84v26.838a10.324 10.324 0 0 0 10.324 10.322z" fill="#D7A379" p-id="15191"></path><path d="M119.838 926.57v-141.964a10.32 10.32 0 0 0-3.292-7.558l-49.596-46.14a10.324 10.324 0 0 0-14.062 0l-49.596 46.14A10.324 10.324 0 0 0 0 784.606v141.964l59.92 18z" fill="#E2AE84" p-id="15192"></path><path d="M10.322 963.732h99.194a10.322 10.322 0 0 0 10.322-10.322v-26.838H0v26.838a10.322 10.322 0 0 0 10.322 10.322z" fill="#D7A379" p-id="15193"></path><path d="M448.048 674.914v25.226a15.514 15.514 0 0 0 31.028 0v-25.226a15.514 15.514 0 0 0-31.028 0z" fill="#BD6E45" p-id="15194"></path></svg>
\ No newline at end of file
<!--
* 主页
-->
<script setup lang="ts">
import MyPoems from '../page10/element/MyPoems.vue';
</script>
<template>
<my-poems />
</template>
<style lang="scss" scoped></style>
...@@ -14,24 +14,33 @@ ...@@ -14,24 +14,33 @@
<q-item :key="index" v-if="item.id === '1'"> <q-item :key="index" v-if="item.id === '1'">
<div class="q-gutter-sm full-width"> <div class="q-gutter-sm full-width">
<q-btn <q-btn
outline unelevated
label="success" label="success"
color="positive" color="positive"
:icon="ICON.success"
@click="onClick('success')" @click="onClick('success')"
/> />
<q-btn <q-btn
outline unelevated
label="error" label="error"
color="negative" color="negative"
:icon="ICON.error"
@click="onClick('error')" @click="onClick('error')"
/> />
<q-btn <q-btn
outline unelevated
label="warn" label="warn"
color="warning" color="warning"
:icon="ICON.warn"
@click="onClick('warn')" @click="onClick('warn')"
/> />
<q-btn outline label="info" color="info" @click="onClick('info')" /> <q-btn
unelevated
label="info"
color="info"
:icon="ICON.info"
@click="onClick('info')"
/>
</div> </div>
</q-item> </q-item>
...@@ -237,7 +246,7 @@ function onClick(type: string) { ...@@ -237,7 +246,7 @@ function onClick(type: string) {
warn('警告'); warn('警告');
break; break;
case 'info': case 'info':
info('提示信息'); info('提示');
break; break;
default: default:
......
...@@ -11,7 +11,7 @@ const props = defineProps<{ ...@@ -11,7 +11,7 @@ const props = defineProps<{
const $q = useQuasar(); const $q = useQuasar();
function delRow() { function delRow() {
const msg = `确定<strong>删除</strong>当前行<span class="text-red text-weight-bold">${props.params.data.name}</span>?`; const msg = `确定<strong>删除</strong>当前行<span class="text-warning text-weight-bold">${props.params.data.name}</span>?`;
$q.dialog({ $q.dialog({
title: '<i class="bi bi-exclamation-circle text-warning"></i>&nbsp;提示', title: '<i class="bi bi-exclamation-circle text-warning"></i>&nbsp;提示',
message: msg, message: msg,
......
...@@ -20,6 +20,9 @@ import AgGridDetailGrids from './element/AgGridDetailGrids.vue'; ...@@ -20,6 +20,9 @@ import AgGridDetailGrids from './element/AgGridDetailGrids.vue';
import AgGridTreeData from './element/AgGridTreeData.vue'; import AgGridTreeData from './element/AgGridTreeData.vue';
import AgGridTreeFileBrowser from './element/AgGridTreeFileBrowser.vue'; import AgGridTreeFileBrowser from './element/AgGridTreeFileBrowser.vue';
import AgGridCustomDateComponent from './element/AgGridCustomDateComponent.vue'; import AgGridCustomDateComponent from './element/AgGridCustomDateComponent.vue';
import AgGridSelection from './element/AgGridSelection.vue';
import AgGridCheckboxSelection from './element/AgGridCheckboxSelection.vue';
import AgGridGroupSelection from './element/AgGridGroupSelection.vue';
const listData = [ const listData = [
{ {
...@@ -66,10 +69,22 @@ const listData = [ ...@@ -66,10 +69,22 @@ const listData = [
title: 'Ag Grid 自定义日期组件', title: 'Ag Grid 自定义日期组件',
name: 'ag-grid-custom-date-component', name: 'ag-grid-custom-date-component',
}, },
{
title: 'Ag Grid 选择',
name: 'ag-grid-selection',
},
{
title: 'Ag Grid 复选框选择',
name: 'ag-grid-checkbox-selection',
},
{
title: 'Ag Grid 组选择',
name: 'ag-grid-group-selection',
},
]; ];
const isShow = ref(true); const isShow = ref(true);
const elementName = ref('ag-grid-detail-grids'); const elementName = ref('ag-grid-group-selection');
const elementTitle = ref('Vue Data Grid: Master / Detail - Detail Grids'); const elementTitle = ref('Ag Grid 组选择');
function onclick(data: any) { function onclick(data: any) {
elementTitle.value = data.title; elementTitle.value = data.title;
...@@ -117,6 +132,13 @@ function goBack() { ...@@ -117,6 +132,13 @@ function goBack() {
<ag-grid-custom-date-component <ag-grid-custom-date-component
v-if="elementName === 'ag-grid-custom-date-component'" v-if="elementName === 'ag-grid-custom-date-component'"
/> />
<ag-grid-selection v-if="elementName === 'ag-grid-selection'" />
<ag-grid-checkbox-selection
v-if="elementName === 'ag-grid-checkbox-selection'"
/>
<ag-grid-group-selection
v-if="elementName === 'ag-grid-group-selection'"
/>
</div> </div>
</div> </div>
<div v-else> <div v-else>
......
<!--
* Ag Grid 复选框选择
* https://www.ag-grid.com/vue-data-grid/row-selection/#checkbox-selection
-->
<script setup lang="ts">
import { ref, reactive, onMounted, watch } from 'vue';
import { AgGridVue } from 'ag-grid-vue3';
import AG_GRID_LOCALE from 'src/config/ag-grid-locale';
const defaultColDef = {
flex: 1,
minWidth: 100,
suppressMenu: true, // 是否禁用标题行菜单
};
const gridApi = ref<any>(null);
const gridColumnApi = ref<any>(null);
const checkAllUsable = ref<any>(null);
const columnDefs = reactive([
{
field: 'athlete',
headerName: '运动员',
checkboxSelection: (params: any) => {
return params.data && params.data.year !== 2012;
},
showDisabledCheckboxes: true,
},
{ field: 'sport', headerName: '运动' },
{ field: 'year', maxWidth: 120, headerName: '年份' },
]);
const state = reactive({
rowData: [] as any,
selected: [],
});
watch(checkAllUsable, (val: any) => {
if (val === true) {
gridApi.value.forEachNode((node: any) => {
node.setSelected(true);
});
} else if (val === false) {
deselectRows();
}
});
onMounted(() => {
//
});
function getData() {
fetch('https://www.ag-grid.com/example-assets/small-olympic-winners.json')
.then((resp) => resp.json())
.then((data) => {
state.rowData = data;
console.log('state.rowData[0]', state.rowData[0]);
});
}
function onGridReady(params: any) {
gridApi.value = params.api;
gridColumnApi.value = params.columnApi;
getData();
}
function onFirstDataRendered(params: any) {
params.api.forEachNode((node: any) =>
node.setSelected(node.data && node.data.year == 2012)
);
}
function onSelectionChanged() {
const length1 = state.rowData.length;
const selectedRows = gridApi.value.getSelectedRows();
const length2 = selectedRows.length;
state.selected = selectedRows.map((item: any) => item.athlete);
if (length1 && length1 === length2) {
checkAllUsable.value = true;
} else if (length1 !== length2) {
checkAllUsable.value = null;
} else {
checkAllUsable.value = false;
}
}
// function isRowSelectable(params: any) {
// return !!params.data && params.data.year === 2012;
// }
function deselectRows() {
// gridApi.value.deselectAll();
gridApi.value.forEachNode((node: any) => {
let falg = false;
if (node.data && node.data.year == 2012) {
falg = true;
}
node.setSelected(falg);
});
}
</script>
<template>
<div class="box">
<div class="text">
<div>固定选中<q-chip square :ripple="false">年份=2012</q-chip>的行</div>
<q-checkbox v-model="checkAllUsable" label="选择全部可选内容" dense />
<span>已选择:{{ state.selected.join(',') }}</span>
</div>
<!--
rowSelection="multiple":多选,按住control键多选;【control+shift+鼠标点击】可选中多行
animateRows=true:启用行动画
:masterDetail="true" 启用展开的细节网格行
:isRowMaster="isRowMaster" 确定哪一个行该展开
rowSelection="single" single单选 multiple多选
-->
<div class="ag-table">
<ag-grid-vue
style="height: 550px"
class="ag-theme-alpine"
:animateRows="true"
:localeText="AG_GRID_LOCALE"
:defaultColDef="defaultColDef"
:columnDefs="columnDefs"
:rowData="state.rowData"
rowSelection="multiple"
:suppressRowClickSelection="true"
@grid-ready="onGridReady"
@first-data-rendered="onFirstDataRendered"
@selection-changed="onSelectionChanged"
>
</ag-grid-vue>
</div>
</div>
</template>
<style lang="scss" scoped>
.text {
padding: 10px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
row-gap: 10px;
}
.ag-table {
padding: 0 10px 10px 10px;
}
</style>
<!--
* Ag Grid 组选择
* https://www.ag-grid.com/vue-data-grid/row-selection/#group-selection
-->
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue';
import { AgGridVue } from 'ag-grid-vue3';
import AG_GRID_LOCALE from 'src/config/ag-grid-locale';
const defaultColDef = {
flex: 1,
minWidth: 100,
suppressMenu: true, // 是否禁用标题行菜单
};
const gridApi = ref<any>(null);
const gridColumnApi = ref<any>(null);
const autoGroupColumnDef = reactive({
headerName: '运动员',
field: 'athlete',
minWidth: 250,
sortable: true,
cellRenderer: 'agGroupCellRenderer',
cellRendererParams: {
checkbox: true,
},
});
const columnDefs = reactive([
{
field: 'year',
minWidth: 150,
rowGroup: true,
hide: true,
sortable: true,
headerName: '年份',
},
{
field: 'country',
rowGroup: true,
hide: true,
sortable: true,
headerName: '国家',
},
{ field: 'sport', headerName: '运动' },
{ field: 'gold', aggFunc: 'sum', headerName: '金牌' },
{ field: 'silver', aggFunc: 'sum', headerName: '银牌' },
{ field: 'bronze', aggFunc: 'sum', headerName: '铜牌' },
{
field: 'age',
minWidth: 120,
aggFunc: 'sum',
headerName: '年龄',
},
{ field: 'date', minWidth: 150, headerName: '日期' },
]);
const state = reactive({
rowData: [] as any,
});
onMounted(() => {
//
});
function getData() {
fetch('https://www.ag-grid.com/example-assets/olympic-winners.json')
.then((resp) => resp.json())
.then((data) => {
state.rowData = data;
console.log('state.rowData[0]', state.rowData[0]);
});
}
function onGridReady(params: any) {
gridApi.value = params.api;
gridColumnApi.value = params.columnApi;
getData();
}
function onFirstDataRendered() {
//
}
function onSelectionChanged() {
// const selectedNodes = gridApi.value.getSelectedNodes();
// console.log('selectedNodes', selectedNodes);
}
</script>
<template>
<div class="box">
<!--
rowSelection="multiple":多选,按住control键多选;【control+shift+鼠标点击】可选中多行
animateRows=true:启用行动画
:masterDetail="true" 启用展开的细节网格行
:isRowMaster="isRowMaster" 确定哪一个行该展开
rowSelection="single" single单选 multiple多选
:suppressContextMenu="true" 阻止显示右键单击时的上下文菜单
:suppressCellFocus="true" 阻止单元格聚焦
-->
<div class="ag-table">
<ag-grid-vue
style="height: 550px"
class="ag-theme-alpine"
:animateRows="true"
:localeText="AG_GRID_LOCALE"
:suppressContextMenu="true"
:suppressCellFocus="true"
:defaultColDef="defaultColDef"
:columnDefs="columnDefs"
:rowData="state.rowData"
:autoGroupColumnDef="autoGroupColumnDef"
:groupSelectsChildren="true"
rowSelection="multiple"
:suppressAggFuncInHeader="true"
:suppressRowClickSelection="true"
@grid-ready="onGridReady"
@first-data-rendered="onFirstDataRendered"
@selection-changed="onSelectionChanged"
>
</ag-grid-vue>
</div>
</div>
</template>
<style lang="scss" scoped>
.ag-table {
padding: 0 10px 10px 10px;
}
</style>
<!--
* AG-grid 选择
* https://www.ag-grid.com/vue-data-grid/selection-overview/
-->
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue';
import { AgGridVue } from 'ag-grid-vue3';
import AG_GRID_LOCALE from 'src/config/ag-grid-locale';
const defaultColDef = {
flex: 1,
minWidth: 100,
suppressMenu: true, // 是否禁用标题行菜单
};
const gridApi = ref<any>(null);
const gridColumnApi = ref<any>(null);
const columnDefs = reactive([
{ field: 'athlete', minWidth: 150, headerName: '运动员' },
{ field: 'age', maxWidth: 90, headerName: '年龄' },
{ field: 'country', minWidth: 150, headerName: '国家' },
{ field: 'year', maxWidth: 90, headerName: '年份' },
{ field: 'date', minWidth: 150, headerName: '日期' },
{ field: 'sport', minWidth: 150, headerName: '运动' },
{ field: 'gold', headerName: '金牌' },
{ field: 'silver', headerName: '银牌' },
{ field: 'bronze', headerName: '铜牌' },
{ field: 'total', headerName: '共计' },
]);
const selectionGroup = ref('single');
const rowSelectionOpt = reactive([
{
label: '单选',
value: 'single',
},
{
label: '多选',
value: 'multiple',
},
{
label: '单击多选',
value: 'both',
},
]);
const state = reactive({
rowData: [] as any,
selected: [],
});
const rowSelection = computed(() => {
let val = '';
switch (selectionGroup.value) {
case 'single':
val = 'single';
break;
case 'multiple':
val = 'multiple';
break;
default:
val = 'multiple';
break;
}
return val;
});
onMounted(() => {
//
});
function getData() {
fetch('https://www.ag-grid.com/example-assets/olympic-winners.json')
.then((resp) => resp.json())
.then((data) => {
state.rowData = data;
console.log('state.rowData[0]', state.rowData[0]);
});
}
function onGridReady(params: any) {
gridApi.value = params.api;
gridColumnApi.value = params.columnApi;
getData();
}
function onSelectionChanged() {
const selectedRows = gridApi.value.getSelectedRows();
state.selected = selectedRows.map((item: any) => item.athlete);
}
function deselectRows() {
gridApi.value.deselectAll();
}
</script>
<template>
<div class="box">
<div class="text">
<span>已选择:{{ state.selected.join(',') }}</span>
<q-option-group
dense
v-model="selectionGroup"
:options="rowSelectionOpt"
color="primary"
inline
/>
<q-btn
color="primary"
label="取消所有选择"
no-caps
@click="deselectRows"
/>
</div>
<!--
rowSelection="multiple":多选,按住control键多选;【control+shift+鼠标点击】可选中多行
animateRows=true:启用行动画
:masterDetail="true" 启用展开的细节网格行
:isRowMaster="isRowMaster" 确定哪一个行该展开
rowSelection="single" single单选 multiple多选
-->
<div class="ag-table">
<ag-grid-vue
style="height: 550px"
class="ag-theme-alpine"
:animateRows="true"
:pagination="true"
:paginationPageSize="10"
:localeText="AG_GRID_LOCALE"
:defaultColDef="defaultColDef"
:columnDefs="columnDefs"
:rowData="state.rowData"
:rowSelection="rowSelection"
:rowMultiSelectWithClick="selectionGroup === 'both'"
@grid-ready="onGridReady"
@selection-changed="onSelectionChanged"
>
</ag-grid-vue>
</div>
</div>
</template>
<style lang="scss" scoped>
.text {
padding: 10px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: flex-start;
row-gap: 10px;
}
.ag-table {
padding: 0 10px 10px 10px;
}
</style>
...@@ -12,6 +12,16 @@ const routes: RouteRecordRaw[] = [ ...@@ -12,6 +12,16 @@ const routes: RouteRecordRaw[] = [
component: () => import('pages/IndexPage.vue'), component: () => import('pages/IndexPage.vue'),
redirect: '/page9', redirect: '/page9',
children: [ children: [
{
path: 'home',
name: 'HOME',
component: () => import('../modules/home/PageHome.vue'),
meta: {
title: '主页',
permission: ['*'],
keepalive: false,
},
},
{ {
path: 'page1', path: 'page1',
name: 'PAGE1', name: 'PAGE1',
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment