Commit 56d5da3f authored by hucy's avatar hucy

feat:提交

parents
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
/dist
/src-bex/www
/src-capacitor
/src-cordova
/.quasar
/node_modules
.eslintrc.js
babel.config.js
/src-ssr
module.exports = {
// https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy
// This option interrupts the configuration hierarchy at this file
// Remove this if you have an higher level ESLint config file (it usually happens into a monorepos)
root: true,
// https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser
// Must use parserOptions instead of "parser" to allow vue-eslint-parser to keep working
// `parser: 'vue-eslint-parser'` is already included with any 'plugin:vue/**' config and should be omitted
parserOptions: {
parser: require.resolve('@typescript-eslint/parser'),
extraFileExtensions: ['.vue'],
},
env: {
browser: true,
es2021: true,
node: true,
'vue/setup-compiler-macros': true,
},
// Rules order is important, please avoid shuffling them
extends: [
// Base ESLint recommended rules
// 'eslint:recommended',
// https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#usage
// ESLint typescript rules
'plugin:@typescript-eslint/recommended',
// Uncomment any of the lines below to choose desired strictness,
// but leave only one uncommented!
// See https://eslint.vuejs.org/rules/#available-rules
'plugin:vue/vue3-essential', // Priority A: Essential (Error Prevention)
// 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability)
// 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead)
// https://github.com/prettier/eslint-config-prettier#installation
// usage with Prettier, provided by 'eslint-config-prettier'.
'prettier',
],
plugins: [
// required to apply rules which need type information
'@typescript-eslint',
// https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-files
// required to lint *.vue files
'vue',
// https://github.com/typescript-eslint/typescript-eslint/issues/389#issuecomment-509292674
// Prettier has not been included as plugin to avoid performance impact
// add it as an extension for your IDE
],
globals: {
ga: 'readonly', // Google Analytics
cordova: 'readonly',
__statics: 'readonly',
__QUASAR_SSR__: 'readonly',
__QUASAR_SSR_SERVER__: 'readonly',
__QUASAR_SSR_CLIENT__: 'readonly',
__QUASAR_SSR_PWA__: 'readonly',
process: 'readonly',
Capacitor: 'readonly',
chrome: 'readonly',
},
// add your custom rules here
rules: {
'prefer-promise-reject-errors': 'off',
quotes: ['warn', 'single', { avoidEscape: true }],
// this rule, if on, would require explicit return type on the `render` function
'@typescript-eslint/explicit-function-return-type': 'off',
// in plain CommonJS modules, you can't use `import foo = require('foo')` to pass this rule, so it has to be disabled
'@typescript-eslint/no-var-requires': 'off',
// The core 'no-unused-vars' rules (in the eslint:recommended ruleset)
// does not work with type definitions
'no-unused-vars': 'off',
// allow debugger during development only
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'@typescript-eslint/no-explicit-any': ['off'],
// 防止this变量和局部变量混淆
'@typescript-eslint/no-this-alias': ['off'],
},
};
.DS_Store
.thumbs.db
node_modules
# Quasar core related directories
.quasar
/dist
# Cordova related directories and files
/src-cordova/node_modules
/src-cordova/platforms
/src-cordova/plugins
/src-cordova/www
# Capacitor related directories and files
/src-capacitor/www
/src-capacitor/node_modules
# BEX related directories and files
/src-bex/www
/src-bex/js/core
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
/* eslint-disable */
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
plugins: [
// to edit target browsers: use "browserslist" field in package.json
require('autoprefixer')
]
}
{
"singleQuote": true,
"semi": true
}
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"editorconfig.editorconfig",
"johnsoncodehk.volar",
"wayou.vscode-todo-highlight"
],
"unwantedRecommendations": [
"octref.vetur",
"hookyqr.beautify",
"dbaeumer.jshint",
"ms-vscode.vscode-typescript-tslint-plugin"
]
}
\ No newline at end of file
{
"editor.bracketPairColorization.enabled": true,
"editor.guides.bracketPairs": true,
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": [
"source.fixAll.eslint"
],
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"vue"
],
"typescript.tsdk": "node_modules/typescript/lib"
}
\ No newline at end of file
# Quasar App (my-study01)
A Quasar Project
## Install the dependencies
```bash
yarn
# or
npm install
```
### Start the app in development mode (hot-code reloading, error reporting, etc.)
```bash
quasar dev
```
### Lint the files
```bash
yarn lint
# or
npm run lint
```
### Format the files
```bash
yarn format
# or
npm run format
```
### Build the app for production
```bash
quasar build
```
### Customize the configuration
See [Configuring quasar.config.js](https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js).
/* eslint-disable */
module.exports = api => {
return {
presets: [
[
'@quasar/babel-preset-app',
api.caller(caller => caller && caller.target === 'node')
? { targets: { node: 'current' } }
: {}
]
]
}
}
This diff is collapsed.
{
"name": "my-study01",
"version": "0.0.1",
"description": "A Quasar Project",
"productName": "yayaya",
"author": "hucy <cy.hu@topibd.com>",
"private": true,
"scripts": {
"lint": "eslint --ext .js,.ts,.vue ./",
"format": "prettier --write \"**/*.{js,ts,vue,scss,html,md,json}\" --ignore-path .gitignore",
"test": "echo \"No test specified\" && exit 0"
},
"dependencies": {
"@antv/x6": "^1.32.11",
"@quasar/extras": "^1.0.0",
"ag-grid-community": "^28.0.0",
"ag-grid-vue3": "^28.0.0",
"axios": "^0.27.2",
"core-js": "^3.6.5",
"echarts": "^5.3.2",
"lodash-es": "^4.17.21",
"mitt": "^3.0.0",
"pinia": "^2.0.14",
"quasar": "^2.6.0",
"vue": "^3.0.0",
"vue-router": "^4.0.0"
},
"devDependencies": {
"@quasar/app-webpack": "^3.0.0",
"@types/lodash-es": "^4.17.6",
"@types/node": "^12.20.21",
"@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0",
"eslint": "^8.10.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-vue": "^8.5.0",
"prettier": "^2.5.1"
},
"browserslist": [
"last 10 Chrome versions",
"last 10 Firefox versions",
"last 4 Edge versions",
"last 7 Safari versions",
"last 8 Android versions",
"last 8 ChromeAndroid versions",
"last 8 FirefoxAndroid versions",
"last 10 iOS versions",
"last 5 Opera versions"
],
"engines": {
"node": ">= 12.22.1",
"npm": ">= 6.13.4",
"yarn": ">= 1.21.1"
}
}
This diff is collapsed.
/* eslint-env node */
/*
* This file runs in a Node context (it's NOT transpiled by Babel), so use only
* the ES6 features that are supported by your Node version. https://node.green/
*/
// Configuration for your app
// https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js
/* eslint-disable @typescript-eslint/no-var-requires */
const { configure } = require('quasar/wrappers');
module.exports = configure(function (ctx) {
return {
// https://v2.quasar.dev/quasar-cli-webpack/supporting-ts
supportTS: {
tsCheckerConfig: {
eslint: {
enabled: true,
files: './src/**/*.{ts,tsx,js,jsx,vue}',
},
},
},
// https://v2.quasar.dev/quasar-cli-webpack/prefetch-feature
// preFetch: true,
// app boot file (/src/boot)
// --> boot files are part of "main.js"
// https://v2.quasar.dev/quasar-cli-webpack/boot-files
boot: ['store'],
// https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-css
css: ['app.scss'],
// https://github.com/quasarframework/quasar/tree/dev/extras
extras: [
// 'ionicons-v4',
// 'mdi-v5',
// 'fontawesome-v6',
// 'eva-icons',
// 'themify',
// 'line-awesome',
// 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both!
'roboto-font', // optional, you are not bound to it
'material-icons', // optional, you are not bound to it
],
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-build
build: {
vueRouterMode: 'hash', // available values: 'hash', 'history'
// transpile: false,
// publicPath: '/',
// Add dependencies for transpiling with Babel (Array of string/regex)
// (from node_modules, which are by default not transpiled).
// Applies only if "transpile" is set to true.
// transpileDependencies: [],
// rtl: true, // https://quasar.dev/options/rtl-support
// preloadChunks: true,
// showProgress: false,
// gzip: true,
// analyze: true,
// Options below are automatically set depending on the env, set them if you want to override
// extractCSS: false,
// https://v2.quasar.dev/quasar-cli-webpack/handling-webpack
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
// chainWebpack (/* chain */) {}
},
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-devServer
devServer: {
// server: {
// type: 'http',
// },
https: false,
port: 8080,
open: true, // opens browser window automatically
proxy: {},
},
extras: ['material-icons', 'fontawesome-v6', 'bootstrap-icons'],
// https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-framework
framework: {
config: {},
// iconSet: 'material-icons', // Quasar icon set
lang: 'zh-CN', // Quasar language pack
// For special cases outside of where the auto-import strategy can have an impact
// (like functional components as one of the examples),
// you can manually specify Quasar components/directives to be available everywhere:
//
// components: [],
// directives: [],
// Quasar plugins
plugins: ['Notify', 'Dialog'],
},
// animations: 'all', // --- includes all animations
// https://quasar.dev/options/animations
animations: [],
// https://v2.quasar.dev/quasar-cli-webpack/developing-ssr/configuring-ssr
ssr: {
pwa: false,
// manualStoreHydration: true,
// manualPostHydrationTrigger: true,
prodPort: 3000, // The default port that the production server should use
// (gets superseded if process.env.PORT is specified at runtime)
maxAge: 1000 * 60 * 60 * 24 * 30,
// Tell browser when a file from the server should expire from cache (in ms)
// chainWebpackWebserver (/* chain */) {},
middlewares: [
ctx.prod ? 'compression' : '',
'render', // keep this as last one
],
},
// https://v2.quasar.dev/quasar-cli-webpack/developing-pwa/configuring-pwa
pwa: {
workboxPluginMode: 'GenerateSW', // 'GenerateSW' or 'InjectManifest'
workboxOptions: {}, // only for GenerateSW
// for the custom service worker ONLY (/src-pwa/custom-service-worker.[js|ts])
// if using workbox in InjectManifest mode
// chainWebpackCustomSW (/* chain */) {},
manifest: {
name: 'Quasar App',
short_name: 'Quasar App',
description: '',
display: 'standalone',
orientation: 'portrait',
background_color: '#ffffff',
theme_color: '#027be3',
icons: [
{
src: 'icons/icon-128x128.png',
sizes: '128x128',
type: 'image/png',
},
{
src: 'icons/icon-192x192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: 'icons/icon-256x256.png',
sizes: '256x256',
type: 'image/png',
},
{
src: 'icons/icon-384x384.png',
sizes: '384x384',
type: 'image/png',
},
{
src: 'icons/icon-512x512.png',
sizes: '512x512',
type: 'image/png',
},
],
},
},
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/developing-cordova-apps/configuring-cordova
cordova: {
// noIosLegacyBuildFlag: true, // uncomment only if you know what you are doing
},
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/developing-capacitor-apps/configuring-capacitor
capacitor: {
hideSplashscreen: true,
},
// Full list of options: https://v2.quasar.dev/quasar-cli-webpack/developing-electron-apps/configuring-electron
electron: {
bundler: 'packager', // 'packager' or 'builder'
packager: {
// https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options
// OS X / Mac App Store
// appBundleId: '',
// appCategoryType: '',
// osxSign: '',
// protocol: 'myapp://path',
// Windows only
// win32metadata: { ... }
},
builder: {
// https://www.electron.build/configuration/configuration
appId: 'my-study01',
},
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
chainWebpackMain(/* chain */) {
// do something with the Electron main process Webpack cfg
// extendWebpackMain also available besides this chainWebpackMain
},
// "chain" is a webpack-chain object https://github.com/neutrinojs/webpack-chain
chainWebpackPreload(/* chain */) {
// do something with the Electron main process Webpack cfg
// extendWebpackPreload also available besides this chainWebpackPreload
},
},
};
});
<template>
<router-view />
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'App'
})
</script>
This diff is collapsed.
import { boot } from 'quasar/wrappers';
import { createPinia } from 'pinia';
const store = createPinia();
export default boot(({ app }) => {
app.use(store);
});
export { store };
export * from './use-message';
export * from './use-webstorage';
export * from './use-pagestore';
import appConfig from 'src/config/app';
// Typescript高级类型Record
// https://zhuanlan.zhihu.com/p/356662885
type IWebStorageReturnType =
| Date
| RegExp
| number
| boolean
| string
| any[]
| Record<string, any>
| null;
interface IWebStorage {
setItem: (key: string, value: any) => void;
getItem: (key: string) => IWebStorageReturnType;
removeItem: (key: string) => void;
}
const prefixKey = appConfig.storagePrefix;
function getStorage(type: 'local' | 'session'): IWebStorage {
const webStorage =
type === 'local' ? window.localStorage : window.sessionStorage;
return {
setItem: (key: string, value: any) => {
webStorage.setItem(prefixKey + key, value);
},
getItem: (key: string) => {
const item = webStorage.getItem(prefixKey + key);
return item || null;
},
removeItem: (key: string) => {
webStorage.removeItem(prefixKey + key);
},
};
}
export type { IWebStorage, IWebStorageReturnType };
export { getStorage };
import { Notify } from 'quasar';
const creatNotify = function (type: string, msg: string) {
Notify.create({
type,
message: msg,
});
};
type IMessage = {
success: (msg: string) => void;
error: (msg: string) => void;
warn: (msg: string) => void;
info: (msg: string) => void;
};
const message: IMessage = {
success: (msg: string) => {
creatNotify('positive', msg);
},
error: (msg: string) => {
creatNotify('negative', msg);
},
warn: (msg: string) => {
creatNotify('warning', msg);
},
info: (msg: string) => {
creatNotify('info', msg);
},
};
function useMessage() {
return message;
}
export { useMessage };
import { defineStore } from 'pinia';
import { useSessionStorage } from './index';
import { some, delArrObj, findIndex } from '../utils';
const PAGE_STORE_KEY = 'MAIN_PAGES';
const session = useSessionStorage();
interface RouterType {
fullPath: string;
path: string;
hash?: string;
href?: string;
matched?: any[];
meta?: any;
name?: string;
params?: any;
query?: any;
redirectedFrom?: any;
[proppName: string]: any;
}
const usePageStore = defineStore(PAGE_STORE_KEY, {
state: () => {
const routersItem = JSON.parse(session.getItem(PAGE_STORE_KEY) as string);
return {
activeRouter: (routersItem?.activeRouter as RouterType) || null,
tabRouterList: (routersItem?.tabRouterList as RouterType[]) || [],
allPageKeys: routersItem?.allPageKeys || [],
};
},
getters: {},
actions: {
addRoute(route: RouterType) {
const item: RouterType = {
fullPath: route.fullPath,
path: route.path,
name: route.name,
meta: route.meta,
params: route.params,
query: route.query,
};
this.activeRouter = item;
const flag = some(this.tabRouterList, (item: RouterType) => {
return item.fullPath === route.fullPath;
});
if (!flag) {
this.tabRouterList.push(item);
if (item.meta.keepalive) {
this.allPageKeys.push(route.name);
}
}
this.saveToSession();
},
removePage(path: string) {
const index = findIndex(this.tabRouterList, ['path', path]);
if (path === this.activeRouter.path) {
if (index > 0) {
this.activeRouter = this.tabRouterList[index - 1];
} else {
this.activeRouter = this.tabRouterList[index + 1];
}
}
this.allPageKeys.splice(index, 1);
delArrObj(this.tabRouterList, { path: path });
this.saveToSession();
},
saveToSession() {
session.setItem(PAGE_STORE_KEY, JSON.stringify(this.$state));
},
},
});
export type { RouterType };
export { usePageStore, PAGE_STORE_KEY };
import { getStorage } from './private/webstorage';
import type { IWebStorage, IWebStorageReturnType } from './private/webstorage';
const useLocalStorage = (): IWebStorage => {
return getStorage('local');
};
const useSessionStorage = (): IWebStorage => {
return getStorage('session');
};
export type { IWebStorage, IWebStorageReturnType };
export { useLocalStorage, useSessionStorage };
export interface AnyType {
[proppName: string]: any;
}
import { AnyType } from 'src/common/types';
function func(data: Array<any>, key: string, value: any) {
return data.filter((item: any) => {
return item[key] == value;
});
}
/**
* 数组对象删除 改变原数组
* @param objArr - 原始数组
* @param valueData - 删除的对象条件{age:18,num:1}
**/
export const delArrObj = function (objArr: Array<any>, valueData: AnyType) {
for (let i = 0; i < objArr.length; i++) {
objArr[i].item_del_id = i;
}
const valueDataArr = [] as any[];
for (const key in valueData) {
valueDataArr.push({
key: key,
value: valueData[key],
});
}
let resArr = [] as any;
for (let i = 0; i < valueDataArr.length; i++) {
if (i == 0) {
const res = func(objArr, valueDataArr[i].key, valueDataArr[i].value);
resArr = res;
} else {
const res = func(resArr, valueDataArr[i].key, valueDataArr[i].value);
resArr = res;
}
}
for (let i = 0; i < objArr.length; i++) {
for (let j = 0; j < resArr.length; j++) {
if (objArr[i].item_del_id == resArr[j].item_del_id) {
objArr.splice(i, 1);
}
}
}
for (let i = 0; i < objArr.length; i++) {
delete objArr[i].item_del_id;
}
};
/**
* 删除对象中为空的属性值 返回一个新对象
* @param data - 原始对象
**/
export const delEmptyObjkey = function (data: any) {
const obj = {} as any;
for (const key in data) {
if (
data[key] !== null &&
data[key] !== undefined &&
data[key] !== '' &&
JSON.stringify(data[key]) !== '[]' &&
JSON.stringify(data[key]) !== '{}'
) {
obj[key] = data[key];
}
}
return obj;
};
import { AnyType } from 'src/common/types';
function func(data: Array<any>, key: string, value: any) {
return data.filter((item: any) => {
return item[key] == value;
});
}
/**
* 数组对象查找 返回一个数组,返回所有符合条件的数据
* @param objArr - 原始数组
* @param valueData - 查找的对象条件{age:18,num:1}
**/
export const findArrObjs = function (objArr: Array<any>, valueData: AnyType) {
const valueDataArr = [] as any[];
for (const key in valueData) {
valueDataArr.push({
key: key,
value: valueData[key],
});
}
let resArr = [] as any;
for (let i = 0; i < valueDataArr.length; i++) {
if (i == 0) {
const res = func(objArr, valueDataArr[i].key, valueDataArr[i].value);
resArr = res;
} else {
const res = func(resArr, valueDataArr[i].key, valueDataArr[i].value);
resArr = res;
}
}
return resArr;
};
export * from './del-arr-obj';
export * from './find-arr-objs';
export * from './no-repeat-obj-in-arr';
export * from './obj-del';
export * from './is-obj-equal';
export * from './del-empty-objkey';
export * from './json-str';
export * from './isEmpty';
export * from './maths';
export {
cloneDeep,
orderBy,
find,
findIndex,
size,
every,
some,
maxBy,
minBy,
sumBy,
random,
replace,
repeat,
uniqueId,
} from 'lodash-es';
/**
* 判断两个对象是否相等
**/
export const isObjEqual = function (obj1: any, obj2: any) {
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length === keys2.length) {
const sortKeys1 = keys1.sort();
const sortKeys2 = keys2.sort();
const sortStr1 = JSON.stringify(sortKeys1);
const sortStr2 = JSON.stringify(sortKeys2);
if (sortStr1 === sortStr2) {
let flag = true;
for (const key1 in obj1) {
if (obj1[key1] !== obj2[key1]) {
flag = false;
break;
}
}
return flag;
} else {
return false;
}
} else {
return false;
}
};
export const isEmpty = function (data: any) {
if (data === '' || data === null || data === undefined) {
return true;
} else {
const typeofs = Object.prototype.toString.call(data);
if (typeofs === '[object Array]') {
if (data.length > 0) {
return false;
} else {
return true;
}
} else {
if (Object.keys(data).length > 0) {
return false;
} else {
return true;
}
}
}
};
export const jsonStr = function (json_data: any) {
let cache = [] as any;
const json_str = JSON.stringify(json_data, function (key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
return;
}
cache.push(value);
}
return value;
});
cache = null; //释放cache
return json_str;
};
/**
* 返回了一个在指定值之间的随机整数
* @param min 这个值不小于 min (如果 min 不是整数,则不小于 min 的向上取整数)
* @param max 这个值小于(不等于)max
* @returns [min ,max )
*/
export const getRandomInt = function (min: number, max: number) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min; // 不含最大值,含最小值
};
function deduplicatObj(arr: Array<any>) {
const cloneArr = JSON.parse(JSON.stringify(arr));
const res = cloneArr.map((item: any) => {
const types = Object.prototype.toString.call(item);
if (types === '[object Array]') {
return handleArr(item);
} else if (types === '[object Object]') {
return handleObj(item);
} else {
return item;
}
});
return res;
}
function handleArr(data: Array<any>) {
return JSON.parse(JSON.stringify(deduplicatObj(data))).sort();
}
function handleObj(data: any) {
for (const key in data) {
if (Object.prototype.hasOwnProperty.call(data, key)) {
const element = data[key];
const types = Object.prototype.toString.call(element);
if (types === '[object Array]') {
data[key] = handleArr(element);
} else if (types === '[object Object]') {
data[key] = handleObj(element);
} else {
//
}
}
}
// 把对象按照默认顺序排序
const keyslist = Object.keys(data).sort();
const myobj = {} as any;
keyslist.map((item: string) => {
myobj[item] = data[item];
});
return myobj;
}
/**
* 数组对象去重 返回一个新数组
* @param data - 原始数组
**/
export const noRepeatObjInArr = function (data: Array<any>) {
const res = deduplicatObj(data);
const mySet: Set<string> = new Set();
res.map((item: any) => {
const JSONstr = JSON.stringify(item);
mySet.add('JSON_' + JSONstr);
});
const arr = [] as any[];
for (const item of mySet) {
const itemArr = item.split('JSON_', 2);
arr.push(JSON.parse(itemArr[1]));
}
return arr;
};
/**
* 删除对象的某个属性 返回一个删除后的新对象
* @param data - 原始对象
* @param key - 要删除的对象的属性的键名 'name' || ['name','age']
**/
export const objDel = function (data: any, key: string | Array<any>) {
const _data = JSON.parse(JSON.stringify(data));
if (typeof key === 'string') {
_data[key] = undefined;
} else if (Array.isArray(key)) {
for (const item of key) {
_data[item] = undefined;
}
}
const obj = {} as any;
for (const key in _data) {
if (_data[key]) {
obj[key] = _data[key];
}
}
return obj;
};
<template>
<div
id="allmap"
:style="{ width: width + 'px', height: height + 'px' }"
></div>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted } from 'vue';
import { isEmpty, cloneDeep } from 'src/common/utils';
interface Props {
id: string;
width: number;
height: number;
bMapPoint?: Array<number>; // 中心点坐标
mapLevel?: number; // 地图级别
navigationControl?: boolean; // 平移缩放控件
overviewMapControl?: boolean; // 缩略地图控件
scrollWheelZoom?: boolean; // 开启鼠标滚轮缩放
scaleControl?: boolean; // 比例尺控件
}
const props = withDefaults(defineProps<Props>(), {
id: 'map',
width: 100,
height: 100,
bMapPoint: () => [],
mapLevel: 12,
navigationControl: false,
overviewMapControl: false,
scrollWheelZoom: false,
scaleControl: false,
});
const bMapApi = ref(null);
const state = reactive({
bMapPoint: cloneDeep(props.bMapPoint),
});
onMounted(async () => {
let map = new (window as any).BMap.Map(props.id); // 创建Map实例
bMapApi.value = map;
let p = new Promise<void>(function (resolve) {
if (isEmpty(props.bMapPoint)) {
let myCity = new (window as any).BMap.LocalCity();
myCity.get((res: any) => {
state.bMapPoint.push(res.center.lng);
state.bMapPoint.push(res.center.lat);
resolve();
});
} else {
resolve();
}
});
p.then(() => {
map.centerAndZoom(
new (window as any).BMap.Point(state.bMapPoint[0], state.bMapPoint[1]),
props.mapLevel
);
});
if (props.navigationControl) {
map.addControl(new (window as any).BMap.NavigationControl());
}
if (props.overviewMapControl) {
map.addControl(new (window as any).BMap.OverviewMapControl());
}
if (props.scaleControl) {
map.addControl(new (window as any).BMap.ScaleControl());
}
if (props.scrollWheelZoom) {
map.enableScrollWheelZoom(true);
}
// 添加地图类型控件
// map.addControl(
// new window.BMap.MapTypeControl({
// mapTypes: [window.BMAP_NORMAL_MAP, window.BMAP_HYBRID_MAP],
// })
// );
// map.setCurrentCity('成都'); // 设置地图显示的城市 仅当设置城市信息时,MapTypeControl的切换功能才能可用
});
defineExpose({
bMapApi,
});
</script>
<style lang="scss" scoped></style>
<script lang="ts" setup>
import { onMounted, ref, reactive, computed } from 'vue';
import { date } from 'quasar';
interface Props {
modelValue: string;
format24h?: boolean;
withSeconds?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
modelValue: date.formatDate(Date.now(), 'YYYY/MM/DD HH:mm'),
format24h: false,
withSeconds: false,
});
const emit = defineEmits<{
(e: 'update:modelValue', value: string): void;
}>();
const dates = computed({
set(value: string) {
emit('update:modelValue', value);
},
get() {
return props.modelValue;
},
});
const timeMask = computed(() => {
if (props.withSeconds) {
return 'HH:mm:ss';
} else {
return 'HH:mm';
}
});
const dateRules = computed(() => {
let dateRegular: RegExp;
if (props.withSeconds) {
dateRegular =
/^-?[\d]+\/[0-1]\d\/[0-3]\d ([0-1]?\d|2[0-3]):[0-5]\d:[0-5]\d$/;
} else {
dateRegular = /^-?[\d]+\/[0-1]\d\/[0-3]\d (\d{2}):(\d{2})$/;
}
return [(v: string) => dateRegular.test(v)];
});
const dateProxyDate = ref('');
const timeProxyDate = ref('');
const dateLocale = reactive({
daysShort: '六_日_一_二_三_四_五'.split('_'),
months:
'一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split(
'_'
),
monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
firstDayOfWeek: 1,
format24h: true,
pluralDay: 'dias',
});
onMounted(() => {
getNowDate();
});
function getNowDate() {
dateProxyDate.value = date.formatDate(Date.now(), 'YYYY/MM/DD');
timeProxyDate.value = date.formatDate(Date.now(), timeMask.value);
}
function updateProxy() {
const _dates = dates.value;
const dateArr = _dates.split(' ');
dateProxyDate.value = dateArr[0];
timeProxyDate.value = dateArr[1];
}
function onClickDate() {
const datesStr = `${dateProxyDate.value} ${timeProxyDate.value}`;
dates.value = datesStr;
}
</script>
<template>
<div class="hcy-datetime-pick">
<q-input filled dense v-model="dates" :rules="dateRules">
<template v-slot:append>
<q-icon name="event" class="cursor-pointer">
<q-popup-proxy
@before-show="updateProxy"
transition-show="scale"
transition-hide="scale"
class="row"
>
<q-date
flat
square
minimal
v-model="dateProxyDate"
:locale="dateLocale"
mask="YYYY/MM/DD"
class="my-date"
>
</q-date>
<q-time
flat
square
v-model="timeProxyDate"
:mask="timeMask"
:format24h="format24h"
:with-seconds="withSeconds"
text-color="primary"
class="my-time"
>
<div class="row items-center justify-end q-gutter-sm">
<q-btn
label="此刻"
size="sm"
color="primary"
flat
@click="getNowDate"
/>
<q-btn
unelevated
label="确定"
size="sm"
color="primary"
@click="onClickDate"
v-close-popup
/>
</div>
</q-time>
</q-popup-proxy>
</q-icon>
</template>
</q-input>
</div>
</template>
<style lang="scss" scoped>
.my-date {
:deep(.q-date__main .q-date__content .q-date__view .q-date__navigation) {
> .relative-position {
color: $primary;
}
}
}
.my-time {
:deep(.q-time__header) {
background-color: white;
}
:deep(.q-time__main
.q-time__content
.q-time__container-child
.q-time__clock
.q-time__clock-circle
.q-time__clock-position--active) {
color: white !important;
}
}
</style>
<template>
<q-item
clickable
@click="onClick"
:active="pageStore.activeRouter?.path === link ? true : false"
active-class="bg-primary-bg-light"
>
<q-item-section v-if="icon" avatar>
<q-avatar size="md" square>
<img :src="icon" />
</q-avatar>
</q-item-section>
<q-item-section>
<q-item-label>{{ title }}</q-item-label>
<q-item-label caption>{{ caption }}</q-item-label>
</q-item-section>
</q-item>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs } from 'vue';
import { useRouter } from 'vue-router';
import { usePageStore } from 'src/common/hooks';
export default defineComponent({
name: 'EssentialLink',
props: {
active: {
type: Boolean,
required: true,
},
title: {
type: String,
required: true,
},
caption: {
type: String,
default: '',
},
link: {
type: String,
default: '#',
},
icon: {
type: String,
default: '',
},
},
setup(props) {
const pageStore = usePageStore();
const router = useRouter();
const state = reactive({
//
});
const onClick = () => {
const currentRouter = router.currentRoute.value.path;
if (currentRouter === props.link) return;
router.push(props.link);
};
return {
...toRefs(state),
onClick,
pageStore,
};
},
});
</script>
<template>
<q-form ref="myForm" class="my-form row fit">
<div
:class="['item', item.col || 'col-12']"
v-for="(item, index) in state.config"
:key="index"
>
<template v-if="item.solt">
<div>
<slot :name="item.solt"></slot>
</div>
</template>
<template v-else>
<q-input
v-if="item.type !== 'select'"
:type="item.type"
v-model="formValue[item.fild]"
v-bind="item.bind"
:disable="
item.bind.disable === undefined ? state.disable : item.bind.disable
"
:readonly="
item.bind.readonly === undefined
? state.readonly
: item.bind.readonly
"
/>
<q-select
v-if="item.type === 'select'"
v-bind="item.bind"
v-model="formValue[item.fild]"
:disable="
item.bind.disable === undefined ? state.disable : item.bind.disable
"
:readonly="
item.bind.readonly === undefined
? state.readonly
: item.bind.readonly
"
/>
</template>
</div>
</q-form>
</template>
<script lang="ts" setup>
import { onMounted, reactive, ref, watch } from 'vue';
import { cloneDeep, isObjEqual } from 'src/common/utils';
interface Props {
config: any;
modelValue: any;
disable?: boolean;
readonly?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
config: () => {
return {};
},
modelValue: () => {
return {};
},
disable: false,
readonly: false,
});
defineExpose({
validate,
reset,
});
const emit = defineEmits<{
(e: 'update:modelValue', value: any): void;
}>();
const myForm = ref<any>(null);
const state = reactive({
config: cloneDeep(props.config),
disable: props.disable,
readonly: props.readonly,
});
const formValue = ref<any>(cloneDeep(props.modelValue));
watch(
() => props.config,
(val) => {
state.config = cloneDeep(val);
},
{
deep: true,
}
);
watch(
() => props.modelValue,
(val: any) => {
if (!isObjEqual(val, formValue.value)) {
formValue.value = val;
}
},
{
deep: true,
}
);
watch(
formValue.value,
(val) => {
emit('update:modelValue', val);
},
{ deep: true }
);
onMounted(() => {
//
});
async function validate() {
return await myForm.value.validate().then((success: any) => {
if (success) {
return true;
} else {
return false;
}
});
}
function reset() {
myForm.value.resetValidation();
}
</script>
<style lang="scss" scoped>
.item {
padding: $padding-sm;
}
</style>
<template>
<q-tooltip
anchor="top middle"
self="bottom middle"
:offset="[6, 6]"
class="com-tooltip-sty"
>
<slot></slot>
</q-tooltip>
</template>
This diff is collapsed.
<!--
* 轮播图
-->
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
import { isEmpty } from 'src/common/utils';
// import * as echarts from 'echarts';
// type EChartsOption = echarts.EChartsOption;
interface Props {
itemKey: string;
list: any[];
times?: number;
navigation?: boolean; // 小圆点点击导航
}
const props = withDefaults(defineProps<Props>(), {
itemKey: 'id',
list: () => [],
times: 10000,
navigation: false,
});
const pointActive = ref<any>(1);
const lastIndex = ref(0);
const timer = ref<any>(null);
watch(
() => props.list,
() => {
listChange();
}
);
onMounted(() => {
//
});
onBeforeUnmount(() => {
offTimer();
});
// list改变
function listChange() {
console.log('listChange', props.list);
offTimer(); // 清除定时器
if (isEmpty(props.list)) {
resetIndex();
} else {
// 如果当前下标 > list长度,则下标重新开始
if (pointActive.value > props.list.length) {
resetIndex();
}
onStartTimer();
}
}
function onStartTimer() {
timer.value = setTimeout(() => {
const maxLength = props.list.length;
if (pointActive.value >= maxLength) {
pointActive.value = 1;
lastIndex.value = 0;
} else {
pointActive.value++;
lastIndex.value++;
}
onStartTimer();
}, props.times);
}
function onClickPoint(val: any, index: number) {
offTimer();
if (index > lastIndex.value) {
// 右
} else if (index < lastIndex.value) {
// 左
} else {
return;
}
pointActive.value = val[props.itemKey];
lastIndex.value = index;
onStartTimer();
}
function offTimer() {
if (timer.value) {
clearTimeout(timer.value);
timer.value = null;
}
}
function resetIndex() {
pointActive.value = 1;
lastIndex.value = 0;
}
</script>
<template>
<div class="carousel-box">
<div class="carousel">
<div class="carousel-content">
<div class="carousel-item-box">
<!-- item -->
<template v-for="(i, index) in props.list" :key="index">
<div
class="item-box opacity-in"
v-show="pointActive === i[props.itemKey]"
>
<!-- some item -->
<div class="my-item-box center">
<div class="fit" :id="`chart-pie-dom-${i[props.itemKey]}`">
{{ i.label }}
</div>
</div>
</div>
</template>
</div>
</div>
<div class="carousel-points" v-if="props.navigation">
<div
class="point"
:class="{ 'active-point': pointActive === i[props.itemKey] }"
v-for="(i, index) in props.list"
:key="index"
@click="onClickPoint(i, index)"
></div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
@keyframes opacity-in {
0% {
opacity: 0.5;
}
100% {
opacity: 1;
}
}
.carousel-box {
width: 100%;
height: 100%;
}
.carousel {
width: 100%;
height: 100%;
border: 1px solid $primary;
overflow: hidden;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: space-between;
}
.carousel-content {
flex: 1;
overflow: hidden;
}
.carousel-item-box {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
}
.item-box {
width: 100%;
height: 100%;
overflow: auto;
position: absolute;
background-color: pink;
top: 0;
left: 0;
}
.opacity-in {
animation: opacity-in 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}
.my-item-box {
width: 100%;
height: 100%;
color: #fff;
font-size: 40px;
}
.carousel-points {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: center;
padding: 4px;
padding-bottom: 0px;
}
.point {
width: 12px;
height: 12px;
margin-right: 4px;
margin-bottom: 4px;
border-radius: 50%;
border: 1px solid $primary;
cursor: pointer;
transition: all 0.5s;
}
.active-point {
height: 10px;
width: 30px;
border-radius: 10px;
background-color: $primary;
}
</style>
import DateTimePick from './DateTimePick.vue';
import BaiduMap from './BaiduMap.vue';
import MyForm from './MyForm.vue';
import MyTooltip from './MyTooltip.vue';
import CanvasStaticRoute from './canvas-static-route/CanvasStaticRoute.vue';
import CarouselWarp from './carousel-warp/CarouselWarp.vue';
export {
DateTimePick as ComDateTimePick,
BaiduMap as ComBaiduMap,
MyForm as ComForm,
MyTooltip as ComTooltip,
CanvasStaticRoute as ComCanvasStaticRoute,
CarouselWarp as ComCarouselWarp,
};
export default {
DateTimePick,
BaiduMap,
MyForm,
MyTooltip,
CanvasStaticRoute,
CarouselWarp,
};
export interface Todo {
id: number;
content: string;
}
export interface Meta {
totalCount: number;
}
export interface CanvasRoute {
x: number;
y: number;
[proppName: string]: any;
}
export interface CanvasStyle {
lineWidth?: number;
strokeStyle?: string;
lineJoin?: string;
lineCap?: string;
step?: number;
}
export interface CanvasData {
data: CanvasRoute[];
style?: CanvasStyle;
}
// 开发环境app配置
const development = {
name: 'TopPMS',
productName: 'TopPMS',
storagePrefix: '__ABC__',
langs: ['en-US', 'zh-CN', 'zh-TW'],
serverUrl: { base: 'http://139.196.104.13:9000' },
//http://192.168.2.100:29010
base_url: '',
};
// 生产环境app配置
const production = {
name: 'TopPMS',
productName: 'TopPMS',
storagePrefix: '__ABC__',
langs: ['en-US', 'zh-CN', 'zh-TW'],
// serverUrl: { base: '' },
base_url: '',
};
export default process.env.NODE_ENV === 'production' ? production : development;
export default {
num0: 'fa-solid fa-0', // 数字0
idCard: 'fa-regular fa-address-card', // 身份证
mapLocation: 'bi-pin-map-fill', // 地图定位
alipay: 'fa-brands fa-alipay', // 支付宝
play: 'fa-solid fa-circle-play', // 播放
pause: 'fa-solid fa-circle-pause', // 暂停
takeColor: 'fa-solid fa-palette', // 取色
reset: 'bi-arrow-counterclockwise', // 重置
refresh: 'bi-arrow-repeat', // 刷新
delete: 'bi-trash', // 删除
alarm_clock: 'bi-stopwatch', // 闹钟
};
// app global css in SCSS form
// 布局
.center {
display: flex;
justify-content: center;
align-items: center;
}
.container-height {
height: calc(100vh - 50px);
}
// 颜色
// 播放
.text-play {
color: #6cc4a1;
}
.bg-play {
background: #6cc4a1;
}
// 暂停
.text-pause {
color: #df7861;
}
.bg-pause {
background: #df7861;
}
// 导航栏激活颜色
.text-headeractive {
color: $primary-3;
}
.bg-headeractive {
background: $primary-3;
}
// tooltip样式
.com-tooltip-sty {
border: 1px solid rgba(9, 30, 66, 0.13);
color: $gray-light-text;
background-color: white;
box-shadow: rgba(0, 0, 0, 0.15) 0px 5px 15px 0px;
}
// Quasar SCSS (& Sass) Variables
// --------------------------------------------------
// To customize the look and feel of this app, you can override
// the Sass/SCSS variables found in Quasar's source Sass/SCSS files.
// Check documentation for full list of Quasar variables
// Your own variables (that are declared here) and Quasar's own
// ones will be available out of the box in your .vue/.scss/.sass files
// It's highly recommended to change the default colors
// to match your app's branding.
// Tip: Use the "Theme Builder" on Quasar's documentation website.
$space-base: 16px !default;
$padding-xs: ($space-base * 0.25);
$padding-sm: ($space-base * 0.5);
$padding-md: $space-base;
$padding-lg: ($space-base * 1.5);
$padding-xl: ($space-base * 3);
$primary: #78c0a8;
$secondary: #26a69a;
$accent: #9c27b0;
$dark: #1d1d1d;
$positive: #8bc24c;
$negative: #e8222d;
$info: #90c078;
$warning: #f7b32d;
$--color-white: #fff;
$--color-dark: #000;
$primary-10: mix($--color-dark, $primary, 50%);
$primary-9: mix($--color-dark, $primary, 40%);
$primary-8: mix($--color-dark, $primary, 30%);
$primary-7: mix($--color-dark, $primary, 20%);
$primary-6: mix($--color-dark, $primary, 10%);
$primary-5: mix($--color-white, $primary, 5%);
$primary-4: mix($--color-white, $primary, 10%);
$primary-3: mix($--color-white, $primary, 20%);
$primary-2: mix($--color-white, $primary, 30%);
$primary-1: mix($--color-white, $primary, 50%);
$primary-bg-light: rgba(120, 192, 168, 0.136);
.bg-primary-bg-light {
background: $primary-bg-light;
}
$border-color: rgba(0, 0, 0, 0.12);
$gray-text: #000000de;
$gray-light-text: #00000098;
/* eslint-disable */
declare namespace NodeJS {
interface ProcessEnv {
NODE_ENV: string;
VUE_ROUTER_MODE: 'hash' | 'history' | 'abstract' | undefined;
VUE_ROUTER_BASE: string | undefined;
}
}
import axios from 'axios';
import { Notify } from 'quasar';
import appConfig from 'src/config/app';
const $axios = axios.create();
// 请求方法
const request = (options: any) => {
const defaultOptins = {
baseURL: appConfig.base_url,
timeout: 30000,
};
const config = Object.assign(defaultOptins, options);
return $axios(config);
};
// http request 拦截器
$axios.interceptors.request.use(
(config: any) => {
return config;
},
(error) => {
return Promise.reject(error);
}
);
// http response 拦截器
$axios.interceptors.response.use(
(response: any) => {
return response;
},
async (error) => {
let msg = 'Unknown Error';
if (error.response.status === 500 || error.response.status === 504) {
msg = 'Internal Server Error';
} else {
msg = error.response.data.detail.msg; // 接口返回的错误信息
}
Notify.create({
message: msg,
type: 'negative',
position: 'top-right',
});
return Promise.reject(error);
}
);
export default request;
export function baidu_api_point(callback: any) {
//注意这里挂载在了window上
(window as any).callbackData = callback;
const url =
'https://api.map.baidu.com/location/ip?ak=RDBRKGErFTLbtmvUXp6X4UACeQGP5KlD&ip=&coor=bd09ll';
const fetchJsonp = function (url: string) {
const body = document.getElementsByTagName('body')[0];
//插入一个script
const script = document.createElement('script');
script.setAttribute('src', url);
body.appendChild(script);
};
fetchJsonp(url);
}
<!DOCTYPE html>
<html>
<head>
<title><%= productName %></title>
<meta charset="utf-8" />
<meta name="description" content="<%= productDescription %>" />
<meta name="format-detection" content="telephone=no" />
<meta name="msapplication-tap-highlight" content="no" />
<meta
name="viewport"
content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width<% if (ctx.mode.cordova || ctx.mode.capacitor) { %>, viewport-fit=cover<% } %>"
/>
<!-- <link
rel="icon"
type="image/png"
sizes="128x128"
href="icons/favicon-128x128.png"
/>
<link
rel="icon"
type="image/png"
sizes="96x96"
href="icons/favicon-96x96.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="icons/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="icons/favicon-16x16.png"
/> -->
<link rel="icon" sizes="128x128" type="image/ico" href="favicon.svg" />
<script
type="text/javascript"
src="http://api.map.baidu.com/getscript?v=3.0&ak=RDBRKGErFTLbtmvUXp6X4UACeQGP5KlD"
></script>
</head>
<body>
<!-- DO NOT touch the following DIV -->
<div id="q-app"></div>
</body>
</html>
<template>
<q-layout view="lHh Lpr lFf">
<q-header elevated>
<q-toolbar>
<q-btn flat dense round @click="toggleLeftDrawer">
<q-avatar>
<img
:src="
leftDrawerOpen
? require('./menuListIcons/toggle-left-drawer-show.svg')
: require('./menuListIcons/toggle-left-drawer-hide.svg')
"
/>
</q-avatar>
</q-btn>
<q-toolbar-title> Quasar App </q-toolbar-title>
<q-tabs
v-model="defaultRouter"
no-caps
shrink
active-color="white"
active-bg-color="headeractive"
>
<q-tab
class="my-tab"
v-for="page in tabsList"
:key="page.link"
:name="page.link"
:label="page.title"
@click.stop="clickTab(page)"
>
<q-btn
v-show="tabsList.length > 1"
dense
flat
round
size="sm"
icon="close"
@mousedown.stop="doNothing"
@click.stop="closeTab(page)"
>
</q-btn>
</q-tab>
</q-tabs>
<q-space />
<div>Quasar v{{ $q.version }}</div>
</q-toolbar>
</q-header>
<q-drawer v-model="leftDrawerOpen" show-if-above bordered>
<q-list>
<q-item-label header style="padding: 0">
<TopLeftLoading />
</q-item-label>
<EssentialLink
v-for="link in essentialLinks"
:key="link.title"
v-bind="link"
/>
</q-list>
</q-drawer>
<q-page-container>
<router-view />
</q-page-container>
</q-layout>
</template>
<script lang="ts">
import { defineComponent, ref, onMounted, reactive, toRefs } from 'vue';
import { onBeforeRouteUpdate, useRouter } from 'vue-router';
import { usePageStore } from 'src/common/hooks';
import EssentialLink from 'components/EssentialLink.vue';
import TopLeftLoading from './TopLeftLoading.vue';
export default defineComponent({
name: 'MainLayout',
components: {
EssentialLink,
TopLeftLoading,
},
setup() {
const pageStore = usePageStore();
const router = useRouter();
const leftDrawerOpen = ref(false);
const defaultRouter = ref('/page1');
const linksList = ref<any>([]);
const state = reactive({
tabsList: [] as any,
});
onBeforeRouteUpdate((to, from, next) => {
defaultRouter.value = to.path;
if (to.matched.length == 3) {
pageStore.addRoute(to as any);
getTabsList();
}
next();
});
onMounted(() => {
getLinksList();
const path = router.currentRoute.value.path;
defaultRouter.value = path;
pageStore.addRoute(router.currentRoute.value as any);
getTabsList();
});
const getLinksList = () => {
const lists = [
{
title: '一',
caption: '日历',
icon: require('./menuListIcons/page1.svg'),
link: '/page1',
active: true,
},
{
title: '贰',
caption: '2',
icon: require('./menuListIcons/page2.svg'),
link: '/page2',
active: false,
},
{
title: '叁',
caption: '3',
icon: require('./menuListIcons/page3.svg'),
link: '/page3',
active: false,
},
{
title: '四',
caption: '4',
icon: require('./menuListIcons/page4.svg'),
link: '/page4',
active: false,
},
{
title: '五',
caption: '5',
icon: require('./menuListIcons/page5.svg'),
link: '/page5',
active: false,
},
{
title: '六',
caption: '一些js练习',
icon: require('./menuListIcons/page6.png'),
link: '/page6',
active: false,
},
];
for (const item of lists) {
if (item.link === defaultRouter.value) {
item.active = true;
} else {
item.active = false;
}
}
linksList.value = lists;
};
const getTabsList = () => {
state.tabsList = pageStore.tabRouterList.map((item: any) => {
return {
title: item.meta?.title,
link: item.path,
keepalive: item.meta?.keepalive,
permission: item.meta?.permission,
};
});
};
const clickTab = (page: any) => {
router.push(page.link);
};
const closeTab = (page: any) => {
pageStore.removePage(page.link);
getTabsList();
router.push(pageStore.activeRouter.path);
};
const doNothing = () => {
// to prevent tab close button ripple effect
};
return {
...toRefs(state),
essentialLinks: linksList,
leftDrawerOpen,
toggleLeftDrawer() {
leftDrawerOpen.value = !leftDrawerOpen.value;
},
linksList,
pageStore,
defaultRouter,
clickTab,
closeTab,
doNothing,
};
},
});
</script>
<style lang="scss" scoped>
.my-tab {
:deep(.q-tab__content) {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
> button {
color: transparent;
}
&:hover > button {
color: white;
}
.q-tab__label {
flex: 1;
}
}
}
</style>
<script lang="ts" setup>
import { onMounted } from 'vue';
onMounted(() => {
//
});
</script>
<template>
<div class="top-left-box row items-center justify-center overflow-hidden">
<span>间谍过家家</span>
</div>
</template>
<style lang="scss" scoped>
.top-left-box {
height: 50px;
padding: $padding-sm;
}
</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="1652088790468" class="icon" viewBox="0 0 1067 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1324" xmlns:xlink="http://www.w3.org/1999/xlink" width="520.99609375" height="500"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
</style></defs><path d="M43.389831 980.610169V173.559322c0-71.59322 58.576271-130.169492 130.169491-130.169491h720.271186c71.59322 0 130.169492 58.576271 130.169492 130.169491v807.050847H43.389831z" fill="#94D6D0" p-id="1325"></path><path d="M43.389831 251.661017h980.610169v728.949152H43.389831z" fill="#F0F0FF" p-id="1326"></path><path d="M648.647593 521.719322l91.118644-60.745763-50.267118-31.678915-56.40678 394.847458 64.433898 9.207322 56.40678-394.847458 10.292068-72.053152-60.559187 40.374237-91.118644 60.745763zM305.173695 592.271186h199.59322v65.084746h-199.59322z" fill="#ABABD1" p-id="1327"></path><path d="M372.427932 514.169492h65.084746v221.288135h-65.084746z" fill="#ABABD1" p-id="1328"></path><path d="M43.389831 922.033898h980.610169V980.610169H43.389831z" fill="#6E6E96" opacity=".07" p-id="1329"></path><path d="M379.661017 43.389831h333.377085v208.271186H379.661017z" fill="#FFE95F" p-id="1330"></path><path d="M1024 173.559322c0-71.59322-58.576271-130.169492-130.169492-130.169491h-210.440677v208.271186H1024V173.559322z" fill="#FF9780" p-id="1331"></path><path d="M43.389831 208.813559h980.610169v83.525424H43.389831z" fill="#6E6E96" opacity=".15" p-id="1332"></path></svg>
\ No newline at end of file
<?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="1652088596536" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1161" xmlns:xlink="http://www.w3.org/1999/xlink" width="500" height="500"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
</style></defs><path d="M970.443515 514.142259c0-252.006828-204.294427-456.301255-456.301256-456.301255C262.139715 57.841004 57.841004 262.135431 57.841004 514.142259S262.139715 970.443515 514.142259 970.443515L970.443515 514.142259z" fill="#93DBCF" p-id="1162"></path><path d="M514.142259 970.443515S482.402544 514.142259 970.443515 514.142259L514.142259 970.443515z" fill="#93DBCF" p-id="1163"></path><path d="M927.131314 556.34477l40.612954-40.612954c-488.040971 0-456.301255 456.301255-456.301255 456.301255l39.640368-39.640368c14.087498-120.009372 80.398996-343.035715 376.047933-376.047933z" fill="#ABFFF1" opacity=".36" p-id="1164"></path><path d="M462.728033 850.476987a383.010276 383.010276 0 0 0 18.787616 118.796854c10.779849 0.762644 21.653958 1.169674 32.62661 1.169674L970.443515 514.142259c0-9.006059-0.287063-17.943565-0.80549-26.821087a382.941724 382.941724 0 0 0-123.449841-20.30862C634.408703 467.012552 462.728033 638.693222 462.728033 850.476987z" fill="#87C9BF" p-id="1165"></path></svg>
\ No newline at end of file
<?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="1652088920076" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1489" xmlns:xlink="http://www.w3.org/1999/xlink" width="500" height="500"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
</style></defs><path d="M992.278549 713.920521c0 45.924712-37.574764 83.499476-83.499476 83.499476H115.220927c-45.924712 0-83.499476-37.574764-83.499476-83.499476V104.374345C31.721451 58.449633 69.296215 20.874869 115.220927 20.874869h793.558146c45.924712 0 83.499476 37.574764 83.499476 83.499476v609.546176z" fill="#B1E3C4" p-id="1490"></path><path d="M109.780936 236.67509s122.606456 30.018062 122.606456-122.606456h555.952037s-30.030587 122.606456 122.606455 122.606456l-2.39226 340.189391s-122.606456-30.018062-122.606455 122.61063H232.387392s30.026412-122.610631-122.606456-122.61063V236.67509z" fill="#93BDA3" p-id="1491"></path><path d="M378.402926 246.323454h271.373297v41.749739h-271.373297z" fill="#FFFFFF" p-id="1492"></path><path d="M292.815963 352.785286h484.296961v41.749739h-484.296961zM292.815963 469.684553h271.373297v41.749738h-271.373297z" fill="#FFFFFF" opacity=".39" p-id="1493"></path><path d="M589.472901 772.917075a41.753913 41.753913 0 0 1-40.63502-51.343827l17.768689-75.249728-62.99618-56.587595a41.745563 41.745563 0 1 1 27.90135-72.811543h70.590457l34.627233-79.75035a41.758088 41.758088 0 0 1 37.837787-25.120817h0.459248a41.749738 41.749738 0 0 1 37.917112 24.285822l37.111342 80.585345h71.254278a41.749738 41.749738 0 0 1 25.667739 74.677756l-59.7898 46.613583 20.69952 79.696075A41.749738 41.749738 0 0 1 745.683721 764.020206l-69.237765-42.367634-63.188229 43.820525a41.653714 41.653714 0 0 1-23.784826 7.443978z m85.557739-142.834203c7.535828 0 15.08418 2.037387 21.789188 6.137211l4.262648 2.609359-1.60319-6.174787a41.762263 41.762263 0 0 1 7.13503-35.7169 41.728863 41.728863 0 0 1-21.213041-20.795545l-9.251742-20.089974-8.362473 19.259154a41.762263 41.762263 0 0 1-28.594396 23.976875l1.640765 1.473766a41.749738 41.749738 0 0 1 13.689739 34.706557 41.678763 41.678763 0 0 1 20.507472-5.385716z" p-id="1494"></path><path d="M908.779073 755.670259H115.220927c-45.924712 0-83.499476-37.574764-83.499476-83.499476v41.749738c0 45.924712 37.574764 83.499476 83.499476 83.499476h793.558146c45.924712 0 83.499476-37.574764 83.499476-83.499476v-41.749738c0 45.924712-37.574764 83.499476-83.499476 83.499476z" fill="#93BDA3" opacity=".3" p-id="1495"></path><path d="M627.653037 737.905745l2.187686 265.219386 79.332852-80.309796 80.313971 79.324502-2.187686-265.215211" fill="#A8D6F7" p-id="1496"></path><path d="M921.007571 593.75225c0 120.923941-98.02421 218.927276-218.931451 218.927276-120.898891 0-218.927276-98.020035-218.927276-218.927276 0-120.919766 98.028385-218.927276 218.927276-218.927277 120.915591-0.004175 218.931451 98.003335 218.931451 218.927277z" fill="#FFD28F" p-id="1497"></path><path d="M744.731827 379.008297c84.054748 23.747251 145.669011 100.971741 145.669011 192.637466 0 110.570006-89.649213 200.210869-200.227568 200.210869-110.557481 0-200.223394-89.649213-200.223394-200.210869 0-20.778845 3.168805-40.806194 9.047168-59.66455a218.296855 218.296855 0 0 0-15.8482 81.783561c0 120.898891 98.028385 218.927276 218.927276 218.927277 120.919766 0 218.931451-98.01586 218.931451-218.927277 0-106.336583-75.784124-194.908652-176.275744-214.756477z" fill="#E8B76D" opacity=".76" p-id="1498"></path><path d="M704.860827 593.505926m-71.943148 0a71.943149 71.943149 0 1 0 143.886297 0 71.943149 71.943149 0 1 0-143.886297 0Z" fill="#E8B76D" p-id="1499"></path><path d="M704.860827 686.323944c-51.181004 0-92.813843-41.641189-92.813842-92.818018s41.637014-92.818018 92.813842-92.818018 92.813843 41.641189 92.813843 92.818018-41.632839 92.818018-92.813843 92.818018z m0-143.886297c-28.156023 0-51.064105 22.908081-51.064104 51.068279s22.908081 51.06828 51.064104 51.06828 51.064105-22.908081 51.064105-51.06828-22.908081-51.06828-51.064105-51.068279z" fill="#D68989" p-id="1500"></path><path d="M578.066873 538.262673a16.699895 16.699895 0 0 1-14.533084-24.903719 161.905484 161.905484 0 0 1 57.952812-59.422402 16.699895 16.699895 0 0 1 17.121567 28.677895 128.430544 128.430544 0 0 0-45.983161 47.139629 16.67902 16.67902 0 0 1-14.558134 8.508597z" fill="#FFFFFF" p-id="1501"></path></svg>
\ No newline at end of file
This diff is collapsed.
<?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="1659322568882" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1337" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
</style></defs><path d="M762.71616 507.5968c-33.66912-66.4576-65.80224-133.67296-92.44672-203.24352l-61.25568-160.03072c-5.61152-14.66368-18.08384-27.01312-34.79552-32.48128-13.37344-4.36224-30.1056-5.34528-47.37024 5.0176-9.23648 5.55008-20.48 5.55008-29.71648 0-17.26464-10.36288-33.9968-9.37984-47.37024-5.0176-16.71168 5.46816-29.184 17.8176-34.79552 32.48128l-64.12288 167.5264c-25.53856 66.70336-56.44288 131.09248-89.00608 194.64192-20.52096 40.0384-31.70304 85.62688-30.67904 133.9392 3.03104 143.11424 126.89408 269.18912 269.94688 274.59584 160.09216 6.0416 291.77856-121.93792 291.77856-280.69888 0.02048-45.58848-10.8544-88.63744-30.16704-126.73024z" fill="#A4C257" p-id="1338"></path><path d="M512.12288 921.6c-3.74784 0-7.49568-0.06144-11.24352-0.2048-146.5344-5.5296-272.93696-134.12352-276.0704-280.82176-1.00352-47.59552 9.8304-94.94528 31.37536-136.97024 26.60352-51.89632 60.7232-120.85248 88.73984-194.02752l64.12288-167.5264c6.5536-17.14176 20.6848-30.35136 38.74816-36.2496 18.3296-5.98016 36.53632-4.05504 52.61312 5.61152 7.24992 4.36224 15.91296 4.36224 23.16288 0 16.09728-9.66656 34.304-11.59168 52.61312-5.61152 18.08384 5.91872 32.19456 19.12832 38.74816 36.2496l61.25568 160.03072c28.79488 75.22304 64.38912 147.80416 92.18048 202.6496 20.48 40.40704 30.86336 84.00896 30.86336 129.61792 0 78.78656-31.27296 152.28928-88.02304 206.9504-54.02624 52.0192-124.35456 80.30208-199.08608 80.30208zM468.5824 115.07712c-5.48864 0-11.10016 0.94208-16.83456 2.80576-14.41792 4.7104-25.64096 15.17568-30.8224 28.71296l-64.12288 167.5264c-28.24192 73.74848-62.54592 143.09376-89.2928 195.2768-20.5824 40.16128-30.94528 85.42208-29.98272 130.90816 2.9696 140.1856 123.8016 263.10656 263.84384 268.3904 75.3664 2.8672 146.82112-24.33024 201.05216-76.55424 54.25152-52.24448 84.13184-122.49088 84.13184-197.79584 0-43.58144-9.9328-85.25824-29.4912-123.86304-27.93472-55.11168-63.71328-128.08192-92.71296-203.85792l-61.25568-160.03072c-5.18144-13.53728-16.42496-24.00256-30.84288-28.71296-14.92992-4.89472-29.10208-3.3792-42.12736 4.42368a35.1232 35.1232 0 0 1-36.2496 0c-8.02816-4.8128-16.4864-7.22944-25.2928-7.22944z" fill="#426126" p-id="1339"></path><path d="M731.97568 508.08832c-29.55264-59.2896-57.73312-119.25504-81.1008-181.32992l-53.73952-142.76608c-4.93568-13.08672-15.85152-24.10496-30.53568-28.9792-11.42784-3.80928-25.68192-4.7104-40.40704 3.7888-8.84736 5.12-19.51744 5.12-28.3648 0-14.72512-8.51968-28.9792-7.59808-40.40704-3.7888-14.66368 4.87424-25.6 15.89248-30.53568 28.9792l-56.25856 149.46304c-22.40512 59.51488-49.52064 116.96128-78.09024 173.6704-19.2512 38.21568-29.14304 82.10432-26.56256 128.55296 7.08608 127.95904 110.2848 230.95296 236.21632 235.9296 140.57472 5.55008 256.26624-108.68736 256.26624-250.42944-0.02048-40.71424-9.56416-79.13472-26.48064-113.09056z" fill="#E9E776" p-id="1340"></path><path d="M665.088 526.39744c34.4064-9.4208 52.18304-47.57504 36.98688-79.85152-18.49344-39.30112-35.88096-79.09376-51.2-119.78752l-53.73952-142.76608c-4.93568-13.08672-15.85152-24.10496-30.53568-28.9792-11.42784-3.7888-25.66144-4.7104-40.38656 3.7888-8.86784 5.12-19.5584 5.12-28.40576 0-14.72512-8.4992-28.95872-7.5776-40.38656-3.7888-14.66368 4.87424-25.6 15.89248-30.53568 28.9792l-56.25856 149.46304c-22.40512 59.51488-49.52064 116.96128-78.09024 173.6704-5.03808 10.01472-9.44128 20.41856-13.14816 31.15008-15.1552 43.90912 24.76032 86.9376 69.57056 74.67008l316.12928-86.54848z" fill="#F4F0AB" p-id="1341"></path><path d="M674.34496 586.05568c9.97376 106.8032-70.30784 194.3552-157.02016 194.3552s-164.0448-87.28576-157.02016-194.3552c7.29088-111.0016 113.82784-194.3552 157.02016-194.3552 40.448 0 147.1488 88.65792 157.02016 194.3552z" fill="#FBD947" p-id="1342"></path><path d="M648.92928 586.05568c8.27392 86.71232-58.368 157.77792-130.39616 157.77792s-136.21248-70.8608-130.39616-157.77792c6.0416-90.112 94.5152-157.77792 130.39616-157.77792 33.60768 0 122.20416 71.96672 130.39616 157.77792z" fill="#7B4104" p-id="1343"></path><path d="M518.5536 746.86464c-33.44384 0-67.01056-15.38048-92.07808-42.1888-29.24544-31.27296-44.29824-74.56768-41.32864-118.82496 6.22592-92.79488 96.82944-160.62464 133.40672-160.62464 33.28 0 124.86656 71.18848 133.40672 160.52224 4.07552 42.76224-9.9328 85.2992-38.46144 116.67456-25.68192 28.2624-60.29312 44.4416-94.94528 44.4416z m0-315.57632c-33.91488 0-121.46688 67.072-127.36512 154.97216-2.8672 42.57792 11.61216 84.23424 39.71072 114.2784 23.92064 25.6 55.86944 40.26368 87.6544 40.26368 32.9728 0 65.9456-15.4624 90.46016-42.45504 27.38176-30.12608 40.83712-70.94272 36.90496-112.0256-8.06912-84.60288-96.54272-155.0336-127.36512-155.0336z" fill="#663904" p-id="1344"></path><path d="M498.91328 568.29952c-12.02176 41.73824-43.29472 68.38272-64.32768 60.96896s-27.97568-47.45216-11.79648-87.83872c16.77312-41.86112 53.84192-64.65536 64.32768-60.96896 9.80992 3.4816 23.69536 46.55104 11.79648 87.83872z" fill="#B2855D" p-id="1345"></path></svg>
\ No newline at end of file
<?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="1652146029925" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1827" xmlns:xlink="http://www.w3.org/1999/xlink" width="500" height="500"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
</style></defs><path d="M321.030145 412.290992l-60.146254 25.758484c-51.749842 22.16187-113.75909-5.783045-137.874516-62.099811-24.128364-56.290891-17.853696-148.340922 67.637043-185.005685 84.339305-36.134327 156.439773 22.342994 180.555199 78.646822 24.128364 56.355578 1.539558 120.53832-50.171472 142.70019z" fill="#F3F3F3" p-id="1828"></path><path d="M223.559318 452.125433c-43.857991 0-86.91386-27.931977-106.501175-73.652963-13.636083-31.83909-16.482325-70.754972-7.59429-104.08187 7.658977-28.68235 27.517979-67.481794 78.633885-89.371977 89.695414-38.424258 164.55156 24.839924 189.055111 82.036437 25.590297 59.719318 1.552495 127.524548-53.574024 151.135414l-60.146254 25.771421a100.912192 100.912192 0 0 1-39.873253 8.163538z m19.406191-265.851876a125.493367 125.493367 0 0 0-49.718661 10.634592c-86.072925 36.871762-85.07674 127.809172-64.234492 176.479899 22.782868 53.160025 80.820316 79.487757 129.374605 58.684321l60.146254-25.771421c48.567227-20.803437 69.551788-80.988503 46.781858-134.148529-17.698446-41.154062-63.794618-85.840051-122.414252-85.84005z" fill="#CFD1D1" p-id="1829"></path><path d="M702.969855 412.290992l60.146254 25.758484c51.749842 22.16187 113.75909-5.783045 137.887454-62.099811 24.115426-56.290891 17.853696-148.340922-67.637044-185.005685-84.352243-36.134327-156.45271 22.342994-180.568136 78.646822-24.115426 56.355578-1.539558 120.53832 50.171472 142.70019z" fill="#F3F3F3" p-id="1830"></path><path d="M800.45362 452.125433a101.015692 101.015692 0 0 1-39.886191-8.163538l-60.146254-25.732609c-55.126519-23.610865-79.151383-91.416096-53.574024-151.135414 24.50355-57.196513 99.372634-120.460695 189.068048-82.036437 51.115907 21.890183 70.961971 60.689627 78.620948 89.371978 8.888035 33.326898 6.054732 72.24278-7.59429 104.081869-19.574378 45.720985-62.643184 73.61415-106.488237 73.614151z m-94.935086-45.824485l60.146254 25.771421c48.567227 20.803437 106.604675-5.524296 129.374606-58.684321 12.536399-29.277473 15.149766-65.036614 6.986228-95.659583-6.921541-25.874921-24.878737-60.974251-71.156033-80.820316-45.785673-19.626128-83.588932-8.435224-107.23861 4.398737-28.138977 15.266203-52.37084 41.749185-64.829615 70.845533-22.782868 53.160025-1.798307 113.345092 46.76892 134.148529z" fill="#CFD1D1" p-id="1831"></path><path d="M884.378926 593.609501c0 86.887985-29.096349 136.063272-103.900745 190.439419-66.602047 48.437852-173.116159 60.081567-270.5223 60.081566-107.380922 0-220.260265-19.690815-288.505369-77.159014-63.277119-53.250587-81.790625-106.358863-81.790626-185.354997 0-164.241061 163.529501-332.233986 370.32187-332.233986s374.39717 179.985951 374.39717 344.227012z" fill="#F3F3F3" p-id="1832"></path><path d="M509.955881 850.599217c-59.111257 0-113.086342-5.783045-160.42451-17.206823-55.100644-13.299709-99.618446-33.973771-132.272597-61.465875-32.175464-27.091042-53.2894-54.246772-66.420922-85.464864-12.057713-28.669413-17.672571-61.983373-17.672571-104.79343 0-82.411623 39.963816-167.126115 109.657915-232.434416a393.725736 393.725736 0 0 1 119.555073-76.939077 385.238762 385.238762 0 0 1 147.577612-29.303349 370.735869 370.735869 0 0 1 148.315048 31.218093 406.158636 406.158636 0 0 1 120.939381 81.10494c34.129021 33.016399 62.345622 71.919343 81.583626 112.555906 19.66494 41.464561 30.053721 84.986178 30.05372 125.842679 0 45.048238-7.853039 80.212255-24.710549 110.5506-16.482325 29.756159-41.72331 55.954517-81.855313 85.115553-56.795452 41.179937-146.529678 61.220063-274.325913 61.220063z m0-594.747998c-95.82777 0-187.593178 36.496576-258.283462 102.775187-67.09367 62.863121-105.569678 144.149185-105.569677 222.990069 0 82.73506 21.540872 131.638661 79.487757 180.412887s158.936702 75.632394 284.365382 75.632394c124.962931 0 212.174352-19.250941 266.718686-58.878383 74.739709-54.337334 101.235629-102.788124 101.235629-185.199747 0-78.206949-40.261377-163.827063-107.691422-228.993051-72.488591-70.121036-164.913809-108.713481-260.262893-108.713481z" fill="#CFD1D1" p-id="1833"></path><path d="M246.665622 578.912546a78.025824 76.26633 0 1 0 156.051649 0 78.025824 76.26633 0 1 0-156.051649 0Z" fill="#42393B" p-id="1834"></path><path d="M275.723159 557.720985a19.755502 19.302691 0 1 0 39.511004 0 19.755502 19.302691 0 1 0-39.511004 0Z" fill="#FFFFFF" p-id="1835"></path><path d="M621.282729 577.036614a78.025824 76.26633 0 1 0 156.051649 0 78.025824 76.26633 0 1 0-156.051649 0Z" fill="#42393B" p-id="1836"></path><path d="M650.353203 555.845054a19.755502 19.302691 0 1 0 39.511004 0 19.755502 19.302691 0 1 0-39.511004 0Z" fill="#FFFFFF" p-id="1837"></path><path d="M469.422817 741.782236c-31.94259 0-41.956184-26.638231-42.771244-40.727125a6.480374 6.480374 0 0 1 12.93746-0.776248c0.194062 2.936804 2.690992 28.565913 29.859659 28.565913 29.626785 0 36.393076-13.623146 36.664763-14.231207v0.116437l11.928339 5.019735c-0.452811 0.931497-9.793658 22.032495-48.618977 22.032495z" fill="#CFD1D1" p-id="1838"></path><path d="M554.577183 741.782236c-38.812382 0-48.153228-21.100998-48.541352-21.993683l11.928338-5.032672v-0.116437c0.271687 0.582186 7.050916 14.231207 36.664763 14.231207 27.168667 0 29.665597-25.642047 29.872597-28.565913a6.480374 6.480374 0 0 1 12.93746 0.776247c-0.905622 14.06302-10.906279 40.701251-42.861806 40.701251z" fill="#CFD1D1" p-id="1839"></path><path d="M245.824687 694.418193m-39.239317 0a39.239318 39.239318 0 1 0 78.478635 0 39.239318 39.239318 0 1 0-78.478635 0Z" fill="#FFBECC" p-id="1840"></path><path d="M776.907442 694.418193m-39.239318 0a39.239318 39.239318 0 1 0 78.478635 0 39.239318 39.239318 0 1 0-78.478635 0Z" fill="#FFBECC" p-id="1841"></path></svg>
\ No newline at end of file
This diff is collapsed.
<template>
<div class="q-gutter-md overflow-hidden">
<q-virtual-scroll
ref="virtualListRef"
:items="heavyList"
v-slot="{ item, index }"
class="container-height"
:virtual-scroll-slice-ratio-before="1"
:virtual-scroll-slice-ratio-after="0.1"
:virtual-scroll-item-size="600"
:virtual-scroll-sticky-size-start="0"
:virtual-scroll-sticky-size-end="10"
>
<q-item :key="index" v-if="item.id === '1'">
<div class="q-gutter-sm full-width">
<q-btn
outline
label="success"
color="positive"
@click="onClick('success')"
/>
<q-btn
outline
label="error"
color="negative"
@click="onClick('error')"
/>
<q-btn
outline
label="warn"
color="warning"
@click="onClick('warn')"
/>
<q-btn outline label="info" color="info" @click="onClick('info')" />
</div>
</q-item>
<q-item :key="index" dense v-if="item.id === '2'">
<div class="q-gutter-sm full-width">
<Com.DateTimePick
style="width: 220px"
v-model="dates"
format24h
with-seconds
/>
</div>
</q-item>
<q-item :key="index" dense v-if="item.id === '3'">
<div class="actions full-width">
<div class="q-ml-sm">
<q-btn
round
color="primary"
:icon="ICON.mapLocation"
@click="getLocation"
title="定位"
/>
</div>
<div class="q-mr-sm q-gutter-sm">
<q-btn
v-if="!state.isPlay"
round
color="play"
:icon="ICON.play"
@click="chartRaceRun"
title="开始"
/>
<q-btn
v-else
round
color="pause"
:icon="ICON.pause"
@click="chartRaceStop"
title="停止"
/>
</div>
</div>
</q-item>
<q-item :key="index" dense v-if="item.id === '4'">
<div class="map full-width">
<div class="left-area q-ml-sm" ref="leftMapRef">
<template v-if="state.isRenderMap">
<Com.BaiduMap
id="allmap"
ref="allmapRef"
:scrollWheelZoom="false"
navigationControl
overviewMapControl
scaleControl
:width="state.width"
:height="state.height"
/>
</template>
</div>
<div v class="right-area q-mr-sm">
<!-- 动态排序柱状图 -->
<ChartsRace ref="faChartsRaceRef" />
</div>
</div>
</q-item>
<q-item :key="index" dense v-if="item.id === '5'">
<div class="map full-width">
<div class="left-area q-ml-sm">
<!-- 动态数据 -->
<ChartDynamic />
</div>
<div class="right-area q-mr-sm">
<!-- 时钟 -->
<ChartsClock />
</div>
</div>
</q-item>
<q-item :key="index" dense v-if="item.id === '6'">
<div class="map full-width">
<div class="left-area q-ml-sm">
<!-- 多Y轴示例 -->
<ChartMultipleY />
</div>
<div class="right-area q-mr-sm">
<!-- 联动和共享数据集 -->
<ChartShareDataset />
</div>
</div>
</q-item>
<q-item :key="index" dense v-if="item.id === '7'">
<div class="actions full-width">
<div class="q-ml-sm">
<q-btn color="primary" label="重置图节点" @click="resetChartNode" />
</div>
</div>
</q-item>
<q-item :key="index" dense v-if="item.id === '8'">
<div class="map full-width">
<div class="left-area q-ml-sm">
<!-- 动态增加图节点 -->
<ChartGraphDynamic ref="faGraphDynamicChartRef" />
</div>
<div class="right-area q-mr-sm">2</div>
</div>
</q-item>
<q-item :key="index" dense v-if="index > 7">
<ChartItem :id="`item-chart${item.id}`" />
</q-item>
</q-virtual-scroll>
</div>
</template>
<script lang="ts">
export default {
name: 'PAGE1',
};
</script>
<script lang="ts" setup>
import { ref, reactive, onMounted, nextTick } from 'vue';
import { date, dom } from 'quasar';
import { useMessage } from 'src/common/hooks';
import ICON from 'src/config/icons';
import Com from 'src/components';
import ChartsRace from './elements/ChartsRace.vue';
import ChartDynamic from './elements/ChartDynamic.vue';
import ChartsClock from './elements/ChartsClock.vue';
import ChartMultipleY from './elements/ChartMultipleY.vue';
import ChartShareDataset from './elements/ChartShareDataset.vue';
import ChartGraphDynamic from './elements/ChartGraphDynamic.vue';
import ChartItem from './elements/ChartItem.vue';
// function renewStore() {
// user_store.$patch((state) => {
// state.count++;
// state.arr.push(1);
// });
// user_store.changeState(10);
// }
const { height, width } = dom;
const { success, error, warn, info } = useMessage();
const dates = ref(date.formatDate(Date.now(), 'YYYY/MM/DD HH:mm:ss'));
const virtualListRef = ref<any>(null);
const leftMapRef = ref<any>(null);
const allmapRef = ref<any>(null);
const faChartsRaceRef = ref<any>(null);
const faGraphDynamicChartRef = ref<any>(null);
const state = reactive({
width: 0,
height: 0,
isRenderMap: false,
bMapApi: null as any,
isPlay: true,
});
const heavyList = ref<any>([
{ id: '1' },
{ id: '2' },
{ id: '3' },
{ id: '4' },
{ id: '5' },
{ id: '6' },
{ id: '7' },
{ id: '8' },
]);
onMounted(() => {
for (let index = 0; index < 500; index++) {
heavyList.value.push({
id: String(heavyList.value.length + 1),
});
}
setTimeout(() => {
console.log('宽', width(leftMapRef.value), '高', height(leftMapRef.value));
if (leftMapRef.value) {
state.width = width(leftMapRef.value);
state.height = height(leftMapRef.value) - 2;
state.isRenderMap = true;
nextTick(() => {
state.bMapApi = allmapRef.value.bMapApi;
});
}
}, 500);
});
function onClick(type: string) {
switch (type) {
case 'success':
success('成功');
break;
case 'error':
error('失败');
break;
case 'warn':
warn('警告');
break;
case 'info':
info('提示信息');
break;
default:
break;
}
}
function getLocation() {
let myCity = new (window as any).BMap.LocalCity();
myCity.get((result: any) => {
const cityName = result.name;
state.bMapApi = allmapRef.value.bMapApi;
state.bMapApi.setCenter(cityName);
});
}
function chartRaceRun() {
state.isPlay = true;
faChartsRaceRef.value.setTimer();
}
function chartRaceStop() {
state.isPlay = false;
faChartsRaceRef.value.clearTimer();
}
function resetChartNode() {
faGraphDynamicChartRef.value.reset();
}
</script>
<style lang="scss" scoped>
.actions {
display: grid;
grid-template-columns: repeat(2, 1fr);
column-gap: $padding-md;
}
.map {
display: grid;
grid-template-columns: repeat(2, 1fr);
column-gap: $padding-md;
> div {
border: 1px solid $border-color;
height: 600px;
}
}
</style>
import request from 'src/http';
// 获取
export function getLocation() {
return request({
url: '/location/ip?ak=RDBRKGErFTLbtmvUXp6X4UACeQGP5KlD&ip=192.168.2.103&coor=bd09ll',
method: 'get',
});
}
export const colorList = [
'#FF7396',
'#F4E06D',
'#C499BA',
'#B25068',
'#3AB0FF',
'#FFB562',
'#F87474',
'#A0D995',
'#6CC4A1',
'#4CACBC',
'#53BF9D',
'#816797',
'#94B49F',
'#DF7861',
'#47B5FF',
'#9EB23B',
'#F15412',
'#3BACB6',
'#92B4EC',
];
<script setup lang="ts">
import { reactive, ref, onMounted } from 'vue';
import * as echarts from 'echarts';
type EChartsOption = echarts.EChartsOption;
type ECharts = echarts.ECharts;
const colors = ['#9EB23B', '#EF9F9F'];
const dynamicRef = ref<any>(null);
const state = reactive({
app: {} as any,
categories: null as any,
categories2: null as any,
data: [] as number[],
data2: [] as number[],
});
onMounted(() => {
getCategories();
getCategories2();
getData();
getData2();
getChart();
});
var dynamicChart: ECharts;
function getChart() {
if (dynamicChart != null && dynamicChart != undefined) {
dynamicChart.dispose();
}
dynamicChart = echarts.init(dynamicRef.value);
let option: EChartsOption;
option = {
color: colors,
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
},
},
legend: {},
dataZoom: {
show: false,
start: 0,
end: 100,
},
xAxis: [
{
type: 'category',
boundaryGap: true,
data: state.categories,
},
{
type: 'category',
boundaryGap: true,
data: state.categories2,
},
],
yAxis: [
{
type: 'value',
scale: true,
name: '折线图',
max: 30,
min: 0,
boundaryGap: [0.2, 0.2],
axisLine: {
show: true,
lineStyle: {
color: colors[0],
},
},
},
{
type: 'value',
scale: true,
name: '柱状图',
max: 1200,
min: 0,
boundaryGap: [0.2, 0.2],
axisLine: {
show: true,
lineStyle: {
color: colors[1],
},
},
},
],
series: [
{
name: '折线图',
type: 'line',
data: state.data2,
itemStyle: {
color: colors[0],
},
},
{
name: '柱状图',
type: 'bar',
// 使用的 x 轴的 index,在单个图表实例中存在多个 x 轴的时候有用。
xAxisIndex: 1,
yAxisIndex: 1,
data: state.data,
barWidth: 35,
itemStyle: {
borderRadius: 10,
color: colors[1],
},
},
],
};
state.app.count = 11;
setInterval(function () {
let axisData = new Date().toLocaleTimeString().replace(/^\D*/, '');
state.data.shift();
state.data.push(Math.round(Math.random() * 1000));
state.data2.shift();
state.data2.push(+(Math.random() * 10 + 5).toFixed(1));
state.categories.shift();
state.categories.push(axisData);
state.categories2.shift();
state.categories2.push(state.app.count++);
dynamicChart.setOption<EChartsOption>({
xAxis: [
{
data: state.categories,
},
{
data: state.categories2,
},
],
series: [
{
data: state.data2,
},
{
data: state.data,
},
],
});
}, 2100);
option && dynamicChart.setOption(option);
}
function getCategories() {
let now = new Date();
let res = <any>[];
let len = 10;
while (len--) {
res.unshift(now.toLocaleTimeString().replace(/^\D*/, ''));
now = new Date(+now - 2000);
}
state.categories = res;
}
function getCategories2() {
let res = [];
let len = 10;
while (len--) {
res.push(10 - len - 1);
}
state.categories2 = res;
}
function getData() {
let res = [];
let len = 10;
while (len--) {
res.push(Math.round(Math.random() * 1000));
}
state.data = res;
}
function getData2() {
let res = [];
let len = 0;
while (len < 10) {
res.push(+(Math.random() * 10 + 5).toFixed(1));
len++;
}
state.data2 = res;
}
</script>
<template>
<div class="fit" ref="dynamicRef"></div>
</template>
<style lang="scss" scoped></style>
<!--
* 动态增加图节点
-->
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue';
import * as echarts from 'echarts';
type EChartsOption = echarts.EChartsOption;
type ECharts = echarts.ECharts;
interface StateType {
data: NonNullable<echarts.GraphSeriesOption['data']>;
edges: NonNullable<echarts.GraphSeriesOption['edges']>;
timer: null | NodeJS.Timeout;
}
defineExpose({
reset,
});
const chartGraphDynamicRef = ref<any>(null);
const state = reactive<StateType>({
data: [],
edges: [],
timer: null,
});
onMounted(() => {
getChart();
});
var graphDynamicChart: ECharts;
function getChart() {
if (graphDynamicChart != null && graphDynamicChart != undefined) {
graphDynamicChart.dispose();
}
graphDynamicChart = echarts.init(chartGraphDynamicRef.value);
let option: EChartsOption;
state.data = [
{
fixed: true,
x: graphDynamicChart.getWidth() / 2,
y: graphDynamicChart.getHeight() / 2,
symbolSize: 18,
id: '0',
name: '原点',
itemStyle: {
color: '#FEB139',
},
},
];
state.edges = [];
option = {
series: [
{
type: 'graph',
roam: true,
layout: 'force',
animation: false,
data: state.data,
force: {
// initLayout: 'circular'
// gravity: 0
repulsion: 100,
edgeLength: 5,
},
edges: state.edges,
},
],
};
run();
option && graphDynamicChart.setOption(option);
}
function run() {
if (state.timer) {
clearTimer();
}
state.timer = setInterval(function () {
state.data.push({
id: state.data.length + '',
itemStyle: {
color: '#8bc24c',
},
});
let source = Math.round((state.data.length - 1) * Math.random());
let target = Math.round((state.data.length - 1) * Math.random());
// 把不相同的两点连接起来
if (source !== target) {
state.edges.push({
source: source,
target: target,
});
}
graphDynamicChart.setOption({
series: [
{
data: state.data,
edges: state.edges,
},
],
});
}, 1000);
}
function clearTimer() {
clearInterval(Number(state.timer));
}
function reset() {
getChart();
}
</script>
<template>
<div class="fit" ref="chartGraphDynamicRef"></div>
</template>
<style lang="scss" scoped></style>
<script setup lang="ts">
import { reactive, onMounted } from 'vue';
import { getRandomPresetColor } from '../utils';
import * as echarts from 'echarts';
type EChartsOption = echarts.EChartsOption;
type ECharts = echarts.ECharts;
interface Props {
id: string;
}
const props = withDefaults(defineProps<Props>(), {
id: 'mychart',
});
interface ChartDomsType {
[proppName: string]: ECharts | null | undefined;
}
const chartDoms = reactive<ChartDomsType>({});
onMounted(() => {
setTimeout(() => {
getLeftChart();
getRightChart();
}, 500);
});
function getLeftChart() {
const id = `${props.id}-left`;
const domkey = `chartLeftDom${props.id}`;
let myChart = chartDoms[domkey];
if (myChart != null && myChart != undefined) {
chartDoms[domkey]?.dispose();
}
const chartDom = document.getElementById(id) as HTMLElement;
if (chartDom) {
myChart = echarts.init(chartDom);
let option: EChartsOption;
option = {
color: getRandomPresetColor(),
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'line',
},
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
data: getRandomData(),
type: 'line',
},
],
};
option && myChart.setOption(option);
}
}
function getRightChart() {
const id = `${props.id}-right`;
const domkey = `chartRightDom${props.id}`;
let myChart = chartDoms[domkey];
if (myChart != null && myChart != undefined) {
chartDoms[domkey]?.dispose();
}
const chartDom = document.getElementById(id) as HTMLElement;
if (chartDom) {
myChart = echarts.init(chartDom);
let option: EChartsOption;
option = {
color: getRandomPresetColor(),
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
},
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
data: getRandomData(),
type: 'bar',
},
],
};
option && myChart.setOption(option);
}
}
function getRandomData() {
let arr = [];
for (let i = 0; i < 7; i++) {
arr.push(Math.round(Math.random() * 300));
}
return arr;
}
</script>
<template>
<div class="map full-width">
<div class="q-ml-sm" :id="`${props.id}-left`"></div>
<div class="q-mr-sm" :id="`${props.id}-right`"></div>
</div>
</template>
<style lang="scss" scoped>
.map {
display: grid;
grid-template-columns: repeat(2, 1fr);
column-gap: $padding-md;
> div {
border: 1px solid $border-color;
height: 600px;
}
}
</style>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import * as echarts from 'echarts';
type EChartsOption = echarts.EChartsOption;
type ECharts = echarts.ECharts;
const colors = ['#95D1CC', '#809A6F', '#FDAF75'];
const chartMultipleYRef = ref<any>(null);
onMounted(() => {
getChart();
});
var multipleYChart: ECharts;
function getChart() {
if (multipleYChart != null && multipleYChart != undefined) {
multipleYChart.dispose();
}
multipleYChart = echarts.init(chartMultipleYRef.value);
let option: EChartsOption;
option = {
color: colors,
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
},
},
grid: {
top: 40,
bottom: 50,
left: 50,
right: 150,
},
legend: {
top: 7,
data: ['蒸发', '降水', '温度'],
},
xAxis: [
{
type: 'category',
axisTick: {
alignWithLabel: true,
},
data: [
'1月',
'2月',
'3月',
'4月',
'5月',
'6月',
'7月',
'8月',
'9月',
'10月',
'11月',
'12月',
],
},
],
yAxis: [
{
type: 'value',
name: '蒸发',
position: 'right',
alignTicks: true,
axisLine: {
show: true,
lineStyle: {
color: colors[0],
},
},
axisLabel: {
formatter: '{value} ml',
},
},
{
type: 'value',
name: '降水',
position: 'right',
alignTicks: true,
offset: 80,
axisLine: {
show: true,
lineStyle: {
color: colors[1],
},
},
axisLabel: {
formatter: '{value} ml',
},
},
{
type: 'value',
name: '温度',
position: 'left',
alignTicks: true,
axisLine: {
show: true,
lineStyle: {
color: colors[2],
},
},
axisLabel: {
formatter: '{value} °C',
},
},
],
series: [
{
name: '蒸发',
type: 'bar',
data: [
2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3,
],
},
{
name: '降水',
type: 'bar',
yAxisIndex: 1,
data: [
2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3,
],
},
{
name: '温度',
type: 'line',
yAxisIndex: 2,
data: [
2.0, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3, 23.4, 23.0, 16.5, 12.0, 6.2,
],
},
],
};
option && multipleYChart.setOption(option);
}
</script>
<template>
<div class="fit" ref="chartMultipleYRef"></div>
</template>
<style lang="scss" scoped></style>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import * as echarts from 'echarts';
type EChartsOption = echarts.EChartsOption;
type ECharts = echarts.ECharts;
const colors = ['#E8C07D', '#9FC088', '#CC704B', '#614124'];
const chartShareDatasetRef = ref<any>(null);
onMounted(() => {
getChart();
});
var shareDatasetChart: ECharts;
function getChart() {
if (shareDatasetChart != null && shareDatasetChart != undefined) {
shareDatasetChart.dispose();
}
shareDatasetChart = echarts.init(chartShareDatasetRef.value);
let option: EChartsOption;
option = {
color: colors,
// grid: { top: '55%' },
grid: {
top: 300,
bottom: 50,
left: 40,
right: 20,
},
legend: {},
tooltip: {
trigger: 'axis',
showContent: false,
axisPointer: {
type: 'shadow',
},
},
dataset: {
source: [
['product', '2012', '2013', '2014', '2015', '2016', '2017'],
['奶茶', 56.5, 82.1, 88.7, 70.1, 53.4, 85.1],
['抹茶拿铁', 51.1, 51.4, 55.1, 53.3, 73.8, 68.7],
['奶酪可可', 40.1, 62.2, 69.5, 36.4, 45.2, 32.5],
['核桃布朗尼', 25.2, 37.1, 41.2, 18, 33.9, 49.1],
],
},
xAxis: { type: 'category' },
yAxis: { gridIndex: 0 },
series: [
{
type: 'line',
smooth: true,
seriesLayoutBy: 'row',
emphasis: { focus: 'series' },
},
{
type: 'line',
smooth: true,
seriesLayoutBy: 'row',
emphasis: { focus: 'series' },
},
{
type: 'line',
smooth: true,
seriesLayoutBy: 'row',
emphasis: { focus: 'series' },
},
{
type: 'line',
smooth: true,
seriesLayoutBy: 'row',
emphasis: { focus: 'series' },
},
{
type: 'pie',
id: 'pie',
radius: '30%',
center: ['50%', '25%'],
// emphasis: {
// focus: 'self',
// },
label: {
formatter: '{b}: {@2012} ({d}%)',
},
encode: {
itemName: 'product',
value: '2017',
tooltip: '2017',
},
},
],
};
shareDatasetChart.on('updateAxisPointer', function (event: any) {
const xAxisInfo = event.axesInfo[0];
if (xAxisInfo) {
const dimension = xAxisInfo.value + 1;
shareDatasetChart.setOption<EChartsOption>({
series: {
id: 'pie',
label: {
formatter: '{b}: {@[' + dimension + ']} ({d}%)',
},
encode: {
value: dimension,
tooltip: dimension,
},
},
});
}
});
shareDatasetChart.setOption(option);
}
</script>
<template>
<div class="fit" ref="chartShareDatasetRef"></div>
</template>
<style lang="scss" scoped></style>
This diff is collapsed.
<script setup lang="ts">
import * as echarts from 'echarts';
import { onMounted, onUnmounted, reactive, ref } from 'vue';
type EChartsOption = echarts.EChartsOption;
type ECharts = echarts.ECharts;
const colorList = {
A: '#F6E3C5',
B: '#A0D995',
C: '#6CC4A1',
D: '#4CACBC',
E: '#DF7861',
} as any;
defineExpose({
run,
setTimer,
clearTimer,
});
const chartsRaceRef = ref<any>(null);
const state = reactive({
data: [] as number[],
timer: null as any,
});
onMounted(() => {
getChart();
});
onUnmounted(() => {
clearTimer();
});
var raceChart: ECharts;
function getChart() {
if (raceChart != null && raceChart != undefined) {
raceChart.dispose();
}
raceChart = echarts.init(chartsRaceRef.value);
let option: EChartsOption;
for (let i = 0; i < 5; ++i) {
state.data.push(Math.round(Math.random() * 200));
}
option = {
grid: {
top: 10,
bottom: 30,
left: 40,
right: 60,
},
xAxis: {
max: 'dataMax',
},
yAxis: {
type: 'category',
data: ['A', 'B', 'C', 'D', 'E'],
inverse: true,
animationDuration: 300,
animationDurationUpdate: 300,
max: 4, // only the largest ${max + 1} bars will be displayed
},
series: [
{
realtimeSort: true,
type: 'bar',
itemStyle: {
color: function (param) {
return colorList[param.name] || '#9EB23B';
},
},
data: state.data,
label: {
show: true,
position: 'right',
valueAnimation: true,
},
barWidth: 60,
},
],
legend: {
show: true,
},
animationDuration: 0,
animationDurationUpdate: 3000,
animationEasing: 'linear',
animationEasingUpdate: 'linear',
};
setTimer();
option && raceChart.setOption(option);
}
function run() {
for (var i = 0; i < state.data.length; ++i) {
if (Math.random() > 0.9) {
state.data[i] = Math.round(Math.random() * 2000);
} else {
state.data[i] = Math.round(Math.random() * 200);
}
}
raceChart.setOption<EChartsOption>({
series: [
{
type: 'bar',
data: state.data,
},
],
});
}
function setTimer() {
if (state.timer) {
clearTimer();
}
setTimeout(function () {
run();
}, 0);
state.timer = setInterval(function () {
run();
}, 3000);
}
function clearTimer() {
clearInterval(state.timer);
}
</script>
<template>
<div class="fit" ref="chartsRaceRef"></div>
</template>
<style lang="scss" scoped></style>
import { colorList } from './config';
// 生成随机的16进制颜色
export const getRandomColor = function () {
let str = '#';
const arr = [
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'a',
'b',
'c',
'd',
'e',
'f',
];
for (let i = 0; i < 6; i++) {
const num = parseInt(String(Math.random() * 16));
str += arr[num];
}
return str;
};
// 获取随机预设颜色
export const getRandomPresetColor = function () {
const index = parseInt(String(Math.random() * colorList.length));
return colorList[index];
};
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<template>
<div class="fit" id="list">
<div id="id1">{{ msg }}</div>
<div id="id2">2</div>
<div id="id3">3</div>
</div>
</template>
<script lang="ts">
export default {
name: 'PAGE3',
};
</script>
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
// import { LinkedList } from './linkedList';
import { LinkedList2 } from './doublyLinkedList';
const msg = ref('page3');
onMounted(() => {
// 创建两个列表节点
// let node1 = new ListNode(2);
// let node2 = new ListNode(5);
// node1.next = node2;
// console.log('列表节点', node1);
// 用node1创建一个链表
// let list = new LinkedList(node1);
// console.log('链表', list);
// console.log(list.head.next.data); // 5
// console.log('list的size', list.size()); // 2
// list.clear();
// console.log('清空链表', list);
// console.log('链表的最后一个节点', list.getLast());
// console.log('链表的第一个节点', list.getFirst());
let list = new LinkedList2(1);
list.append(2);
list.append(3);
console.log('插入前', list.toArr()); // [1, 2, 3]
list.insert(2, 4);
console.log('插入后', list.toArr()); // [1, 2, 4, 3]
});
</script>
<style lang="scss" scoped></style>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<script setup lang="ts">
// import { reactive } from 'vue';
const props = defineProps<{
params: any;
}>();
</script>
<template>
<div class="ag-grid-firt-col">{{ props.params.value }}</div>
</template>
<style lang="scss">
.ag-cell-value {
height: 40px;
}
.ag-grid-firt-col {
height: 100%;
// background-color: #f8f8f8;
// border-right: 1px solid;
// border-color: var(--ag-border-color);
font-size: 13px;
font-weight: 700;
color: var(--ag-header-foreground-color);
}
</style>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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