Commit 39767357 by qlintonger xeno

first setup

parent 57e268cd
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# 配置文件说明
project.ui.config.ts是配置UI框架的文件,根据需要修改配置项。
project.app.config.ts是配置应用程序的文件,根据需要修改配置项。
\ No newline at end of file
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp']
const customRef: typeof import('vue')['customRef']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const effectScope: typeof import('vue')['effectScope']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const inject: typeof import('vue')['inject']
const isProxy: typeof import('vue')['isProxy']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const provide: typeof import('vue')['provide']
const reactive: typeof import('vue')['reactive']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const resolveComponent: typeof import('vue')['resolveComponent']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const toRaw: typeof import('vue')['toRaw']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const toValue: typeof import('vue')['toValue']
const triggerRef: typeof import('vue')['triggerRef']
const unref: typeof import('vue')['unref']
const useAttrs: typeof import('vue')['useAttrs']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVars: typeof import('vue')['useCssVars']
const useLink: typeof import('vue-router')['useLink']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useSlots: typeof import('vue')['useSlots']
const watch: typeof import('vue')['watch']
const watchEffect: typeof import('vue')['watchEffect']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
}
// for type re-export
declare global {
// @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
import('vue')
}
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}
declare module 'vue' {
export interface GlobalComponents {
AButton: typeof import('@arco-design/web-vue')['Button']
ACol: typeof import('@arco-design/web-vue')['Col']
AConfigProvider: typeof import('@arco-design/web-vue')['ConfigProvider']
ARow: typeof import('@arco-design/web-vue')['Row']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
// 自定义组件
GlobalSetting: typeof import('./src/components/global-setting/index.vue')['default']
LocaleText: typeof import('./src/components/locale/localeText.vue')['default']
ChangeThemeText: typeof import('./src/components/theme/changeThemeText.vue')['default']
}
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>...</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "vue-ts-init",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview"
},
"dependencies": {
"@alova/mock": "^1.5.1",
"@vueuse/core": "^10.9.0",
"alova": "^2.17.0",
"exceljs": "^4.4.0",
"gsap": "^3.12.5",
"less": "^4.2.0",
"pinia": "^2.1.7",
"vite-plugin-compression": "^0.5.1",
"vue": "^3.4.19",
"vue-i18n": "^9.9.0",
"vue-router": "^4.3.0",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@arco-design/web-vue": "^2.54.5",
"@arco-plugins/vite-vue": "^1.4.5",
"@types/node": "^20.11.20",
"@vitejs/plugin-vue": "^5.0.4",
"autoprefixer": "^10.4.17",
"eslint": "^8.56.0",
"postcss": "^8.4.35",
"tailwindcss": "^3.4.1",
"typescript": "^5.2.2",
"unplugin-auto-import": "^0.17.5",
"unplugin-vue-components": "^0.26.0",
"vite": "^5.1.4",
"vue-tsc": "^1.8.27"
}
}
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
// =============================
// App设置
// =============================
export default {
// App配置 ==========
baseTitle: 'Vue3项目', // 基础标题
enableGZip: false, // 是否开启gzip压缩
}
// api设置 ==============
export const ApiConfig = {
// 本地存储token的key
API_TOKEN_KEY: 'token',
// 是否开发环境
IS_DEVMODE: false,
// API服务器超时设置.
API_TIMEOUT: 30 * 1000,
// 接口服务器地址.
DEV_API_URL: 'http://localhost/TMSServer',
PROD_API_URL: 'https://www.insightbridge.com.cn',
// Mockt等待延时时间
MOCK_DELAY: 1000,
}
// api地址
export const API_URL = ApiConfig.IS_DEVMODE ? ApiConfig.DEV_API_URL : ApiConfig.PROD_API_URL
import { ref } from "vue"
// 激活主题色:dark, light
export const activedTheme = ref('light')
// UI配置
export default {
// 定义项目配色主色
colors: {
// 亮色主题 ===================
// 主色
primary: '#ffcc00', // 主色
primaryHover: '#005600', // 主色鼠标移上色
primaryPressed: '#0056b3', // 主色按下色
primaryActivated: '#003a8c', // 主色激活色
primaryDisable: '#005600', // 主色禁用色
// 背景色
themeBg1: '#ffffff', // 背景色
themeBg2: '#f5f5f5', // 比上面浅一点
themeBg3: '#eeeeee', // 比上面浅一点
themeBg4: '#dddddd', // 比上面浅一点
themeBg5: '#eeeeee', // 比上面浅一点
// 文字色
themeText1: '#000000', // 正常文字
themeText2: '#333333', // 比上面浅一点
themeText3: '#666666', // 比上面浅一点
themeText4: '#999999', // 比上面浅一点
themeText5: '#eeeeee', // 比上面浅一点
// 深色主题 ===================
// 主色
darkPrimary: '#ffcc66', // 主色
darkPrimaryHover: '#005600', // 主色鼠标移上色
darkPrimaryPressed: '#0056b3', // 主色按下色
darkPrimaryActivated: '#003a8c', // 主色激活色
darkPrimaryDisable: '#005600', // 主色禁用色
// 背景色
darkThemeBg1: '#000000', // 背景色
darkThemeBg2: '#111111', // 比上面浅一点
darkThemeBg3: '#222222', // 比上面浅一点
darkThemeBg4: '#333333', // 比上面浅一点
darkThemeBg5: '#222222', // 比上面浅一点
// 文字色
darkThemeText1: '#ffffff', // 正常文字
darkThemeText2: '#eeeeee', // 比上面浅一点
darkThemeText3: '#dddddd', // 比上面浅一点
darkThemeText4: '#999999', // 比上面浅一点
darkThemeText5: '#666666', // 比上面浅一点
},
// 定义间距
spacing: {
xxs: '4px',
xs: '8px',
sm: '12px',
md: '18px',
lg: '24px',
xl: '32px',
x2l: '48px',
x3l: '64px',
x4l: '80px',
x5l: '96px',
x6l: '120px',
x7l: '150px',
x8l: '180px',
x9l: '210px',
},
// 定义圆角
borderRadius: {
xs: '2px',
sm: '4px',
md: '8px',
lg: '12px',
xl: '16px',
},
// 定义圆角宽
borderWidth: {
xs: '1px',
sm: '2px',
md: '3px',
lg: '4px',
xl: '5px',
},
}
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
\ No newline at end of file
<template>
<a-config-provider :locale="localeVal">
<router-view />
<global-setting />
</a-config-provider>
</template>
<script setup lang="ts">
import enUS from '@arco-design/web-vue/es/locale/lang/en-us';
import zhCN from '@arco-design/web-vue/es/locale/lang/zh-cn';
import GlobalSetting from '@/components/global-setting/index.vue';
import useLocale from '@/hooks/locale';
import useAppStore from '@/store/app/index';
import { activedTheme } from '../project.ui.config';
import config from '../project.app.config';
const { changeTheme } = useAppStore();
// 国际化
const { currentLocale, changeLocale } = useLocale();
const localeVal = computed(() => {
switch (currentLocale.value) {
case 'zh-CN':
return zhCN;
case 'en-US':
return enUS;
default:
return zhCN;
}
});
onMounted(() => {
changeTheme(activedTheme.value)
setTimeout(() => {
changeLocale('en-US')
}, 3000)
})
watch(activedTheme, (newVal) => {
changeTheme(newVal)
})
const router = useRouter()
// @ts-ignore
router.beforeEach(async (to, from, next) => {
// 动态标题
let pageTitle = !to.meta.hideBaseTitle ? config.baseTitle + ' - ' : ''
if(to.meta.title != '') pageTitle += to.meta.title
window.document.title = pageTitle
next()
})
</script>
\ No newline at end of file
import { createAlova } from "alova";
import vueHook from "alova/vue";
import GlobalFetch from "alova/GlobalFetch";
import { API_URL, ApiConfig } from "../../project.app.config";
import { createAlovaMockAdapter } from '@alova/mock';
import mock from './mock';
// 创建模拟请求适配器
const mockAdapter = createAlovaMockAdapter([mock], {
enable: true,
delay: ApiConfig.MOCK_DELAY,
httpAdapter: GlobalFetch(), // 无适配使用接口请求
mockRequestLogger: true, // 是否打印mock接口请求信息
});
// 创建实例
export const alova = createAlova({
baseURL: API_URL,
statesHook: vueHook,
shareRequest: true,
// 通过环境变量控制生产环境下,不会将mock相关代码打包进去
requestAdapter: process.env.NODE_ENV === 'development' ? mockAdapter : GlobalFetch(),
// 请求拦截器
beforeRequest(method) {
// 设置请求头
method.config.headers = {
"Content-Type": "application/json;charset=UTF-8",
}
// method.config.headers.Authorization = `Bearer ${localStorage.getItem("token")}`;
},
// 响应拦截器
responded: {
// 当使用GlobalFetch请求适配器时,第一个参数接收Response对象
onSuccess: async (response) => {
if(response.status >= 400){
throw new Error(response.statusText);
}
const json = await response.json();
if(json.code === 200) {
return json["data"];
} else {
return json;
}
},
// 请求错误时将会进入该拦截器
onError(error) {
console.log(error);
throw error;
},
// 当你需要在请求不论是成功、失败、还是命中缓存都需要执行的逻辑时,可以在创建alova实例时指定全局的`onComplete`拦截器,例如关闭请求 loading 状态。
onComplete:async () => {
// 处理响应完成后的逻辑
// console.log("执行完成");
}
}
});
\ No newline at end of file
import { defineMock } from '@alova/mock';
// 模似数据
export default defineMock({
'[get]/api/user': { code: 200, data:{ name: '张三', age: 18 } },
'[post]/api/login': ({ data }) => {
if(data.uName === 'admin' && data.pwd === '123456') return { code: 200, data:{ token: 'SvSDfa9sdf8gfA' } };
else return { code: 401, msg: '用户名或密码错误' };
}
})
\ No newline at end of file
body {
background-color: var(--color-bg-1);
color: var(--color-text-1);
}
html,body,#app{width:100%;height:100%;overflow:hidden;}
div{box-sizing:border-box;}
\ No newline at end of file
@tailwind base;
@tailwind components;
@tailwind utilities;
/* 适配主题 */
/* 主题背景 */
.bg-primary{@apply bg-primary-light dark:bg-primary-dark}
.bg-primary-hover{@apply bg-primary-hover-light dark:bg-primary-hover-dark}
.bg-primary-pressed{@apply bg-primary-pressed-light dark:bg-primary-pressed-dark}
.bg-primary-activated{@apply bg-primary-activated-light dark:bg-primary-activated-dark}
.bg-primary-disable{@apply bg-primary-disable-light dark:bg-primary-disable-dark}
.bg-theme-bg1{@apply bg-theme-bg1-light dark:bg-theme-bg1-dark}
.bg-theme-bg2{@apply bg-theme-bg2-light dark:bg-theme-bg2-dark}
.bg-theme-bg3{@apply bg-theme-bg3-light dark:bg-theme-bg3-dark}
.bg-theme-bg4{@apply bg-theme-bg4-light dark:bg-theme-bg4-dark}
.bg-theme-bg5{@apply bg-theme-bg5-light dark:bg-theme-bg5-dark}
/* 主题文本色 */
.text-primary{@apply text-primary-light dark:text-primary-dark}
.text-primary-hover{@apply text-primary-hover-light dark:text-primary-hover-dark}
.text-primary-pressed{@apply text-primary-pressed-light dark:text-primary-pressed-dark}
.text-primary-activated{@apply text-primary-activated-light dark:text-primary-activated-dark}
.text-primary-disable{@apply text-primary-disable-light dark:text-primary-disable-dark}
.text-theme-text1{@apply text-theme-text1-light dark:text-theme-text1-dark}
.text-theme-text2{@apply text-theme-text2-light dark:text-theme-text2-dark}
.text-theme-text3{@apply text-theme-text3-light dark:text-theme-text3-dark}
.text-theme-text4{@apply text-theme-text4-light dark:text-theme-text4-dark}
.text-theme-text5{@apply text-theme-text5-light dark:text-theme-text5-dark}
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp']
const customRef: typeof import('vue')['customRef']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const effectScope: typeof import('vue')['effectScope']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const inject: typeof import('vue')['inject']
const isProxy: typeof import('vue')['isProxy']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const provide: typeof import('vue')['provide']
const reactive: typeof import('vue')['reactive']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const resolveComponent: typeof import('vue')['resolveComponent']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const toRaw: typeof import('vue')['toRaw']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const toValue: typeof import('vue')['toValue']
const triggerRef: typeof import('vue')['triggerRef']
const unref: typeof import('vue')['unref']
const useAttrs: typeof import('vue')['useAttrs']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVars: typeof import('vue')['useCssVars']
const useLink: typeof import('vue-router')['useLink']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useSlots: typeof import('vue')['useSlots']
const watch: typeof import('vue')['watch']
const watchEffect: typeof import('vue')['watchEffect']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
}
// for type re-export
declare global {
// @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
import('vue')
}
<template>
</template>
<script lang="ts" setup>
</script>
<style scoped lang="less">
</style>
<template>
<div class="flex items-center">
<div class="pr-2 border-solid border-0 border-r-xs border-theme-text1/20" :class="currentLocale=='zh-CN' ? 'text-primary' : 'cursor-pointer'" @click="changeLocale('zh-CN')">中文</div>
<div class="ml-2" :class="currentLocale=='en-US' ? 'text-primary' : 'cursor-pointer'" @click="changeLocale('en-US')">English</div>
</div>
</template>
<script lang="ts" setup>
import useLocale from '@/hooks/locale';
const { currentLocale, changeLocale } = useLocale();
</script>
\ No newline at end of file
<template>
<div class="flex items-center">
<div class="pr-2 border-solid border-0 border-r-xs border-theme-text1/20" :class="activedTheme=='light' ? 'text-primary' : 'cursor-pointer'" @click="activedTheme='light'">{{$t('app.theme.light')}}</div>
<div class="ml-2" :class="activedTheme=='dark' ? 'text-primary' : 'cursor-pointer'" @click="activedTheme='dark'">{{$t('app.theme.dark')}}</div>
</div>
</template>
<script lang="ts" setup>
import { activedTheme } from '../../../project.ui.config';
</script>
\ No newline at end of file
import projectUiConfig from '../../project.ui.config'
// 改变ArcoUI框架的主题
export function changeArcoTheme(themeName:string) {
if(themeName === 'dark') {
document.body.setAttribute('arco-theme', themeName)
} else {
document.body.removeAttribute('arco-theme')
}
}
// Arco的变量设置
export const arcoUiConfig = {
// 白底主色 ==================
'primary-7': projectUiConfig.colors.primaryPressed,
'primary-6': projectUiConfig.colors.primary,
'primary-5': projectUiConfig.colors.primaryHover,
'primary-4': projectUiConfig.colors.primary,
'primary-3': projectUiConfig.colors.primaryDisable,
'primary-2': projectUiConfig.colors.primaryDisable,
'primary-1': projectUiConfig.colors.primaryDisable,
'color-bg-1': projectUiConfig.colors.themeBg1,
'color-bg-2': projectUiConfig.colors.themeBg2,
'color-bg-3': projectUiConfig.colors.themeBg3,
'color-bg-4': projectUiConfig.colors.themeBg4,
'color-bg-5': projectUiConfig.colors.themeBg5,
'color-text-1': projectUiConfig.colors.themeText1,
'color-text-2': projectUiConfig.colors.themeText2,
'color-text-3': projectUiConfig.colors.themeText3,
'color-text-4': projectUiConfig.colors.themeText4,
// 深底主色 ==================
'dark-primary-7': projectUiConfig.colors.darkPrimaryPressed,
'dark-primary-6': projectUiConfig.colors.darkPrimary,
'dark-primary-5': projectUiConfig.colors.darkPrimaryHover,
'dark-primary-4': projectUiConfig.colors.darkPrimary,
'dark-primary-3': projectUiConfig.colors.darkPrimaryDisable,
'dark-primary-2': projectUiConfig.colors.darkPrimaryDisable,
'dark-primary-1': projectUiConfig.colors.darkPrimaryDisable,
'dark-color-bg-1': projectUiConfig.colors.darkThemeBg1,
'dark-color-bg-2': projectUiConfig.colors.darkThemeBg2,
'dark-color-bg-3': projectUiConfig.colors.darkThemeBg3,
'dark-color-bg-4': projectUiConfig.colors.darkThemeBg4,
'dark-color-bg-5': projectUiConfig.colors.darkThemeBg5,
'dark-color-text-1': projectUiConfig.colors.darkThemeText1,
'dark-color-text-2': projectUiConfig.colors.darkThemeText2,
'dark-color-text-3': projectUiConfig.colors.darkThemeText3,
'dark-color-text-4': projectUiConfig.colors.darkThemeText4,
// 边框宽度 =================
'border-1': projectUiConfig.borderWidth.xs,
'border-2': projectUiConfig.borderWidth.sm,
'border-3': projectUiConfig.borderWidth.md,
// 边框圆角 ================
'border-radius-small': projectUiConfig.borderRadius.sm,
'border-radius-medium': projectUiConfig.borderRadius.md,
'border-radius-large': projectUiConfig.borderRadius.lg,
}
import projectUiConfig from '../../project.ui.config'
// 改变ArcoUI框架的主题
export function changeTailwindTheme(themeName:string) {
document.body.setAttribute('class', themeName)
}
// tailwind的UI变量设置
export const tailwindUiConfig = {
// 定义主色,这里简化一点,就直接动态改变
colors: {
'primary-light': projectUiConfig.colors.primary,
'primary-hover-light': projectUiConfig.colors.primaryHover,
'primary-pressed-light': projectUiConfig.colors.primaryPressed,
'primary-activated-light': projectUiConfig.colors.primaryActivated,
'primary-disable-light': projectUiConfig.colors.primaryDisable,
'theme-bg1-light': projectUiConfig.colors.themeBg1,
'theme-bg2-light': projectUiConfig.colors.themeBg2,
'theme-bg3-light': projectUiConfig.colors.themeBg3,
'theme-bg4-light': projectUiConfig.colors.themeBg4,
'theme-bg5-light': projectUiConfig.colors.themeBg5,
'theme-text1-light': projectUiConfig.colors.themeText1,
'theme-text2-light': projectUiConfig.colors.themeText2,
'theme-text3-light': projectUiConfig.colors.themeText3,
'theme-text4-light': projectUiConfig.colors.themeText4,
'theme-text5-light': projectUiConfig.colors.themeText5,
'primary-dark': projectUiConfig.colors.darkPrimary,
'primary-hover-dark': projectUiConfig.colors.darkPrimaryHover,
'primary-pressed-dark': projectUiConfig.colors.darkPrimaryPressed,
'primary-activated-dark': projectUiConfig.colors.darkPrimaryActivated,
'primary-disable-dark': projectUiConfig.colors.darkPrimaryDisable,
'theme-bg1-dark': projectUiConfig.colors.darkThemeBg1,
'theme-bg2-dark': projectUiConfig.colors.darkThemeBg2,
'theme-bg3-dark': projectUiConfig.colors.darkThemeBg3,
'theme-bg4-dark': projectUiConfig.colors.darkThemeBg4,
'theme-bg5-dark': projectUiConfig.colors.darkThemeBg5,
'theme-text1-dark': projectUiConfig.colors.darkThemeText1,
'theme-text2-dark': projectUiConfig.colors.darkThemeText2,
'theme-text3-dark': projectUiConfig.colors.darkThemeText3,
'theme-text4-dark': projectUiConfig.colors.darkThemeText4,
'theme-text5-dark': projectUiConfig.colors.darkThemeText5,
},
// 定义间距
spacing: {
'xxs': projectUiConfig.spacing.xxs,
'xs': projectUiConfig.spacing.xs,
'sm': projectUiConfig.spacing.sm,
'md': projectUiConfig.spacing.md,
'lg': projectUiConfig.spacing.lg,
'xl': projectUiConfig.spacing.xl,
'2xl': projectUiConfig.spacing.x2l,
'3xl': projectUiConfig.spacing.x3l,
'4xl': projectUiConfig.spacing.x4l,
'5xl': projectUiConfig.spacing.x5l,
'6xl': projectUiConfig.spacing.x6l,
'7xl': projectUiConfig.spacing.x7l,
'8xl': projectUiConfig.spacing.x8l,
'9xl': projectUiConfig.spacing.x9l,
},
// 定义圆角
borderRadius: {
'xs': projectUiConfig.borderRadius.xs,
'sm': projectUiConfig.borderRadius.sm,
'md': projectUiConfig.borderRadius.md,
'lg': projectUiConfig.borderRadius.lg,
'xl': projectUiConfig.borderRadius.xl,
},
borderWidth: {
'xs': projectUiConfig.borderWidth.xs,
'sm': projectUiConfig.borderWidth.sm,
'md': projectUiConfig.borderWidth.md,
'lg': projectUiConfig.borderWidth.lg,
'xl': projectUiConfig.borderWidth.xl,
},
// 新加的角度
rotate: {
'30': '30deg',
'60': '60deg',
},
// 新加的缩放
scale: {
'20': '.2',
'25': '.25',
'30': '.3',
'66': '.66',
'80': '.8',
'200': '.2',
},
// 动画延时
transitionDelay: {
'1250': '1250ms',
'1500': '1500ms',
'1750': '1750ms',
'2000': '2000ms',
'2250': '2250ms',
'2500': '2500ms',
'2750': '2750ms',
'3000': '3000ms',
},
// 动画周期
transitionDuration: {
'1250': '1250ms',
'1500': '1500ms',
'1750': '1750ms',
'2000': '2000ms',
'2250': '2250ms',
'2500': '2500ms',
'2750': '2750ms',
'3000': '3000ms',
},
// 层级
zIndex: {
'60': '60',
'70': '70',
'80': '80',
'90': '90',
'100': '100',
'200': '200',
'300': '300',
'400': '400',
'500': '500',
'600': '600',
'700': '700',
'800': '800',
'900': '900',
'1000': '1000',
'1100': '1100',
},
backgroundColor: {
}
}
\ No newline at end of file
export const KBSize = 1024
export const MBSize = KBSize * 1024
export const GBSize = MBSize * 1024
\ No newline at end of file
export enum InputFormType {
input,
select,
textarea,
radio,
datepicker,
checkbox,
inputpair,//输入数字区间
singleCheck, // 单独的checkbox
}
\ No newline at end of file
// import { App } from 'vue';
// import permission from './permission';
export default {
// install(Vue: App) {
// Vue.directive('permission', permission);
// },
};
import { ref } from 'vue';
export default function useLoading(initValue = false) {
const loading = ref(initValue);
const setLoading = (value: boolean) => {
loading.value = value;
};
const toggle = () => {
loading.value = !loading.value;
};
return {
loading,
setLoading,
toggle,
};
}
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { Message } from '@arco-design/web-vue';
export default function useLocale() {
const i18 = useI18n();
const currentLocale = computed(() => {
return i18.locale.value;
});
const changeLocale = (value: string) => {
if (i18.locale.value === value) {
return;
}
i18.locale.value = value;
localStorage.setItem('arco-locale', value);
Message.success(i18.t('action.locale'));
};
return {
currentLocale,
changeLocale,
};
}
import { ref } from 'vue';
export default function useVisible(initValue = false) {
const visible = ref(initValue);
const setVisible = (value: boolean) => {
visible.value = value;
};
const toggle = () => {
visible.value = !visible.value;
};
return {
visible,
setVisible,
toggle,
};
}
export let socketChannelBroadcast: BroadcastChannel | null
const msgListener = [] as Function[]
export function removeListenerOfSCB(f: Function) {
const index = msgListener.findIndex(a => a === f);
if (index > -1) {
msgListener.splice(index, 1)
}
}
export function setupSCB(name: string) {
if (!socketChannelBroadcast) {
socketChannelBroadcast = new BroadcastChannel(name);
socketChannelBroadcast.onmessage = function ($e) {
for (const f of msgListener) {
f.call(null, $e.data)
}
}
}
}
export function pushListenerSCB(f: Function) {
if (!msgListener.includes(f)) {
msgListener.push(f);
}
}
export function pushMsgSCB(msg: any) {
if (socketChannelBroadcast) {
socketChannelBroadcast.postMessage(JSON.stringify(msg))
}
}
export function destroySCB() {
if (socketChannelBroadcast) {
socketChannelBroadcast = null;
msgListener.length = 0;
}
}
\ No newline at end of file
// 不同的翻译文件都放在对应的模块里,可以在views里
import localeApp from './en-US/app';
export default {
'action.locale': 'Switch to English',
...localeApp,
};
export default {
'app.title': 'APP Title',
'app.theme.light': 'Light',
'app.theme.dark': 'Dark',
};
import { createI18n } from 'vue-i18n';
import en from './en-US';
import cn from './zh-CN';
// 定义多语言
export const LOCALE_OPTIONS = [
{ label: '中文', value: 'zh-CN' },
{ label: 'English', value: 'en-US' },
];
// 默认语言
const defaultLocale = localStorage.getItem('arco-locale') || 'zh-CN';
const i18n = createI18n({
locale: defaultLocale,
fallbackLocale: 'en-US',
legacy: false,
allowComposition: true,
messages: {
'en-US': en,
'zh-CN': cn,
},
});
export default i18n;
// 不同的翻译文件都放在对应的模块里,可以在views里
import localeApp from './zh-CN/app';
export default {
'action.locale': '切换为中文',
...localeApp,
};
export default {
'app.title': '网站名称',
'app.theme.light': '亮色',
'app.theme.dark': '暗黑',
};
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { createPinia } from 'pinia';
import i18n from './locale';
// import directive from './directive';
// 加载Css
import './assets/css/arco.style.css'
import './assets/css/style.css'
import './assets/css/tailwind.css'
const app = createApp(App)
app.use(router)
app.use(createPinia())
app.use(i18n)
// app.use(directive);
app.mount('#app')
import {createRouter, createWebHashHistory, RouteRecordRaw} from 'vue-router'
const routes: Array<RouteRecordRaw> = [
{
path: '/',
component: () => import('../views/login/index.vue'),
meta: {
title: '登录',
}
},
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
\ No newline at end of file
import { defineStore } from 'pinia';
import { AppState } from './types';
import { changeArcoTheme } from '@/configs/arco.ui.config';
import { changeTailwindTheme } from '@/configs/tailwind.ui.config';
const useAppStore = defineStore('app', {
state: (): AppState => {
return {
theme: 'light',
}
},
getters: {},
actions: {
changeTheme(themeName: string) {
this.theme = 'dark';
changeArcoTheme(themeName);
changeTailwindTheme(themeName);
},
},
});
export default useAppStore;
export interface AppState {
theme: string;
}
import {createPinia} from 'pinia';
const pinia = createPinia();
export default pinia;
import {Ref} from "vue";
import {displayError} from "../../components/Global/MessagePrompt/functionals/triggerMessagePrompt";
export async function fetchCommonFuncSimplified(
f: Function,
params: any,
txt: any,
cb: Function,
loaderRef?: Ref<boolean>,
judgeFunc = (a: any) => a.data.code.toString() === '200',
) {
try {
if (loaderRef) {
loaderRef.value = true
}
const res = await f.call(null, ...params);
if (judgeFunc(res)) {
cb(res)
} else {
console.log('请求出错!!!', res)
throw new Error(`请求${txt}出错!`)
}
} catch (e: any) {
console.log('error in fetch', e);
displayError(`处理${txt}失败,错误信息:${e.message}`);
} finally {
if (loaderRef) {
loaderRef.value = false
}
}
}
export async function fetchCommonFunc(
f: Function,
params: any,
txt: any,
cb: Function,
loaderRef?: Ref<boolean>,
) {
try {
if (loaderRef) {
loaderRef.value = true
}
const res = await f.call(null, ...params);
cb(res);
} catch (e: any) {
console.log('error in fetch', e);
displayError(`处理${txt}失败,错误信息:${e.message}`);
} finally {
if (loaderRef) {
loaderRef.value = false
}
}
}
/**
* 在异步操作中休息若干毫秒
* @param expiredTime {Number} 休息的时间,单位为毫秒
* @return Promise<void> 无返回值
*/
export function sleepInAsyncFunc(expiredTime: number): Promise<void> {
return new Promise(function (r) {
setTimeout(function () {
r()
}, expiredTime)
})
}
\ No newline at end of file
const TOKEN_KEY = 'token';
const isLogin = () => {
return !!localStorage.getItem(TOKEN_KEY);
};
const getToken = () => {
return localStorage.getItem(TOKEN_KEY);
};
const setToken = (token: string) => {
localStorage.setItem(TOKEN_KEY, token);
};
const clearToken = () => {
localStorage.removeItem(TOKEN_KEY);
};
export { isLogin, getToken, setToken, clearToken };
/**
* 判断两个数组是否长度和内容一致,不能判断内嵌复杂数据的数组
* @param a1 {Array<Number | String | Boolean>} 数组一
* @param a2 {Array<Number | String | Boolean>} 数组二
* @return Boolean 判断二者是否相等
*/
export function arrayMemberShallowEqual(a1: Array<any>, a2: Array<any>): boolean {
if (a1.length !== a2.length)
return false
let a1LoopLength = a1.length
let comparedA2 = [...a2]
for (let i = 0; i < a1LoopLength; i++) {
const indexInA2 = comparedA2.indexOf(a1[i])
if (indexInA2 === -1) {
return false
}
comparedA2.splice(indexInA2, 1)
}
return true
}
\ No newline at end of file
/**
* 通用的格式化时间
* @param input {String | Date | Number | null} 可以被传入Date构造函数的任意数据
* @param until {String} 为all、day、min中的任何一个,默认为all,表示格式化到哪一位
* @param defaultVal {String} 当传入数据不合法时的默认值,默认为'--’
* @return String 格式化之后的字符串
*/
export const formatDate = (
input: Date | string | number | null,
until = "all",
defaultVal: string = '--'
): string => {
if (input === null || input === 0||input < 0) return defaultVal;
const date = new Date(input);
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const hour = date.getHours();
const min = date.getMinutes();
const sec = date.getSeconds();
if (until === 'day')
return `${year}-${month.toString().padStart(2, "0")}-${day
.toString()
.padStart(2, "0")}`
if (until === "min") {
return `${year}-${month.toString().padStart(2, "0")}-${day
.toString()
.padStart(2, "0")} ${hour.toString().padStart(2, "0")}:${min
.toString()
.padStart(2, "0")}`;
}
return `${year}-${month.toString().padStart(2, "0")}-${day
.toString()
.padStart(2, "0")} ${hour.toString().padStart(2, "0")}:${min
.toString()
.padStart(2, "0")}:${sec.toString().padStart(2, "0")}`;
};
/**
* 加上年月日时分秒的中国本土化的格式化时间
* @param input {String | Date | Number | null} 可以被传入Date构造函数的任意数据
* @param until {String} 为all、day、min中的任何一个,默认为all,表示格式化到哪一位
* @param defaultVal {String} 当传入数据不合法时的默认值,默认为'--’
* @return String 格式化之后的字符串
*/
export const formatDateZh = (
input: Date | string | number | null,
until = "all",
defaultVal: string = '--'
): string => {
if (input === null || input === 0||input < 0) return defaultVal;
const date = new Date(input);
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const hour = date.getHours();
const min = date.getMinutes();
const sec = date.getSeconds();
if (until === 'day')
return `${year}${month.toString().padStart(2, "0")}${day
.toString()
.padStart(2, "0")}日`
if (until === "min") {
return `${year}${month.toString().padStart(2, "0")}${day
.toString()
.padStart(2, "0")}${hour.toString().padStart(2, "0")}:${min
.toString()
.padStart(2, "0")}`;
}
return `${year}${month.toString().padStart(2, "0")}${day
.toString()
.padStart(2, "0")}${hour.toString().padStart(2, "0")}:${min
.toString()
.padStart(2, "0")}:${sec.toString().padStart(2, "0")}`;
};
\ No newline at end of file
/**
* 返回某个日期下的星期几的中文表达
* @param input {Date | String | Number | null} 任何可以传入Date构造函数的数据类型
* @return String 周日到周六的中文表达
*/
export const getWeekday = (input: Date | string | number | null) => {
if (input === null) return "--";
const weekArr = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
//格式必须是yy-mm-dd
return weekArr[new Date(input).getDay()];
};
/**
* 缓存同一参数下的异步请求或者类似方法的结果
* @param f {Function} 待缓存的方法
*/
export function cacheAPICallAsync(f: Function) {
const cacheHit = new Map<String, any>()
return async function (...arg:any[]) {
const argsStr = JSON.stringify(arg)
const cacheGet = cacheHit.get(argsStr)
if (cacheGet) {
return cacheGet
}
const resp = await f.call(null, ...arg);
cacheHit.set(argsStr, resp);
return resp;
}
}
\ No newline at end of file
/**
* 包裹某个function,使其只能被调用一次
* @param f {Function} 被包裹的只会被调用一次的方法
*/
export function calledOnlyOnce(f: Function) {
let hasCalled = false
return function () {
if (!hasCalled) {
hasCalled = true
f.call(null, ...arguments)
}
}
}
\ No newline at end of file
// @ts-nocheck
/**
* 保证在ms范围内不会多次调用方法,只会再最后一次调用结束后的ms后call
* @param f {Function} 待处理的方法
* @param ms {Number} 防抖动的时间,单位为毫秒
* @param isAsync {Boolean} 该方法是否为异步
*/
export function delayFuncCall(f: Function, ms: number, isAsync = false): Function {
let newestArguments: any[] = []
let lastTimer: number
return function () {
newestArguments = arguments
clearTimeout(lastTimer)
if (!isAsync) {
lastTimer = setTimeout(function () {
f.call(null, ...newestArguments)
}, ms)
} else {
lastTimer = setTimeout(async function () {
await f.call(null, ...newestArguments)
}, ms)
}
}
}
\ No newline at end of file
/*
* Copyright (c) $today.year-$today.month-13
* Created by: qlintonger xeno
* Email: 1983115293@qq.com
*/
/**
* 深克隆方法,建议不要使用JSON类操作,而使用本方法
* @param obj {*} 任何合法数据类型
*/
export function deepCopyObject(obj: any): any {
if (Array.isArray(obj)) {
let preCloned = []
for (const item of obj) {
preCloned.push(deepCopyObject(item))
}
return preCloned
}
if (typeof obj === 'object' && obj !== null) {
let preCloned = {}
for (const k of Object.keys(obj)) {
// @ts-ignore
preCloned[k] = deepCopyObject(obj[k])
}
return preCloned
}
return obj
}
/**
* 创建唯一id,使用crypto API,返回16进制字符串
* @param length {Number} 唯一id字符串的长度
*/
export const makeSID = function (length: number = 32) {
if (window.crypto && window.crypto.getRandomValues !== undefined) {
const buffer = new Uint8Array(length)
window.crypto.getRandomValues(buffer)
return buffer.reduce((q, w) => q + w.toString(16).padStart(2, '0'), "")
}
return getSID(length);
}
/**
* 创建唯一id,使用随机数来创建,返回16进制字符串
* @param length {Number} 唯一id字符串的长度
*/
export const getSID = function (length: number = 32) {
let output = '';
for (let i = 0; i < length; i++) {
const bufferType = Math.floor(Math.random() * 3);
switch (bufferType) {
case 0: {
output += String.fromCharCode(48 + Math.floor(Math.random() * 10))
}
break;
case 1:{
output += String.fromCharCode(65 + Math.floor(Math.random() * 26))
}
break;
case 2: {
output += String.fromCharCode(97 + Math.floor(Math.random() * 26))
}
break;
default:break
}
}
return output;
}
\ No newline at end of file
/**
* 判断两个字符串的大小,依据长度以及unicode代码来判断
* @param str1 {String} 字符串1
* @param str2 {String} 字符串2
*/
export function stringCompare(str1: string, str2: string) {
if (str1.length + str2.length === 0)
return 0
if (str1.length === 0)
return -1
if (str2.length === 0)
return 1
const compareLength = Math.min(str1.length, str2.length)
for (let i = 0; i < compareLength; i++) {
const c1 = str1.codePointAt(i)
const c2 = str2.codePointAt(i)
// @ts-ignore
if (c1 < c2)
return -1
// @ts-ignore
if (c1 > c2)
return 1
}
if (str1.length > compareLength)
return 1
if (str2.length > compareLength)
return -1
return 0
}
\ No newline at end of file
const opt = Object.prototype.toString;
export function isArray(obj: any): obj is any[] {
return opt.call(obj) === '[object Array]';
}
export function isObject(obj: any): obj is { [key: string]: any } {
return opt.call(obj) === '[object Object]';
}
export function isString(obj: any): obj is string {
return opt.call(obj) === '[object String]';
}
export function isNumber(obj: any): obj is number {
return opt.call(obj) === '[object Number]' && obj === obj; // eslint-disable-line
}
export function isRegExp(obj: any) {
return opt.call(obj) === '[object RegExp]';
}
export function isFile(obj: any): obj is File {
return opt.call(obj) === '[object File]';
}
export function isBlob(obj: any): obj is Blob {
return opt.call(obj) === '[object Blob]';
}
export function isUndefined(obj: any): obj is undefined {
return obj === undefined;
}
export function isNull(obj: any): obj is null {
return obj === null;
}
export function isFunction(obj: any): obj is (...args: any[]) => any {
return typeof obj === 'function';
}
export function isEmptyObject(obj: any): boolean {
return isObject(obj) && Object.keys(obj).length === 0;
}
export function isExist(obj: any): boolean {
return obj || obj === 0;
}
export function isWindow(el: any): el is Window {
return el === window;
}
export function addEventListen(
target: Window | HTMLElement,
event: string,
handler: EventListenerOrEventListenerObject,
capture = false
) {
if (
target.addEventListener &&
typeof target.addEventListener === 'function'
) {
target.addEventListener(event, handler, capture);
}
}
export function removeEventListen(
target: Window | HTMLElement,
event: string,
handler: EventListenerOrEventListenerObject,
capture = false
) {
if (
target.removeEventListener &&
typeof target.removeEventListener === 'function'
) {
target.removeEventListener(event, handler, capture);
}
}
const MAX_TRY_OUT = 30
export async function longQueryElement(selector: string, parentNode = window.document, currentTry = 1) {
return new Promise(function (resolve) {
if (currentTry > MAX_TRY_OUT) {
return resolve(null)
}
let element = parentNode.querySelector(selector)
if (element !== null) {
return resolve(element)
}
longQueryElement(selector, parentNode,currentTry + 1)
.then(resolve)
})
}
\ No newline at end of file
/**
* 将某个blob以fileName为名字直接下载,并且提供回调
* @param data {Blob} 待下载的blob
* @param fileName {String} 下载的文件名
* @param cb {Function} 下载完成的回调,默认为空方法
*/
export function downloadStream(data: Blob, fileName: string, cb = () => {}) {
const url = window.URL.createObjectURL(data)
const a = document.createElement('a')
a.download = fileName
a.href = url
a.style.display = 'none'
document.body.append(a)
a.click()
setTimeout(function () {
a.remove()
}, 60000)
if (typeof cb === 'function') {
cb();
}
}
export function directlyDownloadFromURL(fileUrl: string, fileName: string) {
window.fetch(fileUrl, {
mode: "no-cors"
}).then(res => res.blob())
.then(blob => downloadStream(blob, fileName))
}
\ No newline at end of file
import {utils, WorkBook, writeFile} from "xlsx"
/**
* 将某个html表格直接导出
* @param DOMElement {HTMLTableElement} 待导出的html表格元素
* @param fileName {String} 导出的excel文件名称
*/
export function exportLocallyExcelFunc(DOMElement: HTMLTableElement, fileName: string) {
const worksheet = utils.table_to_sheet(DOMElement, {})
const workbook: WorkBook = {
SheetNames: [fileName],
Sheets: {
[fileName]: worksheet
}
}
writeFile(workbook, fileName + '.xlsx', {
type: 'file',
bookType: 'xlsx'
})
}
/**
* 导出为包含多个表格的excel文件
* @param fileName {String} 导出的excel文件名
* @param group {{[key: string] : T[][]}} 为一个值为二维数组的键值对,表示表格名以及其内部数据。数组是一行一行数据的集合。二维数组,代表每一行每一列的数据,比如[[1,2], [3,4]]表示第一行第一列数据为1,第一行第二列数据为2,以此类推
*/
export function exportMultipleAOA<T>(fileName: string, group: { [key: string]: T[][] }) {
const workSheetsGrouping = Object.entries(group).reduce((q, w) => {
// @ts-ignore
q[w[0]] = utils.aoa_to_sheet(w[1], {})
return q
}, {})
const workbook: WorkBook = {
SheetNames: Object.keys(group),
Sheets: workSheetsGrouping
}
writeFile(workbook, fileName + '.xlsx', {
type: 'file',
bookType: 'xlsx'
})
}
/**
* 导出只包含一个表格的excel文件
* @param data {T[][]} 二维数组,代表每一行每一列的数据,比如[[1,2], [3,4]]表示第一行第一列数据为1,第一行第二列数据为2,以此类推
* @param fileName {String} 导出的excel文件名
*/
export function exportAOA<T>(data: T[][], fileName: string) {
const worksheet = utils.aoa_to_sheet(data, {})
worksheet['A1'].s = {font: {color: {rgb: "FF0000"}}}
const workbook: WorkBook = utils.book_new()
utils.book_append_sheet(workbook, worksheet, 'Sheet1')
writeFile(workbook, fileName + '.xlsx', {
type: 'file',
bookType: 'xlsx'
})
}
\ No newline at end of file
import ExcelJS from "exceljs"
import {downloadStream} from "../downloadData/downloadBlob";
export type StyleCellItem = {
value: string, // 代表数据
color?: string, // 代表文字颜色
bold?: boolean, // 是否为粗体
italic?: boolean, // 是否为斜体
underline?: boolean, // 是否有下划线
background?: string // 背景颜色
}
/**
* 导出带有格式化单元格的excel
* @param data {StyleCellItem[][]} 单元格数据的二维数组,代表每一列每一行的数据
* @param fileName {String} 导出的excel文件名
*/
export function exportAOAStyle(data: StyleCellItem[][], fileName: string) {
const wb = new ExcelJS.Workbook();
const sheet = wb.addWorksheet("Sheet1")
data.forEach(function (value, index) {
const row = sheet.getRow(index + 1)
value.forEach(function (q, w) {
const cell = row.getCell(w + 1)
cell.value = q.value;
const font = {} as any
if (q.color) {
font.color = {argb: q.color}
}
if (q.bold) {
font.bold = q.bold
}
if (q.italic) {
font.italic = q.italic
}
if (q.underline) {
font.underline = q.underline
}
if (Object.keys(font).length > 0) {
cell.font = font
}
if (q.background) {
cell.fill = {fgColor: {argb: q.background}, type: "pattern", pattern: "solid"}
}
})
})
wb.xlsx.writeBuffer()
.then(function (buffer: any) {
const blob = new Blob([buffer], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'})
downloadStream(blob, fileName + '.xlsx')
})
}
\ No newline at end of file
type TargetContext = '_self' | '_parent' | '_blank' | '_top';
export const openWindow = (
url: string,
opts?: { target?: TargetContext; [key: string]: any }
) => {
const { target = '_blank', ...others } = opts || {};
window.open(
url,
target,
Object.entries(others)
.reduce((preValue: string[], curValue) => {
const [key, value] = curValue;
return [...preValue, `${key}=${value}`];
}, [])
.join(',')
);
};
export const regexUrl = new RegExp(
'^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$',
'i'
);
export default null;
<template>
<div id="app" class="absolute p-md">
<div class="relative wrapper bg-theme-bg2 w-full h-10 rounded-sm">
{{$t('action.locale')}}
<div class="absolute right-3 flex items-center">
<locale-text class="mr-md w-24" />
<change-theme-text class="w-24 "/>
</div>
</div>
<div class="flex items-center justify-between px-md bg-theme-bg3 mt-sm h-14 rounded-sm">
{{$t('app.title')}}
<a-date-picker style="width: 200px;" />
</div>
<div class="w-full bg-theme-bg4 mt-md rounded-sm grid md:grid-cols-6 sm:grid-cols-2 gap-sm p-md">
<div class="bg-theme-bg3 text-theme-text3">col3</div>
<div class="col-span-2 bg-red-600/50">col3</div>
<div class="col-span-1 bg-theme-bg2">col3</div>
<div class="bg-theme-bg2">col3</div>
<div class="bg-theme-bg2">col3</div>
<div class="bg-theme-bg2">col3</div>
<div class="bg-theme-bg2">col3</div>
</div>
<a-button type="primary" size="large" class="px-md mt-md">
<template #icon><icon-plus/></template>
<template #default>Delete</template>
</a-button>
<a-row class="mt-md">
<a-col class="grid-item bg-slate-700" :span="12">
<div class="text-white">12 - 50%</div>
</a-col>
<a-col class="grid-item bg-slate-500" :span="12">
<div class="text-white">12 - 50%</div>
</a-col>
</a-row>
</div>
</template>
<script lang="ts" setup>
import { IconPlus } from "@arco-design/web-vue/es/icon"
import { alova } from '@/api/alova-instance'
import {onRenderTriggered as onRenderTracked} from "vue";
onRenderTracked(function (e: any) {
console.log("rendered here", e);
})
onMounted(() => {
console.log('进入首页')
alova
// .Get('/tibetmuseum/TMServer/api.php?fun_name=statisticsUserAccess&pageName=radio&timeStart=2024-02-21&timeEnd=2024-02-21')
.Get('/tibetmuseum/TMServer/api.php?fun_name=statisticsUserAccess&pageName=radio')
.then((res:any) => {
console.log(res)
})
alova
.Get('/api/user')
.then((res:any) => {
console.log(res)
})
alova
.Post('/api/login', { uName: 'admin', pwd: '123456' })
.then((res:any) => {
console.log(res)
})
})
</script>
<style>
.wrapper{
@apply flex items-center justify-center flex-wrap;
}
.grid-item{
@apply h-28 flex items-center justify-center
}
</style>
/// <reference types="vite/client" />
import { tailwindUiConfig } from './src/configs/tailwind.ui.config'
/** @type {import('tailwindcss').Config} */
export default {
darkMode: "class",
// 禁用预加载,修复tailwind样式与naive-ui等样式的冲突问题
corePlugins:{
preflight: false,
},
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}"
],
theme: {
extend: tailwindUiConfig,
},
plugins: [],
}
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"paths": {
"@/*": ["src/*"]
},
"baseUrl": "."
},
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "./*.ts"],
"references": [{ "path": "./tsconfig.node.json" }]
}
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
"strict": true
},
"include": ["vite.config.ts", "gzBundle.ts"]
}
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import {resolve} from 'path'
import Components from 'unplugin-vue-components/vite'
import AutoImport from 'unplugin-auto-import/vite'
import {ArcoResolver} from 'unplugin-vue-components/resolvers'
import {vitePluginForArco} from '@arco-plugins/vite-vue'
import viteCompression from 'vite-plugin-compression'
// @ts-ignore
import {arcoUiConfig} from './src/configs/arco.ui.config.ts'
// @ts-ignore
import appDefine from './project.app.config'
// https://vitejs.dev/config/
export default defineConfig({
css: {
preprocessorOptions: {
less: {
modifyVars: arcoUiConfig, // 定制less变量
javascriptEnabled: true,
}
}
},
plugins: [
vue(),
vitePluginForArco(),
AutoImport({
imports: ['vue', 'vue-router'],
dts: 'src/auto-import.d.ts',
resolvers: [
ArcoResolver()
],
}),
Components({
// 自动导入的组件位置,默认是src/components
dirs: ['src/components'],
resolvers: [
ArcoResolver({
importStyle: 'less',
resolveIcons: true,
sideEffect: true,
})
],
dts: false,
}),
viteCompression({
disable: !appDefine.enableGZip, // 是否禁用
deleteOriginFile: true, // 删除源文件,删除后nginx没有开启压缩的情况下,就不可以访问
}),
],
resolve: {
alias: {
'@': resolve('src')
}
},
base: './', // 打包路径
server: {
port: 3000, // 启动端口
open: true, // 自动打开
cors: true, // 跨域
},
})
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