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
// @ts-nocheck
//---------------------------------------------------------------------
//
// QR Code Generator for JavaScript
//
// Copyright (c) 2009 Kazuhiko Arase
//
// URL: http://www.d-project.com/
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license.php
//
// The word 'QR Code' is registered trademark of
// DENSO WAVE INCORPORATED
// http://www.denso-wave.com/qrcode/faqpatent-e.html
//
//---------------------------------------------------------------------
let qrcode = function() {
//---------------------------------------------------------------------
// qrcode
//---------------------------------------------------------------------
/**
* qrcode
* @param typeNumber 1 to 40
* @param errorCorrectionLevel 'L','M','Q','H'
*/
let qrcode = function(typeNumber, errorCorrectionLevel) {
let PAD0 = 0xEC;
let PAD1 = 0x11;
let _typeNumber = typeNumber;
let _errorCorrectionLevel = QRErrorCorrectionLevel[errorCorrectionLevel];
let _modules = null;
let _moduleCount = 0;
let _dataCache = null;
let _dataList = [];
let _this = {};
let makeImpl = function(test, maskPattern) {
_moduleCount = _typeNumber * 4 + 17;
_modules = function(moduleCount) {
let modules = new Array(moduleCount);
for (let row = 0; row < moduleCount; row += 1) {
modules[row] = new Array(moduleCount);
for (let col = 0; col < moduleCount; col += 1) {
modules[row][col] = null;
}
}
return modules;
}(_moduleCount);
setupPositionProbePattern(0, 0);
setupPositionProbePattern(_moduleCount - 7, 0);
setupPositionProbePattern(0, _moduleCount - 7);
setupPositionAdjustPattern();
setupTimingPattern();
setupTypeInfo(test, maskPattern);
if (_typeNumber >= 7) {
setupTypeNumber(test);
}
if (_dataCache == null) {
_dataCache = createData(_typeNumber, _errorCorrectionLevel, _dataList);
}
mapData(_dataCache, maskPattern);
};
let setupPositionProbePattern = function(row, col) {
for (let r = -1; r <= 7; r += 1) {
if (row + r <= -1 || _moduleCount <= row + r) continue;
for (let c = -1; c <= 7; c += 1) {
if (col + c <= -1 || _moduleCount <= col + c) continue;
if ( (0 <= r && r <= 6 && (c == 0 || c == 6) )
|| (0 <= c && c <= 6 && (r == 0 || r == 6) )
|| (2 <= r && r <= 4 && 2 <= c && c <= 4) ) {
_modules[row + r][col + c] = true;
} else {
_modules[row + r][col + c] = false;
}
}
}
};
let getBestMaskPattern = function() {
let minLostPoint = 0;
let pattern = 0;
for (let i = 0; i < 8; i += 1) {
makeImpl(true, i);
let lostPoint = QRUtil.getLostPoint(_this);
if (i == 0 || minLostPoint > lostPoint) {
minLostPoint = lostPoint;
pattern = i;
}
}
return pattern;
};
let setupTimingPattern = function() {
for (let r = 8; r < _moduleCount - 8; r += 1) {
if (_modules[r][6] != null) {
continue;
}
_modules[r][6] = (r % 2 == 0);
}
for (let c = 8; c < _moduleCount - 8; c += 1) {
if (_modules[6][c] != null) {
continue;
}
_modules[6][c] = (c % 2 == 0);
}
};
let setupPositionAdjustPattern = function() {
let pos = QRUtil.getPatternPosition(_typeNumber);
for (let i = 0; i < pos.length; i += 1) {
for (let j = 0; j < pos.length; j += 1) {
let row = pos[i];
let col = pos[j];
if (_modules[row][col] != null) {
continue;
}
for (let r = -2; r <= 2; r += 1) {
for (let c = -2; c <= 2; c += 1) {
if (r == -2 || r == 2 || c == -2 || c == 2
|| (r == 0 && c == 0) ) {
_modules[row + r][col + c] = true;
} else {
_modules[row + r][col + c] = false;
}
}
}
}
}
};
let setupTypeNumber = function(test) {
let bits = QRUtil.getBCHTypeNumber(_typeNumber);
for (let i = 0; i < 18; i += 1) {
let mod = (!test && ( (bits >> i) & 1) == 1);
_modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;
}
for (let i = 0; i < 18; i += 1) {
let mod = (!test && ( (bits >> i) & 1) == 1);
_modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
}
};
let setupTypeInfo = function(test, maskPattern) {
let data = (_errorCorrectionLevel << 3) | maskPattern;
let bits = QRUtil.getBCHTypeInfo(data);
// vertical
for (let i = 0; i < 15; i += 1) {
let mod = (!test && ( (bits >> i) & 1) == 1);
if (i < 6) {
_modules[i][8] = mod;
} else if (i < 8) {
_modules[i + 1][8] = mod;
} else {
_modules[_moduleCount - 15 + i][8] = mod;
}
}
// horizontal
for (let i = 0; i < 15; i += 1) {
let mod = (!test && ( (bits >> i) & 1) == 1);
if (i < 8) {
_modules[8][_moduleCount - i - 1] = mod;
} else if (i < 9) {
_modules[8][15 - i - 1 + 1] = mod;
} else {
_modules[8][15 - i - 1] = mod;
}
}
// fixed module
_modules[_moduleCount - 8][8] = (!test);
};
let mapData = function(data, maskPattern) {
let inc = -1;
let row = _moduleCount - 1;
let bitIndex = 7;
let byteIndex = 0;
let maskFunc = QRUtil.getMaskFunction(maskPattern);
for (let col = _moduleCount - 1; col > 0; col -= 2) {
if (col == 6) col -= 1;
while (true) {
for (let c = 0; c < 2; c += 1) {
if (_modules[row][col - c] == null) {
let dark = false;
if (byteIndex < data.length) {
dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1);
}
let mask = maskFunc(row, col - c);
if (mask) {
dark = !dark;
}
_modules[row][col - c] = dark;
bitIndex -= 1;
if (bitIndex == -1) {
byteIndex += 1;
bitIndex = 7;
}
}
}
row += inc;
if (row < 0 || _moduleCount <= row) {
row -= inc;
inc = -inc;
break;
}
}
}
};
let createBytes = function(buffer, rsBlocks) {
let offset = 0;
let maxDcCount = 0;
let maxEcCount = 0;
let dcdata = new Array(rsBlocks.length);
let ecdata = new Array(rsBlocks.length);
for (let r = 0; r < rsBlocks.length; r += 1) {
let dcCount = rsBlocks[r].dataCount;
let ecCount = rsBlocks[r].totalCount - dcCount;
maxDcCount = Math.max(maxDcCount, dcCount);
maxEcCount = Math.max(maxEcCount, ecCount);
dcdata[r] = new Array(dcCount);
for (let i = 0; i < dcdata[r].length; i += 1) {
dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset];
}
offset += dcCount;
let rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
let rawPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1);
let modPoly = rawPoly.mod(rsPoly);
ecdata[r] = new Array(rsPoly.getLength() - 1);
for (let i = 0; i < ecdata[r].length; i += 1) {
let modIndex = i + modPoly.getLength() - ecdata[r].length;
ecdata[r][i] = (modIndex >= 0)? modPoly.getAt(modIndex) : 0;
}
}
let totalCodeCount = 0;
for (let i = 0; i < rsBlocks.length; i += 1) {
totalCodeCount += rsBlocks[i].totalCount;
}
let data = new Array(totalCodeCount);
let index = 0;
for (let i = 0; i < maxDcCount; i += 1) {
for (let r = 0; r < rsBlocks.length; r += 1) {
if (i < dcdata[r].length) {
data[index] = dcdata[r][i];
index += 1;
}
}
}
for (let i = 0; i < maxEcCount; i += 1) {
for (let r = 0; r < rsBlocks.length; r += 1) {
if (i < ecdata[r].length) {
data[index] = ecdata[r][i];
index += 1;
}
}
}
return data;
};
let createData = function(typeNumber, errorCorrectionLevel, dataList) {
let rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectionLevel);
let buffer = qrBitBuffer();
for (let i = 0; i < dataList.length; i += 1) {
let data = dataList[i];
buffer.put(data.getMode(), 4);
buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );
data.write(buffer);
}
// calc num max data.
let totalDataCount = 0;
for (let i = 0; i < rsBlocks.length; i += 1) {
totalDataCount += rsBlocks[i].dataCount;
}
if (buffer.getLengthInBits() > totalDataCount * 8) {
throw 'code length overflow. ('
+ buffer.getLengthInBits()
+ '>'
+ totalDataCount * 8
+ ')';
}
// end code
if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
buffer.put(0, 4);
}
// padding
while (buffer.getLengthInBits() % 8 != 0) {
buffer.putBit(false);
}
// padding
while (true) {
if (buffer.getLengthInBits() >= totalDataCount * 8) {
break;
}
buffer.put(PAD0, 8);
if (buffer.getLengthInBits() >= totalDataCount * 8) {
break;
}
buffer.put(PAD1, 8);
}
return createBytes(buffer, rsBlocks);
};
_this.addData = function(data, mode) {
mode = mode || 'Byte';
let newData = null;
switch(mode) {
case 'Numeric' :
newData = qrNumber(data);
break;
case 'Alphanumeric' :
newData = qrAlphaNum(data);
break;
case 'Byte' :
newData = qr8BitByte(data);
break;
case 'Kanji' :
newData = qrKanji(data);
break;
default :
throw 'mode:' + mode;
}
_dataList.push(newData);
_dataCache = null;
};
_this.isDark = function(row, col) {
if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) {
throw row + ',' + col;
}
return _modules[row][col];
};
_this.getModuleCount = function() {
return _moduleCount;
};
_this.make = function() {
if (_typeNumber < 1) {
let typeNumber = 1;
for (; typeNumber < 40; typeNumber++) {
let rsBlocks = QRRSBlock.getRSBlocks(typeNumber, _errorCorrectionLevel);
let buffer = qrBitBuffer();
for (let i = 0; i < _dataList.length; i++) {
let data = _dataList[i];
buffer.put(data.getMode(), 4);
buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );
data.write(buffer);
}
let totalDataCount = 0;
for (let i = 0; i < rsBlocks.length; i++) {
totalDataCount += rsBlocks[i].dataCount;
}
if (buffer.getLengthInBits() <= totalDataCount * 8) {
break;
}
}
_typeNumber = typeNumber;
}
makeImpl(false, getBestMaskPattern() );
};
_this.createTableTag = function(cellSize, margin) {
cellSize = cellSize || 2;
margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
let qrHtml = '';
qrHtml += '<table style="';
qrHtml += ' border-width: 0px; border-style: none;';
qrHtml += ' border-collapse: collapse;';
qrHtml += ' padding: 0px; margin: ' + margin + 'px;';
qrHtml += '">';
qrHtml += '<tbody>';
for (let r = 0; r < _this.getModuleCount(); r += 1) {
qrHtml += '<tr>';
for (let c = 0; c < _this.getModuleCount(); c += 1) {
qrHtml += '<td style="';
qrHtml += ' border-width: 0px; border-style: none;';
qrHtml += ' border-collapse: collapse;';
qrHtml += ' padding: 0px; margin: 0px;';
qrHtml += ' width: ' + cellSize + 'px;';
qrHtml += ' height: ' + cellSize + 'px;';
qrHtml += ' background-color: ';
qrHtml += _this.isDark(r, c)? '#000000' : '#ffffff';
qrHtml += ';';
qrHtml += '"/>';
}
qrHtml += '</tr>';
}
qrHtml += '</tbody>';
qrHtml += '</table>';
return qrHtml;
};
_this.createSvgTag = function(cellSize, margin, alt, title) {
let opts = {};
if (typeof arguments[0] == 'object') {
// Called by options.
opts = arguments[0];
// overwrite cellSize and margin.
cellSize = opts.cellSize;
margin = opts.margin;
alt = opts.alt;
title = opts.title;
}
cellSize = cellSize || 2;
margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
// Compose alt property surrogate
alt = (typeof alt === 'string') ? {text: alt} : alt || {};
alt.text = alt.text || null;
alt.id = (alt.text) ? alt.id || 'qrcode-description' : null;
// Compose title property surrogate
title = (typeof title === 'string') ? {text: title} : title || {};
title.text = title.text || null;
title.id = (title.text) ? title.id || 'qrcode-title' : null;
let size = _this.getModuleCount() * cellSize + margin * 2;
let c, mc, r, mr, qrSvg='', rect;
rect = 'l' + cellSize + ',0 0,' + cellSize +
' -' + cellSize + ',0 0,-' + cellSize + 'z ';
qrSvg += '<svg version="1.1" xmlns="http://www.w3.org/2000/svg"';
qrSvg += !opts.scalable ? ' width="' + size + 'px" height="' + size + 'px"' : '';
qrSvg += ' viewBox="0 0 ' + size + ' ' + size + '" ';
qrSvg += ' preserveAspectRatio="xMinYMin meet"';
qrSvg += (title.text || alt.text) ? ' role="img" aria-labelledby="' +
escapeXml([title.id, alt.id].join(' ').trim() ) + '"' : '';
qrSvg += '>';
qrSvg += (title.text) ? '<title id="' + escapeXml(title.id) + '">' +
escapeXml(title.text) + '</title>' : '';
qrSvg += (alt.text) ? '<description id="' + escapeXml(alt.id) + '">' +
escapeXml(alt.text) + '</description>' : '';
qrSvg += '<rect width="100%" height="100%" fill="white" cx="0" cy="0"/>';
qrSvg += '<path d="';
for (r = 0; r < _this.getModuleCount(); r += 1) {
mr = r * cellSize + margin;
for (c = 0; c < _this.getModuleCount(); c += 1) {
if (_this.isDark(r, c) ) {
mc = c*cellSize+margin;
qrSvg += 'M' + mc + ',' + mr + rect;
}
}
}
qrSvg += '" stroke="transparent" fill="black"/>';
qrSvg += '</svg>';
return qrSvg;
};
_this.createDataURL = function(cellSize, margin) {
cellSize = cellSize || 2;
margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
let size = _this.getModuleCount() * cellSize + margin * 2;
let min = margin;
let max = size - margin;
return createDataURL(size, size, function(x, y) {
if (min <= x && x < max && min <= y && y < max) {
let c = Math.floor( (x - min) / cellSize);
let r = Math.floor( (y - min) / cellSize);
return _this.isDark(r, c)? 0 : 1;
} else {
return 1;
}
} );
};
_this.createImgTag = function(cellSize, margin, alt) {
cellSize = cellSize || 2;
margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
let size = _this.getModuleCount() * cellSize + margin * 2;
let img = '';
img += '<img';
img += '\u0020src="';
img += _this.createDataURL(cellSize, margin);
img += '"';
img += '\u0020width="';
img += size;
img += '"';
img += '\u0020height="';
img += size;
img += '"';
if (alt) {
img += '\u0020alt="';
img += escapeXml(alt);
img += '"';
}
img += '/>';
return img;
};
let escapeXml = function(s) {
let escaped = '';
for (let i = 0; i < s.length; i += 1) {
let c = s.charAt(i);
switch(c) {
case '<': escaped += '&lt;'; break;
case '>': escaped += '&gt;'; break;
case '&': escaped += '&amp;'; break;
case '"': escaped += '&quot;'; break;
default : escaped += c; break;
}
}
return escaped;
};
let _createHalfASCII = function(margin) {
let cellSize = 1;
margin = (typeof margin == 'undefined')? cellSize * 2 : margin;
let size = _this.getModuleCount() * cellSize + margin * 2;
let min = margin;
let max = size - margin;
let y, x, r1, r2, p;
let blocks = {
'██': '█',
'█ ': '▀',
' █': '▄',
' ': ' '
};
let blocksLastLineNoMargin = {
'██': '▀',
'█ ': '▀',
' █': ' ',
' ': ' '
};
let ascii = '';
for (y = 0; y < size; y += 2) {
r1 = Math.floor((y - min) / cellSize);
r2 = Math.floor((y + 1 - min) / cellSize);
for (x = 0; x < size; x += 1) {
p = '█';
if (min <= x && x < max && min <= y && y < max && _this.isDark(r1, Math.floor((x - min) / cellSize))) {
p = ' ';
}
if (min <= x && x < max && min <= y+1 && y+1 < max && _this.isDark(r2, Math.floor((x - min) / cellSize))) {
p += ' ';
}
else {
p += '█';
}
// Output 2 characters per pixel, to create full square. 1 character per pixels gives only half width of square.
ascii += (margin < 1 && y+1 >= max) ? blocksLastLineNoMargin[p] : blocks[p];
}
ascii += '\n';
}
if (size % 2 && margin > 0) {
return ascii.substring(0, ascii.length - size - 1) + Array(size+1).join('▀');
}
return ascii.substring(0, ascii.length-1);
};
_this.createASCII = function(cellSize, margin) {
cellSize = cellSize || 1;
if (cellSize < 2) {
return _createHalfASCII(margin);
}
cellSize -= 1;
margin = (typeof margin == 'undefined')? cellSize * 2 : margin;
let size = _this.getModuleCount() * cellSize + margin * 2;
let min = margin;
let max = size - margin;
let y, x, r, p;
let white = Array(cellSize+1).join('██');
let black = Array(cellSize+1).join(' ');
let ascii = '';
let line = '';
for (y = 0; y < size; y += 1) {
r = Math.floor( (y - min) / cellSize);
line = '';
for (x = 0; x < size; x += 1) {
p = 1;
if (min <= x && x < max && min <= y && y < max && _this.isDark(r, Math.floor((x - min) / cellSize))) {
p = 0;
}
// Output 2 characters per pixel, to create full square. 1 character per pixels gives only half width of square.
line += p ? white : black;
}
for (r = 0; r < cellSize; r += 1) {
ascii += line + '\n';
}
}
return ascii.substring(0, ascii.length-1);
};
_this.renderTo2dContext = function(context, cellSize) {
cellSize = cellSize || 2;
let length = _this.getModuleCount();
for (let row = 0; row < length; row++) {
for (let col = 0; col < length; col++) {
context.fillStyle = _this.isDark(row, col) ? 'black' : 'white';
context.fillRect(row * cellSize, col * cellSize, cellSize, cellSize);
}
}
}
return _this;
};
//---------------------------------------------------------------------
// qrcode.stringToBytes
//---------------------------------------------------------------------
qrcode.stringToBytesFuncs = {
'default' : function(s) {
let bytes = [];
for (let i = 0; i < s.length; i += 1) {
let c = s.charCodeAt(i);
bytes.push(c & 0xff);
}
return bytes;
}
};
qrcode.stringToBytes = qrcode.stringToBytesFuncs['default'];
//---------------------------------------------------------------------
// qrcode.createStringToBytes
//---------------------------------------------------------------------
/**
* @param unicodeData base64 string of byte array.
* [16bit Unicode],[16bit Bytes], ...
* @param numChars
*/
qrcode.createStringToBytes = function(unicodeData, numChars) {
// create conversion map.
let unicodeMap = function() {
let bin = base64DecodeInputStream(unicodeData);
let read = function() {
let b = bin.read();
if (b == -1) throw 'eof';
return b;
};
let count = 0;
let unicodeMap = {};
while (true) {
let b0 = bin.read();
if (b0 == -1) break;
let b1 = read();
let b2 = read();
let b3 = read();
let k = String.fromCharCode( (b0 << 8) | b1);
let v = (b2 << 8) | b3;
unicodeMap[k] = v;
count += 1;
}
if (count != numChars) {
throw count + ' != ' + numChars;
}
return unicodeMap;
}();
let unknownChar = '?'.charCodeAt(0);
return function(s) {
let bytes = [];
for (let i = 0; i < s.length; i += 1) {
let c = s.charCodeAt(i);
if (c < 128) {
bytes.push(c);
} else {
let b = unicodeMap[s.charAt(i)];
if (typeof b == 'number') {
if ( (b & 0xff) == b) {
// 1byte
bytes.push(b);
} else {
// 2bytes
bytes.push(b >>> 8);
bytes.push(b & 0xff);
}
} else {
bytes.push(unknownChar);
}
}
}
return bytes;
};
};
//---------------------------------------------------------------------
// QRMode
//---------------------------------------------------------------------
let QRMode = {
MODE_NUMBER : 1 << 0,
MODE_ALPHA_NUM : 1 << 1,
MODE_8BIT_BYTE : 1 << 2,
MODE_KANJI : 1 << 3
};
//---------------------------------------------------------------------
// QRErrorCorrectionLevel
//---------------------------------------------------------------------
let QRErrorCorrectionLevel = {
L : 1,
M : 0,
Q : 3,
H : 2
};
//---------------------------------------------------------------------
// QRMaskPattern
//---------------------------------------------------------------------
let QRMaskPattern = {
PATTERN000 : 0,
PATTERN001 : 1,
PATTERN010 : 2,
PATTERN011 : 3,
PATTERN100 : 4,
PATTERN101 : 5,
PATTERN110 : 6,
PATTERN111 : 7
};
//---------------------------------------------------------------------
// QRUtil
//---------------------------------------------------------------------
let QRUtil = function() {
let PATTERN_POSITION_TABLE = [
[],
[6, 18],
[6, 22],
[6, 26],
[6, 30],
[6, 34],
[6, 22, 38],
[6, 24, 42],
[6, 26, 46],
[6, 28, 50],
[6, 30, 54],
[6, 32, 58],
[6, 34, 62],
[6, 26, 46, 66],
[6, 26, 48, 70],
[6, 26, 50, 74],
[6, 30, 54, 78],
[6, 30, 56, 82],
[6, 30, 58, 86],
[6, 34, 62, 90],
[6, 28, 50, 72, 94],
[6, 26, 50, 74, 98],
[6, 30, 54, 78, 102],
[6, 28, 54, 80, 106],
[6, 32, 58, 84, 110],
[6, 30, 58, 86, 114],
[6, 34, 62, 90, 118],
[6, 26, 50, 74, 98, 122],
[6, 30, 54, 78, 102, 126],
[6, 26, 52, 78, 104, 130],
[6, 30, 56, 82, 108, 134],
[6, 34, 60, 86, 112, 138],
[6, 30, 58, 86, 114, 142],
[6, 34, 62, 90, 118, 146],
[6, 30, 54, 78, 102, 126, 150],
[6, 24, 50, 76, 102, 128, 154],
[6, 28, 54, 80, 106, 132, 158],
[6, 32, 58, 84, 110, 136, 162],
[6, 26, 54, 82, 110, 138, 166],
[6, 30, 58, 86, 114, 142, 170]
];
let G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
let G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);
let G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);
let _this = {};
let getBCHDigit = function(data) {
let digit = 0;
while (data != 0) {
digit += 1;
data >>>= 1;
}
return digit;
};
_this.getBCHTypeInfo = function(data) {
let d = data << 10;
while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {
d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) );
}
return ( (data << 10) | d) ^ G15_MASK;
};
_this.getBCHTypeNumber = function(data) {
let d = data << 12;
while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {
d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) );
}
return (data << 12) | d;
};
_this.getPatternPosition = function(typeNumber) {
return PATTERN_POSITION_TABLE[typeNumber - 1];
};
_this.getMaskFunction = function(maskPattern) {
switch (maskPattern) {
case QRMaskPattern.PATTERN000 :
return function(i, j) { return (i + j) % 2 == 0; };
case QRMaskPattern.PATTERN001 :
return function(i, j) { return i % 2 == 0; };
case QRMaskPattern.PATTERN010 :
return function(i, j) { return j % 3 == 0; };
case QRMaskPattern.PATTERN011 :
return function(i, j) { return (i + j) % 3 == 0; };
case QRMaskPattern.PATTERN100 :
return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; };
case QRMaskPattern.PATTERN101 :
return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; };
case QRMaskPattern.PATTERN110 :
return function(i, j) { return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; };
case QRMaskPattern.PATTERN111 :
return function(i, j) { return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; };
default :
throw 'bad maskPattern:' + maskPattern;
}
};
_this.getErrorCorrectPolynomial = function(errorCorrectLength) {
let a = qrPolynomial([1], 0);
for (let i = 0; i < errorCorrectLength; i += 1) {
a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0) );
}
return a;
};
_this.getLengthInBits = function(mode, type) {
if (1 <= type && type < 10) {
// 1 - 9
switch(mode) {
case QRMode.MODE_NUMBER : return 10;
case QRMode.MODE_ALPHA_NUM : return 9;
case QRMode.MODE_8BIT_BYTE : return 8;
case QRMode.MODE_KANJI : return 8;
default :
throw 'mode:' + mode;
}
} else if (type < 27) {
// 10 - 26
switch(mode) {
case QRMode.MODE_NUMBER : return 12;
case QRMode.MODE_ALPHA_NUM : return 11;
case QRMode.MODE_8BIT_BYTE : return 16;
case QRMode.MODE_KANJI : return 10;
default :
throw 'mode:' + mode;
}
} else if (type < 41) {
// 27 - 40
switch(mode) {
case QRMode.MODE_NUMBER : return 14;
case QRMode.MODE_ALPHA_NUM : return 13;
case QRMode.MODE_8BIT_BYTE : return 16;
case QRMode.MODE_KANJI : return 12;
default :
throw 'mode:' + mode;
}
} else {
throw 'type:' + type;
}
};
_this.getLostPoint = function(qrcode) {
let moduleCount = qrcode.getModuleCount();
let lostPoint = 0;
// LEVEL1
for (let row = 0; row < moduleCount; row += 1) {
for (let col = 0; col < moduleCount; col += 1) {
let sameCount = 0;
let dark = qrcode.isDark(row, col);
for (let r = -1; r <= 1; r += 1) {
if (row + r < 0 || moduleCount <= row + r) {
continue;
}
for (let c = -1; c <= 1; c += 1) {
if (col + c < 0 || moduleCount <= col + c) {
continue;
}
if (r == 0 && c == 0) {
continue;
}
if (dark == qrcode.isDark(row + r, col + c) ) {
sameCount += 1;
}
}
}
if (sameCount > 5) {
lostPoint += (3 + sameCount - 5);
}
}
};
// LEVEL2
for (let row = 0; row < moduleCount - 1; row += 1) {
for (let col = 0; col < moduleCount - 1; col += 1) {
let count = 0;
if (qrcode.isDark(row, col) ) count += 1;
if (qrcode.isDark(row + 1, col) ) count += 1;
if (qrcode.isDark(row, col + 1) ) count += 1;
if (qrcode.isDark(row + 1, col + 1) ) count += 1;
if (count == 0 || count == 4) {
lostPoint += 3;
}
}
}
// LEVEL3
for (let row = 0; row < moduleCount; row += 1) {
for (let col = 0; col < moduleCount - 6; col += 1) {
if (qrcode.isDark(row, col)
&& !qrcode.isDark(row, col + 1)
&& qrcode.isDark(row, col + 2)
&& qrcode.isDark(row, col + 3)
&& qrcode.isDark(row, col + 4)
&& !qrcode.isDark(row, col + 5)
&& qrcode.isDark(row, col + 6) ) {
lostPoint += 40;
}
}
}
for (let col = 0; col < moduleCount; col += 1) {
for (let row = 0; row < moduleCount - 6; row += 1) {
if (qrcode.isDark(row, col)
&& !qrcode.isDark(row + 1, col)
&& qrcode.isDark(row + 2, col)
&& qrcode.isDark(row + 3, col)
&& qrcode.isDark(row + 4, col)
&& !qrcode.isDark(row + 5, col)
&& qrcode.isDark(row + 6, col) ) {
lostPoint += 40;
}
}
}
// LEVEL4
let darkCount = 0;
for (let col = 0; col < moduleCount; col += 1) {
for (let row = 0; row < moduleCount; row += 1) {
if (qrcode.isDark(row, col) ) {
darkCount += 1;
}
}
}
let ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
lostPoint += ratio * 10;
return lostPoint;
};
return _this;
}();
//---------------------------------------------------------------------
// QRMath
//---------------------------------------------------------------------
let QRMath = function() {
let EXP_TABLE = new Array(256);
let LOG_TABLE = new Array(256);
// initialize tables
for (let i = 0; i < 8; i += 1) {
EXP_TABLE[i] = 1 << i;
}
for (let i = 8; i < 256; i += 1) {
EXP_TABLE[i] = EXP_TABLE[i - 4]
^ EXP_TABLE[i - 5]
^ EXP_TABLE[i - 6]
^ EXP_TABLE[i - 8];
}
for (let i = 0; i < 255; i += 1) {
LOG_TABLE[EXP_TABLE[i] ] = i;
}
let _this = {};
_this.glog = function(n) {
if (n < 1) {
throw 'glog(' + n + ')';
}
return LOG_TABLE[n];
};
_this.gexp = function(n) {
while (n < 0) {
n += 255;
}
while (n >= 256) {
n -= 255;
}
return EXP_TABLE[n];
};
return _this;
}();
//---------------------------------------------------------------------
// qrPolynomial
//---------------------------------------------------------------------
function qrPolynomial(num, shift) {
if (typeof num.length == 'undefined') {
throw num.length + '/' + shift;
}
let _num = function() {
let offset = 0;
while (offset < num.length && num[offset] == 0) {
offset += 1;
}
let _num = new Array(num.length - offset + shift);
for (let i = 0; i < num.length - offset; i += 1) {
_num[i] = num[i + offset];
}
return _num;
}();
let _this = {};
_this.getAt = function(index) {
return _num[index];
};
_this.getLength = function() {
return _num.length;
};
_this.multiply = function(e) {
let num = new Array(_this.getLength() + e.getLength() - 1);
for (let i = 0; i < _this.getLength(); i += 1) {
for (let j = 0; j < e.getLength(); j += 1) {
num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i) ) + QRMath.glog(e.getAt(j) ) );
}
}
return qrPolynomial(num, 0);
};
_this.mod = function(e) {
if (_this.getLength() - e.getLength() < 0) {
return _this;
}
let ratio = QRMath.glog(_this.getAt(0) ) - QRMath.glog(e.getAt(0) );
let num = new Array(_this.getLength() );
for (let i = 0; i < _this.getLength(); i += 1) {
num[i] = _this.getAt(i);
}
for (let i = 0; i < e.getLength(); i += 1) {
num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i) ) + ratio);
}
// recursive call
return qrPolynomial(num, 0).mod(e);
};
return _this;
};
//---------------------------------------------------------------------
// QRRSBlock
//---------------------------------------------------------------------
let QRRSBlock = function() {
let RS_BLOCK_TABLE = [
// L
// M
// Q
// H
// 1
[1, 26, 19],
[1, 26, 16],
[1, 26, 13],
[1, 26, 9],
// 2
[1, 44, 34],
[1, 44, 28],
[1, 44, 22],
[1, 44, 16],
// 3
[1, 70, 55],
[1, 70, 44],
[2, 35, 17],
[2, 35, 13],
// 4
[1, 100, 80],
[2, 50, 32],
[2, 50, 24],
[4, 25, 9],
// 5
[1, 134, 108],
[2, 67, 43],
[2, 33, 15, 2, 34, 16],
[2, 33, 11, 2, 34, 12],
// 6
[2, 86, 68],
[4, 43, 27],
[4, 43, 19],
[4, 43, 15],
// 7
[2, 98, 78],
[4, 49, 31],
[2, 32, 14, 4, 33, 15],
[4, 39, 13, 1, 40, 14],
// 8
[2, 121, 97],
[2, 60, 38, 2, 61, 39],
[4, 40, 18, 2, 41, 19],
[4, 40, 14, 2, 41, 15],
// 9
[2, 146, 116],
[3, 58, 36, 2, 59, 37],
[4, 36, 16, 4, 37, 17],
[4, 36, 12, 4, 37, 13],
// 10
[2, 86, 68, 2, 87, 69],
[4, 69, 43, 1, 70, 44],
[6, 43, 19, 2, 44, 20],
[6, 43, 15, 2, 44, 16],
// 11
[4, 101, 81],
[1, 80, 50, 4, 81, 51],
[4, 50, 22, 4, 51, 23],
[3, 36, 12, 8, 37, 13],
// 12
[2, 116, 92, 2, 117, 93],
[6, 58, 36, 2, 59, 37],
[4, 46, 20, 6, 47, 21],
[7, 42, 14, 4, 43, 15],
// 13
[4, 133, 107],
[8, 59, 37, 1, 60, 38],
[8, 44, 20, 4, 45, 21],
[12, 33, 11, 4, 34, 12],
// 14
[3, 145, 115, 1, 146, 116],
[4, 64, 40, 5, 65, 41],
[11, 36, 16, 5, 37, 17],
[11, 36, 12, 5, 37, 13],
// 15
[5, 109, 87, 1, 110, 88],
[5, 65, 41, 5, 66, 42],
[5, 54, 24, 7, 55, 25],
[11, 36, 12, 7, 37, 13],
// 16
[5, 122, 98, 1, 123, 99],
[7, 73, 45, 3, 74, 46],
[15, 43, 19, 2, 44, 20],
[3, 45, 15, 13, 46, 16],
// 17
[1, 135, 107, 5, 136, 108],
[10, 74, 46, 1, 75, 47],
[1, 50, 22, 15, 51, 23],
[2, 42, 14, 17, 43, 15],
// 18
[5, 150, 120, 1, 151, 121],
[9, 69, 43, 4, 70, 44],
[17, 50, 22, 1, 51, 23],
[2, 42, 14, 19, 43, 15],
// 19
[3, 141, 113, 4, 142, 114],
[3, 70, 44, 11, 71, 45],
[17, 47, 21, 4, 48, 22],
[9, 39, 13, 16, 40, 14],
// 20
[3, 135, 107, 5, 136, 108],
[3, 67, 41, 13, 68, 42],
[15, 54, 24, 5, 55, 25],
[15, 43, 15, 10, 44, 16],
// 21
[4, 144, 116, 4, 145, 117],
[17, 68, 42],
[17, 50, 22, 6, 51, 23],
[19, 46, 16, 6, 47, 17],
// 22
[2, 139, 111, 7, 140, 112],
[17, 74, 46],
[7, 54, 24, 16, 55, 25],
[34, 37, 13],
// 23
[4, 151, 121, 5, 152, 122],
[4, 75, 47, 14, 76, 48],
[11, 54, 24, 14, 55, 25],
[16, 45, 15, 14, 46, 16],
// 24
[6, 147, 117, 4, 148, 118],
[6, 73, 45, 14, 74, 46],
[11, 54, 24, 16, 55, 25],
[30, 46, 16, 2, 47, 17],
// 25
[8, 132, 106, 4, 133, 107],
[8, 75, 47, 13, 76, 48],
[7, 54, 24, 22, 55, 25],
[22, 45, 15, 13, 46, 16],
// 26
[10, 142, 114, 2, 143, 115],
[19, 74, 46, 4, 75, 47],
[28, 50, 22, 6, 51, 23],
[33, 46, 16, 4, 47, 17],
// 27
[8, 152, 122, 4, 153, 123],
[22, 73, 45, 3, 74, 46],
[8, 53, 23, 26, 54, 24],
[12, 45, 15, 28, 46, 16],
// 28
[3, 147, 117, 10, 148, 118],
[3, 73, 45, 23, 74, 46],
[4, 54, 24, 31, 55, 25],
[11, 45, 15, 31, 46, 16],
// 29
[7, 146, 116, 7, 147, 117],
[21, 73, 45, 7, 74, 46],
[1, 53, 23, 37, 54, 24],
[19, 45, 15, 26, 46, 16],
// 30
[5, 145, 115, 10, 146, 116],
[19, 75, 47, 10, 76, 48],
[15, 54, 24, 25, 55, 25],
[23, 45, 15, 25, 46, 16],
// 31
[13, 145, 115, 3, 146, 116],
[2, 74, 46, 29, 75, 47],
[42, 54, 24, 1, 55, 25],
[23, 45, 15, 28, 46, 16],
// 32
[17, 145, 115],
[10, 74, 46, 23, 75, 47],
[10, 54, 24, 35, 55, 25],
[19, 45, 15, 35, 46, 16],
// 33
[17, 145, 115, 1, 146, 116],
[14, 74, 46, 21, 75, 47],
[29, 54, 24, 19, 55, 25],
[11, 45, 15, 46, 46, 16],
// 34
[13, 145, 115, 6, 146, 116],
[14, 74, 46, 23, 75, 47],
[44, 54, 24, 7, 55, 25],
[59, 46, 16, 1, 47, 17],
// 35
[12, 151, 121, 7, 152, 122],
[12, 75, 47, 26, 76, 48],
[39, 54, 24, 14, 55, 25],
[22, 45, 15, 41, 46, 16],
// 36
[6, 151, 121, 14, 152, 122],
[6, 75, 47, 34, 76, 48],
[46, 54, 24, 10, 55, 25],
[2, 45, 15, 64, 46, 16],
// 37
[17, 152, 122, 4, 153, 123],
[29, 74, 46, 14, 75, 47],
[49, 54, 24, 10, 55, 25],
[24, 45, 15, 46, 46, 16],
// 38
[4, 152, 122, 18, 153, 123],
[13, 74, 46, 32, 75, 47],
[48, 54, 24, 14, 55, 25],
[42, 45, 15, 32, 46, 16],
// 39
[20, 147, 117, 4, 148, 118],
[40, 75, 47, 7, 76, 48],
[43, 54, 24, 22, 55, 25],
[10, 45, 15, 67, 46, 16],
// 40
[19, 148, 118, 6, 149, 119],
[18, 75, 47, 31, 76, 48],
[34, 54, 24, 34, 55, 25],
[20, 45, 15, 61, 46, 16]
];
let qrRSBlock = function(totalCount, dataCount) {
let _this = {};
_this.totalCount = totalCount;
_this.dataCount = dataCount;
return _this;
};
let _this = {};
let getRsBlockTable = function(typeNumber, errorCorrectionLevel) {
switch(errorCorrectionLevel) {
case QRErrorCorrectionLevel.L :
return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
case QRErrorCorrectionLevel.M :
return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
case QRErrorCorrectionLevel.Q :
return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
case QRErrorCorrectionLevel.H :
return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
default :
return undefined;
}
};
_this.getRSBlocks = function(typeNumber, errorCorrectionLevel) {
let rsBlock = getRsBlockTable(typeNumber, errorCorrectionLevel);
if (typeof rsBlock == 'undefined') {
throw 'bad rs block @ typeNumber:' + typeNumber +
'/errorCorrectionLevel:' + errorCorrectionLevel;
}
let length = rsBlock.length / 3;
let list = [];
for (let i = 0; i < length; i += 1) {
let count = rsBlock[i * 3 + 0];
let totalCount = rsBlock[i * 3 + 1];
let dataCount = rsBlock[i * 3 + 2];
for (let j = 0; j < count; j += 1) {
list.push(qrRSBlock(totalCount, dataCount) );
}
}
return list;
};
return _this;
}();
//---------------------------------------------------------------------
// qrBitBuffer
//---------------------------------------------------------------------
let qrBitBuffer = function() {
let _buffer = [];
let _length = 0;
let _this = {};
_this.getBuffer = function() {
return _buffer;
};
_this.getAt = function(index) {
let bufIndex = Math.floor(index / 8);
return ( (_buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1;
};
_this.put = function(num, length) {
for (let i = 0; i < length; i += 1) {
_this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1);
}
};
_this.getLengthInBits = function() {
return _length;
};
_this.putBit = function(bit) {
let bufIndex = Math.floor(_length / 8);
if (_buffer.length <= bufIndex) {
_buffer.push(0);
}
if (bit) {
_buffer[bufIndex] |= (0x80 >>> (_length % 8) );
}
_length += 1;
};
return _this;
};
//---------------------------------------------------------------------
// qrNumber
//---------------------------------------------------------------------
let qrNumber = function(data) {
let _mode = QRMode.MODE_NUMBER;
let _data = data;
let _this = {};
_this.getMode = function() {
return _mode;
};
_this.getLength = function(buffer) {
return _data.length;
};
_this.write = function(buffer) {
let data = _data;
let i = 0;
while (i + 2 < data.length) {
buffer.put(strToNum(data.substring(i, i + 3) ), 10);
i += 3;
}
if (i < data.length) {
if (data.length - i == 1) {
buffer.put(strToNum(data.substring(i, i + 1) ), 4);
} else if (data.length - i == 2) {
buffer.put(strToNum(data.substring(i, i + 2) ), 7);
}
}
};
let strToNum = function(s) {
let num = 0;
for (let i = 0; i < s.length; i += 1) {
num = num * 10 + chatToNum(s.charAt(i) );
}
return num;
};
let chatToNum = function(c) {
if ('0' <= c && c <= '9') {
return c.charCodeAt(0) - '0'.charCodeAt(0);
}
throw 'illegal char :' + c;
};
return _this;
};
//---------------------------------------------------------------------
// qrAlphaNum
//---------------------------------------------------------------------
let qrAlphaNum = function(data) {
let _mode = QRMode.MODE_ALPHA_NUM;
let _data = data;
let _this = {};
_this.getMode = function() {
return _mode;
};
_this.getLength = function(buffer) {
return _data.length;
};
_this.write = function(buffer) {
let s = _data;
let i = 0;
while (i + 1 < s.length) {
buffer.put(
getCode(s.charAt(i) ) * 45 +
getCode(s.charAt(i + 1) ), 11);
i += 2;
}
if (i < s.length) {
buffer.put(getCode(s.charAt(i) ), 6);
}
};
let getCode = function(c) {
if ('0' <= c && c <= '9') {
return c.charCodeAt(0) - '0'.charCodeAt(0);
} else if ('A' <= c && c <= 'Z') {
return c.charCodeAt(0) - 'A'.charCodeAt(0) + 10;
} else {
switch (c) {
case ' ' : return 36;
case '$' : return 37;
case '%' : return 38;
case '*' : return 39;
case '+' : return 40;
case '-' : return 41;
case '.' : return 42;
case '/' : return 43;
case ':' : return 44;
default :
throw 'illegal char :' + c;
}
}
};
return _this;
};
//---------------------------------------------------------------------
// qr8BitByte
//---------------------------------------------------------------------
let qr8BitByte = function(data) {
let _mode = QRMode.MODE_8BIT_BYTE;
let _data = data;
let _bytes = qrcode.stringToBytes(data);
let _this = {};
_this.getMode = function() {
return _mode;
};
_this.getLength = function(buffer) {
return _bytes.length;
};
_this.write = function(buffer) {
for (let i = 0; i < _bytes.length; i += 1) {
buffer.put(_bytes[i], 8);
}
};
return _this;
};
//---------------------------------------------------------------------
// qrKanji
//---------------------------------------------------------------------
let qrKanji = function(data) {
let _mode = QRMode.MODE_KANJI;
let _data = data;
let stringToBytes = qrcode.stringToBytesFuncs['SJIS'];
if (!stringToBytes) {
throw 'sjis not supported.';
}
!function(c, code) {
// self test for sjis support.
let test = stringToBytes(c);
if (test.length != 2 || ( (test[0] << 8) | test[1]) != code) {
throw 'sjis not supported.';
}
}('\u53cb', 0x9746);
let _bytes = stringToBytes(data);
let _this = {};
_this.getMode = function() {
return _mode;
};
_this.getLength = function(buffer) {
return ~~(_bytes.length / 2);
};
_this.write = function(buffer) {
let data = _bytes;
let i = 0;
while (i + 1 < data.length) {
let c = ( (0xff & data[i]) << 8) | (0xff & data[i + 1]);
if (0x8140 <= c && c <= 0x9FFC) {
c -= 0x8140;
} else if (0xE040 <= c && c <= 0xEBBF) {
c -= 0xC140;
} else {
throw 'illegal char at ' + (i + 1) + '/' + c;
}
c = ( (c >>> 8) & 0xff) * 0xC0 + (c & 0xff);
buffer.put(c, 13);
i += 2;
}
if (i < data.length) {
throw 'illegal char at ' + (i + 1);
}
};
return _this;
};
//=====================================================================
// GIF Support etc.
//
//---------------------------------------------------------------------
// byteArrayOutputStream
//---------------------------------------------------------------------
let byteArrayOutputStream = function() {
let _bytes = [];
let _this = {};
_this.writeByte = function(b) {
_bytes.push(b & 0xff);
};
_this.writeShort = function(i) {
_this.writeByte(i);
_this.writeByte(i >>> 8);
};
_this.writeBytes = function(b, off, len) {
off = off || 0;
len = len || b.length;
for (let i = 0; i < len; i += 1) {
_this.writeByte(b[i + off]);
}
};
_this.writeString = function(s) {
for (let i = 0; i < s.length; i += 1) {
_this.writeByte(s.charCodeAt(i) );
}
};
_this.toByteArray = function() {
return _bytes;
};
_this.toString = function() {
let s = '';
s += '[';
for (let i = 0; i < _bytes.length; i += 1) {
if (i > 0) {
s += ',';
}
s += _bytes[i];
}
s += ']';
return s;
};
return _this;
};
//---------------------------------------------------------------------
// base64EncodeOutputStream
//---------------------------------------------------------------------
let base64EncodeOutputStream = function() {
let _buffer = 0;
let _buflen = 0;
let _length = 0;
let _base64 = '';
let _this = {};
let writeEncoded = function(b) {
_base64 += String.fromCharCode(encode(b & 0x3f) );
};
let encode = function(n) {
if (n < 0) {
// error.
} else if (n < 26) {
return 0x41 + n;
} else if (n < 52) {
return 0x61 + (n - 26);
} else if (n < 62) {
return 0x30 + (n - 52);
} else if (n == 62) {
return 0x2b;
} else if (n == 63) {
return 0x2f;
}
throw 'n:' + n;
};
_this.writeByte = function(n) {
_buffer = (_buffer << 8) | (n & 0xff);
_buflen += 8;
_length += 1;
while (_buflen >= 6) {
writeEncoded(_buffer >>> (_buflen - 6) );
_buflen -= 6;
}
};
_this.flush = function() {
if (_buflen > 0) {
writeEncoded(_buffer << (6 - _buflen) );
_buffer = 0;
_buflen = 0;
}
if (_length % 3 != 0) {
// padding
let padlen = 3 - _length % 3;
for (let i = 0; i < padlen; i += 1) {
_base64 += '=';
}
}
};
_this.toString = function() {
return _base64;
};
return _this;
};
//---------------------------------------------------------------------
// base64DecodeInputStream
//---------------------------------------------------------------------
let base64DecodeInputStream = function(str) {
let _str = str;
let _pos = 0;
let _buffer = 0;
let _buflen = 0;
let _this = {};
_this.read = function() {
while (_buflen < 8) {
if (_pos >= _str.length) {
if (_buflen == 0) {
return -1;
}
throw 'unexpected end of file./' + _buflen;
}
let c = _str.charAt(_pos);
_pos += 1;
if (c == '=') {
_buflen = 0;
return -1;
} else if (c.match(/^\s$/) ) {
// ignore if whitespace.
continue;
}
_buffer = (_buffer << 6) | decode(c.charCodeAt(0) );
_buflen += 6;
}
let n = (_buffer >>> (_buflen - 8) ) & 0xff;
_buflen -= 8;
return n;
};
let decode = function(c) {
if (0x41 <= c && c <= 0x5a) {
return c - 0x41;
} else if (0x61 <= c && c <= 0x7a) {
return c - 0x61 + 26;
} else if (0x30 <= c && c <= 0x39) {
return c - 0x30 + 52;
} else if (c == 0x2b) {
return 62;
} else if (c == 0x2f) {
return 63;
} else {
throw 'c:' + c;
}
};
return _this;
};
//---------------------------------------------------------------------
// gifImage (B/W)
//---------------------------------------------------------------------
let gifImage = function(width, height) {
let _width = width;
let _height = height;
let _data = new Array(width * height);
let _this = {};
_this.setPixel = function(x, y, pixel) {
_data[y * _width + x] = pixel;
};
_this.write = function(out) {
//---------------------------------
// GIF Signature
out.writeString('GIF87a');
//---------------------------------
// Screen Descriptor
out.writeShort(_width);
out.writeShort(_height);
out.writeByte(0x80); // 2bit
out.writeByte(0);
out.writeByte(0);
//---------------------------------
// Global Color Map
// black
out.writeByte(0x00);
out.writeByte(0x00);
out.writeByte(0x00);
// white
out.writeByte(0xff);
out.writeByte(0xff);
out.writeByte(0xff);
//---------------------------------
// Image Descriptor
out.writeString(',');
out.writeShort(0);
out.writeShort(0);
out.writeShort(_width);
out.writeShort(_height);
out.writeByte(0);
//---------------------------------
// Local Color Map
//---------------------------------
// Raster Data
let lzwMinCodeSize = 2;
let raster = getLZWRaster(lzwMinCodeSize);
out.writeByte(lzwMinCodeSize);
let offset = 0;
while (raster.length - offset > 255) {
out.writeByte(255);
out.writeBytes(raster, offset, 255);
offset += 255;
}
out.writeByte(raster.length - offset);
out.writeBytes(raster, offset, raster.length - offset);
out.writeByte(0x00);
//---------------------------------
// GIF Terminator
out.writeString(';');
};
let bitOutputStream = function(out) {
let _out = out;
let _bitLength = 0;
let _bitBuffer = 0;
let _this = {};
_this.write = function(data, length) {
if ( (data >>> length) != 0) {
throw 'length over';
}
while (_bitLength + length >= 8) {
_out.writeByte(0xff & ( (data << _bitLength) | _bitBuffer) );
length -= (8 - _bitLength);
data >>>= (8 - _bitLength);
_bitBuffer = 0;
_bitLength = 0;
}
_bitBuffer = (data << _bitLength) | _bitBuffer;
_bitLength = _bitLength + length;
};
_this.flush = function() {
if (_bitLength > 0) {
_out.writeByte(_bitBuffer);
}
};
return _this;
};
let getLZWRaster = function(lzwMinCodeSize) {
let clearCode = 1 << lzwMinCodeSize;
let endCode = (1 << lzwMinCodeSize) + 1;
let bitLength = lzwMinCodeSize + 1;
// Setup LZWTable
let table = lzwTable();
for (let i = 0; i < clearCode; i += 1) {
table.add(String.fromCharCode(i) );
}
table.add(String.fromCharCode(clearCode) );
table.add(String.fromCharCode(endCode) );
let byteOut = byteArrayOutputStream();
let bitOut = bitOutputStream(byteOut);
// clear code
bitOut.write(clearCode, bitLength);
let dataIndex = 0;
let s = String.fromCharCode(_data[dataIndex]);
dataIndex += 1;
while (dataIndex < _data.length) {
let c = String.fromCharCode(_data[dataIndex]);
dataIndex += 1;
if (table.contains(s + c) ) {
s = s + c;
} else {
bitOut.write(table.indexOf(s), bitLength);
if (table.size() < 0xfff) {
if (table.size() == (1 << bitLength) ) {
bitLength += 1;
}
table.add(s + c);
}
s = c;
}
}
bitOut.write(table.indexOf(s), bitLength);
// end code
bitOut.write(endCode, bitLength);
bitOut.flush();
return byteOut.toByteArray();
};
let lzwTable = function() {
let _map = {};
let _size = 0;
let _this = {};
_this.add = function(key) {
if (_this.contains(key) ) {
throw 'dup key:' + key;
}
_map[key] = _size;
_size += 1;
};
_this.size = function() {
return _size;
};
_this.indexOf = function(key) {
return _map[key];
};
_this.contains = function(key) {
return typeof _map[key] != 'undefined';
};
return _this;
};
return _this;
};
let createDataURL = function(width, height, getPixel) {
let gif = gifImage(width, height);
for (let y = 0; y < height; y += 1) {
for (let x = 0; x < width; x += 1) {
gif.setPixel(x, y, getPixel(x, y) );
}
}
let b = byteArrayOutputStream();
gif.write(b);
let base64 = base64EncodeOutputStream();
let bytes = b.toByteArray();
for (let i = 0; i < bytes.length; i += 1) {
base64.writeByte(bytes[i]);
}
base64.flush();
return 'data:image/gif;base64,' + base64;
};
//---------------------------------------------------------------------
// returns qrcode function.
return qrcode;
}();
// multibyte support
!function() {
qrcode.stringToBytesFuncs['UTF-8'] = function(s) {
// http://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array
function toUTF8Array(str) {
let utf8 = [];
for (let i=0; i < str.length; i++) {
let charcode = str.charCodeAt(i);
if (charcode < 0x80) utf8.push(charcode);
else if (charcode < 0x800) {
utf8.push(0xc0 | (charcode >> 6),
0x80 | (charcode & 0x3f));
}
else if (charcode < 0xd800 || charcode >= 0xe000) {
utf8.push(0xe0 | (charcode >> 12),
0x80 | ((charcode>>6) & 0x3f),
0x80 | (charcode & 0x3f));
}
// surrogate pair
else {
i++;
// UTF-16 encodes 0x10000-0x10FFFF by
// subtracting 0x10000 and splitting the
// 20 bits of 0x0-0xFFFFF into two halves
charcode = 0x10000 + (((charcode & 0x3ff)<<10)
| (str.charCodeAt(i) & 0x3ff));
utf8.push(0xf0 | (charcode >>18),
0x80 | ((charcode>>12) & 0x3f),
0x80 | ((charcode>>6) & 0x3f),
0x80 | (charcode & 0x3f));
}
}
return utf8;
}
return toUTF8Array(s);
};
}();
export {
qrcode
}
// 不同的翻译文件都放在对应的模块里,可以在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