init project
|
|
@ -0,0 +1,26 @@
|
|||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
/dist
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
package-lock.json
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
# aigc
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
||||
|
||||
## Customize configuration
|
||||
|
||||
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
||||
|
||||
## Project Setup
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Lint with [ESLint](https://eslint.org/)
|
||||
|
||||
```sh
|
||||
npm run lint
|
||||
```
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- 临时写死暗黑模式 -->
|
||||
<html lang="zh-cn" data-theme="dark" class="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>aigc</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"name": "aigc",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore",
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@traptitech/markdown-it-katex": "^3.6.0",
|
||||
"axios": "^1.4.0",
|
||||
"echarts": "^5.4.3",
|
||||
"highlight.js": "^11.8.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"markdown-it": "^13.0.1",
|
||||
"markdown-it-link-attributes": "^4.0.1",
|
||||
"pinia": "^2.1.3",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"swiper": "^10.1.0",
|
||||
"vant": "^4.6.4",
|
||||
"vue": "^3.3.4",
|
||||
"vue-router": "^4.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rushstack/eslint-patch": "^1.2.0",
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"@vitejs/plugin-vue-jsx": "^3.0.1",
|
||||
"@vue/eslint-config-prettier": "^7.1.0",
|
||||
"eslint": "^8.39.0",
|
||||
"eslint-plugin-vue": "^9.11.0",
|
||||
"prettier": "^2.8.8",
|
||||
"sass": "^1.63.6",
|
||||
"sass-loader": "^13.3.2",
|
||||
"unplugin-vue-components": "^0.25.1",
|
||||
"vite": "^4.3.9",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vite-plugin-windicss": "^1.9.0",
|
||||
"windicss": "^3.5.6"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
|
|
@ -0,0 +1,25 @@
|
|||
<script setup>
|
||||
import { RouterView } from 'vue-router'
|
||||
import { onMounted } from 'vue'
|
||||
|
||||
onMounted(() => {
|
||||
getRem(750, 16)
|
||||
window.onload = function () {
|
||||
getRem(750, 16)
|
||||
}
|
||||
window.onresize = function () {
|
||||
getRem(750, 16)
|
||||
}
|
||||
})
|
||||
const getRem = (pwidth, prem) => {
|
||||
let html = document.documentElement
|
||||
let oWidth = window.outerWidth ? window.outerWidth : screen.width
|
||||
html.style.fontSize = (oWidth / pwidth) * prem + 'px'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RouterView />
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
/* color palette from <https://github.com/vuejs/theme> */
|
||||
:root {
|
||||
--vt-c-white: #ffffff;
|
||||
--vt-c-white-soft: #f8f8f8;
|
||||
--vt-c-white-mute: #f2f2f2;
|
||||
|
||||
--vt-c-black: #181818;
|
||||
--vt-c-black-soft: #222222;
|
||||
--vt-c-black-mute: #282828;
|
||||
|
||||
--vt-c-indigo: #2c3e50;
|
||||
|
||||
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
||||
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
||||
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
||||
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
||||
|
||||
--vt-c-text-light-1: var(--vt-c-white);
|
||||
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
||||
--vt-c-text-dark-1: var(--vt-c-white);
|
||||
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
||||
}
|
||||
|
||||
/* semantic color variables for this project */
|
||||
:root {
|
||||
--color-background: var(--vt-c-black);
|
||||
--color-background-soft: var(--vt-c-black-soft);
|
||||
--color-background-mute: var(--vt-c-black-mute);
|
||||
|
||||
--color-border: var(--vt-c-divider-light-2);
|
||||
--color-border-hover: var(--vt-c-divider-light-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-light-1);
|
||||
--color-text: var(--vt-c-text-light-1);
|
||||
|
||||
--section-gap: 160px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--color-background: var(--vt-c-black);
|
||||
--color-background-soft: var(--vt-c-black-soft);
|
||||
--color-background-mute: var(--vt-c-black-mute);
|
||||
|
||||
--color-border: var(--vt-c-divider-dark-2);
|
||||
--color-border-hover: var(--vt-c-divider-dark-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-dark-1);
|
||||
--color-text: var(--vt-c-text-dark-2);
|
||||
}
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
height: 100vh;
|
||||
/* min-height: 100vh; */
|
||||
color: var(--color-text);
|
||||
background: var(--color-background);
|
||||
transition: color 0.5s, background-color 0.5s;
|
||||
line-height: 1.6;
|
||||
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
|
||||
Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
/* fade-slide */
|
||||
.fade-slide-leave-active,
|
||||
.fade-slide-enter-active {
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.fade-slide-enter-from {
|
||||
transform: translateX(-30px);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.fade-slide-leave-to {
|
||||
transform: translateX(30px);
|
||||
opacity: 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
html.dark {
|
||||
pre code.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 1em
|
||||
}
|
||||
|
||||
code.hljs {
|
||||
padding: 3px 5px
|
||||
}
|
||||
|
||||
.hljs {
|
||||
color: #abb2bf;
|
||||
background: #282c34
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-operator,
|
||||
.hljs-pattern-match {
|
||||
color: #f92672
|
||||
}
|
||||
|
||||
.hljs-function,
|
||||
.hljs-pattern-match .hljs-constructor {
|
||||
color: #61aeee
|
||||
}
|
||||
|
||||
.hljs-function .hljs-params {
|
||||
color: #a6e22e
|
||||
}
|
||||
|
||||
.hljs-function .hljs-params .hljs-typing {
|
||||
color: #fd971f
|
||||
}
|
||||
|
||||
.hljs-module-access .hljs-module {
|
||||
color: #7e57c2
|
||||
}
|
||||
|
||||
.hljs-constructor {
|
||||
color: #e2b93d
|
||||
}
|
||||
|
||||
.hljs-constructor .hljs-string {
|
||||
color: #9ccc65
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #b18eb1;
|
||||
font-style: italic
|
||||
}
|
||||
|
||||
.hljs-doctag,
|
||||
.hljs-formula {
|
||||
color: #c678dd
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
.hljs-name,
|
||||
.hljs-section,
|
||||
.hljs-selector-tag,
|
||||
.hljs-subst {
|
||||
color: #e06c75
|
||||
}
|
||||
|
||||
.hljs-literal {
|
||||
color: #56b6c2
|
||||
}
|
||||
|
||||
.hljs-addition,
|
||||
.hljs-attribute,
|
||||
.hljs-meta .hljs-string,
|
||||
.hljs-regexp,
|
||||
.hljs-string {
|
||||
color: #98c379
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-class .hljs-title,
|
||||
.hljs-title.class_ {
|
||||
color: #e6c07b
|
||||
}
|
||||
|
||||
.hljs-attr,
|
||||
.hljs-number,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-template-variable,
|
||||
.hljs-type,
|
||||
.hljs-variable {
|
||||
color: #d19a66
|
||||
}
|
||||
|
||||
.hljs-bullet,
|
||||
.hljs-link,
|
||||
.hljs-meta,
|
||||
.hljs-selector-id,
|
||||
.hljs-symbol,
|
||||
.hljs-title {
|
||||
color: #61aeee
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: 700
|
||||
}
|
||||
|
||||
.hljs-link {
|
||||
text-decoration: underline
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
pre code.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 1em
|
||||
}
|
||||
|
||||
code.hljs {
|
||||
padding: 3px 5px;
|
||||
&::-webkit-scrollbar {
|
||||
height: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.hljs {
|
||||
color: #383a42;
|
||||
background: #fafafa
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #a0a1a7;
|
||||
font-style: italic
|
||||
}
|
||||
|
||||
.hljs-doctag,
|
||||
.hljs-formula,
|
||||
.hljs-keyword {
|
||||
color: #a626a4
|
||||
}
|
||||
|
||||
.hljs-deletion,
|
||||
.hljs-name,
|
||||
.hljs-section,
|
||||
.hljs-selector-tag,
|
||||
.hljs-subst {
|
||||
color: #e45649
|
||||
}
|
||||
|
||||
.hljs-literal {
|
||||
color: #0184bb
|
||||
}
|
||||
|
||||
.hljs-addition,
|
||||
.hljs-attribute,
|
||||
.hljs-meta .hljs-string,
|
||||
.hljs-regexp,
|
||||
.hljs-string {
|
||||
color: #50a14f
|
||||
}
|
||||
|
||||
.hljs-attr,
|
||||
.hljs-number,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-template-variable,
|
||||
.hljs-type,
|
||||
.hljs-variable {
|
||||
color: #986801
|
||||
}
|
||||
|
||||
.hljs-bullet,
|
||||
.hljs-link,
|
||||
.hljs-meta,
|
||||
.hljs-selector-id,
|
||||
.hljs-symbol,
|
||||
.hljs-title {
|
||||
color: #4078f2
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-class .hljs-title,
|
||||
.hljs-title.class_ {
|
||||
color: #c18401
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: 700
|
||||
}
|
||||
|
||||
.hljs-link {
|
||||
text-decoration: underline
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
|
||||
|
After Width: | Height: | Size: 276 B |
|
|
@ -0,0 +1,66 @@
|
|||
@import './base.css';
|
||||
@import './highlight.scss';
|
||||
@import './github-markdown.scss';
|
||||
|
||||
html,
|
||||
body {
|
||||
overflow: visible;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
#app {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: #0000000d;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 2px;
|
||||
background-color: #9093994d;
|
||||
box-shadow: inset 0 0 6px #0003;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background-color: #b6b7b9;
|
||||
}
|
||||
|
||||
/* #app {
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
a,
|
||||
.green {
|
||||
text-decoration: none;
|
||||
color: hsla(160, 100%, 37%, 1);
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
a:hover {
|
||||
background-color: hsla(160, 100%, 37%, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
body {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
#app {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
} */
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<div class="h-full relative">
|
||||
<div class="absolute right-15 top-14">
|
||||
<div class="flex items-center cursor-pointer text-white hover:opacity-70" @click="$emit('onClick')">
|
||||
<svg-icon class=" text-3xl" name="back"></svg-icon>
|
||||
<div class="text-lg ml-2">{{ title }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
icon: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
<template>
|
||||
<Scrollbar ref="scrollbarRef" class="scroll-container" v-bind="$attrs">
|
||||
<slot></slot>
|
||||
</Scrollbar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, ref, unref, nextTick } from 'vue'
|
||||
import Scrollbar from '@/components/Scrollbar/index.vue'
|
||||
import { useScrollTo } from './useScrollTo.js'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ScrollContainer',
|
||||
components: { Scrollbar },
|
||||
setup() {
|
||||
const scrollbarRef = ref(null)
|
||||
|
||||
/**
|
||||
* Scroll to the specified position
|
||||
*/
|
||||
function scrollTo(to, duration = 500) {
|
||||
const scrollbar = unref(scrollbarRef)
|
||||
if (!scrollbar) {
|
||||
return
|
||||
}
|
||||
nextTick(() => {
|
||||
const wrap = unref(scrollbar.wrap)
|
||||
if (!wrap) {
|
||||
return
|
||||
}
|
||||
const { start } = useScrollTo({
|
||||
el: wrap,
|
||||
to,
|
||||
duration,
|
||||
})
|
||||
start()
|
||||
})
|
||||
}
|
||||
|
||||
function getScrollWrap() {
|
||||
const scrollbar = unref(scrollbarRef)
|
||||
if (!scrollbar) {
|
||||
return null
|
||||
}
|
||||
return scrollbar.wrap
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll to the bottom
|
||||
*/
|
||||
function scrollBottom() {
|
||||
const scrollbar = unref(scrollbarRef)
|
||||
if (!scrollbar) {
|
||||
return
|
||||
}
|
||||
nextTick(() => {
|
||||
const wrap = unref(scrollbar.wrap)
|
||||
if (!wrap) {
|
||||
return
|
||||
}
|
||||
const scrollHeight = wrap.scrollHeight
|
||||
const { start } = useScrollTo({
|
||||
el: wrap,
|
||||
to: scrollHeight,
|
||||
})
|
||||
start()
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
scrollbarRef,
|
||||
scrollTo,
|
||||
scrollBottom,
|
||||
getScrollWrap,
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.scroll-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.scrollbar__wrap {
|
||||
margin-bottom: 18px !important;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.scrollbar__view {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
import { isFunction, isUnDef } from '@/utils/is.js'
|
||||
import { ref, unref } from 'vue'
|
||||
|
||||
|
||||
|
||||
const easeInOutQuad = (t, b, c, d) => {
|
||||
t /= d / 2
|
||||
if (t < 1) {
|
||||
return (c / 2) * t * t + b
|
||||
}
|
||||
t--
|
||||
return (-c / 2) * (t * (t - 2) - 1) + b
|
||||
}
|
||||
const move = (el, amount) => {
|
||||
el.scrollTop = amount
|
||||
}
|
||||
|
||||
const position = (el) => {
|
||||
return el.scrollTop
|
||||
}
|
||||
export function useScrollTo({ el, to, duration = 500, callback }) {
|
||||
const isActiveRef = ref(false)
|
||||
const start = position(el)
|
||||
const change = to - start
|
||||
const increment = 20
|
||||
let currentTime = 0
|
||||
duration = isUnDef(duration) ? 500 : duration
|
||||
|
||||
const animateScroll = function () {
|
||||
if (!unref(isActiveRef)) {
|
||||
return
|
||||
}
|
||||
currentTime += increment
|
||||
const val = easeInOutQuad(currentTime, start, change, duration)
|
||||
move(el, val)
|
||||
if (currentTime < duration && unref(isActiveRef)) {
|
||||
requestAnimationFrame(animateScroll)
|
||||
} else {
|
||||
if (callback && isFunction(callback)) {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
}
|
||||
const run = () => {
|
||||
isActiveRef.value = true
|
||||
animateScroll()
|
||||
}
|
||||
|
||||
const stop = () => {
|
||||
isActiveRef.value = false
|
||||
}
|
||||
|
||||
return { start: run, stop }
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
import {
|
||||
defineComponent,
|
||||
h,
|
||||
computed,
|
||||
ref,
|
||||
getCurrentInstance,
|
||||
onUnmounted,
|
||||
inject,
|
||||
} from 'vue';
|
||||
import { on, off } from '@/utils/domUtils';
|
||||
|
||||
import { renderThumbStyle, BAR_MAP } from './util';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Bar',
|
||||
|
||||
props: {
|
||||
vertical: Boolean,
|
||||
size: String,
|
||||
move: Number,
|
||||
},
|
||||
|
||||
setup(props) {
|
||||
const instance = getCurrentInstance();
|
||||
const thumb = ref();
|
||||
const wrap = inject('scroll-bar-wrap', {}) ;
|
||||
const bar = computed(() => {
|
||||
return BAR_MAP[props.vertical ? 'vertical' : 'horizontal'];
|
||||
});
|
||||
const barStore = ref({});
|
||||
const cursorDown = ref();
|
||||
const clickThumbHandler = (e) => {
|
||||
// prevent click event of right button
|
||||
if (e.ctrlKey || e.button === 2) {
|
||||
return;
|
||||
}
|
||||
window.getSelection()?.removeAllRanges();
|
||||
startDrag(e);
|
||||
barStore.value[bar.value.axis] =
|
||||
e.currentTarget[bar.value.offset] -
|
||||
(e[bar.value.client] - e.currentTarget.getBoundingClientRect()[bar.value.direction]);
|
||||
};
|
||||
|
||||
const clickTrackHandler = (e) => {
|
||||
const offset = Math.abs(
|
||||
e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client],
|
||||
);
|
||||
const thumbHalf = thumb.value[bar.value.offset] / 2;
|
||||
const thumbPositionPercentage =
|
||||
((offset - thumbHalf) * 100) / instance?.vnode.el?.[bar.value.offset];
|
||||
|
||||
wrap.value[bar.value.scroll] =
|
||||
(thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
|
||||
};
|
||||
const startDrag = (e) => {
|
||||
e.stopImmediatePropagation();
|
||||
cursorDown.value = true;
|
||||
on(document, 'mousemove', mouseMoveDocumentHandler);
|
||||
on(document, 'mouseup', mouseUpDocumentHandler);
|
||||
document.onselectstart = () => false;
|
||||
};
|
||||
|
||||
const mouseMoveDocumentHandler = (e) => {
|
||||
if (cursorDown.value === false) return;
|
||||
const prevPage = barStore.value[bar.value.axis];
|
||||
|
||||
if (!prevPage) return;
|
||||
|
||||
const offset =
|
||||
(instance?.vnode.el?.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) *
|
||||
-1;
|
||||
const thumbClickPosition = thumb.value[bar.value.offset] - prevPage;
|
||||
const thumbPositionPercentage =
|
||||
((offset - thumbClickPosition) * 100) / instance?.vnode.el?.[bar.value.offset];
|
||||
wrap.value[bar.value.scroll] =
|
||||
(thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
|
||||
};
|
||||
|
||||
function mouseUpDocumentHandler() {
|
||||
cursorDown.value = false;
|
||||
barStore.value[bar.value.axis] = 0;
|
||||
off(document, 'mousemove', mouseMoveDocumentHandler);
|
||||
document.onselectstart = null;
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
off(document, 'mouseup', mouseUpDocumentHandler);
|
||||
});
|
||||
|
||||
return () =>
|
||||
h(
|
||||
'div',
|
||||
{
|
||||
class: ['scrollbar__bar', 'is-' + bar.value.key],
|
||||
onMousedown: clickTrackHandler,
|
||||
},
|
||||
h('div', {
|
||||
ref: thumb,
|
||||
class: 'scrollbar__thumb',
|
||||
onMousedown: clickThumbHandler,
|
||||
style: renderThumbStyle({
|
||||
size: props.size,
|
||||
move: props.move,
|
||||
bar: bar.value,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
<template>
|
||||
<div class="scrollbar">
|
||||
<div
|
||||
ref="wrap"
|
||||
:class="[
|
||||
wrapClass,
|
||||
'scrollbar__wrap',
|
||||
native ? '' : 'scrollbar__wrap--hidden-default',
|
||||
]"
|
||||
:style="style"
|
||||
@scroll="handleScroll"
|
||||
>
|
||||
<component
|
||||
:is="tag"
|
||||
ref="resize"
|
||||
:class="['scrollbar__view', viewClass]"
|
||||
:style="viewStyle"
|
||||
>
|
||||
<slot></slot>
|
||||
</component>
|
||||
</div>
|
||||
<template v-if="!native">
|
||||
<bar :move="moveX" :size="sizeWidth" />
|
||||
<bar vertical :move="moveY" :size="sizeHeight" />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { addResizeListener, removeResizeListener } from '@/utils/event'
|
||||
import Bar from './bar';
|
||||
import {
|
||||
defineComponent,
|
||||
ref,
|
||||
onMounted,
|
||||
onBeforeUnmount,
|
||||
nextTick,
|
||||
provide,
|
||||
computed,
|
||||
unref,
|
||||
} from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Scrollbar',
|
||||
components: { Bar },
|
||||
props: {
|
||||
native: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
wrapStyle: {
|
||||
type: [String, Array],
|
||||
default: '',
|
||||
},
|
||||
wrapClass: {
|
||||
type: [String, Array],
|
||||
default: '',
|
||||
},
|
||||
viewClass: {
|
||||
type: [String, Array],
|
||||
default: '',
|
||||
},
|
||||
viewStyle: {
|
||||
type: [String, Array],
|
||||
default: '',
|
||||
},
|
||||
noresize: Boolean, // 如果 container 尺寸不会发生变化,最好设置它可以优化性能
|
||||
tag: {
|
||||
type: String,
|
||||
default: 'div',
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const sizeWidth = ref('0')
|
||||
const sizeHeight = ref('0')
|
||||
const moveX = ref(0)
|
||||
const moveY = ref(0)
|
||||
const wrap = ref()
|
||||
const resize = ref()
|
||||
|
||||
provide('scroll-bar-wrap', wrap);
|
||||
|
||||
const style = computed(() => {
|
||||
if (Array.isArray(props.wrapStyle)) {
|
||||
return toObject(props.wrapStyle)
|
||||
}
|
||||
return props.wrapStyle
|
||||
})
|
||||
|
||||
const handleScroll = () => {
|
||||
if (!props.native) {
|
||||
moveY.value = (unref(wrap).scrollTop * 100) / unref(wrap).clientHeight
|
||||
moveX.value = (unref(wrap).scrollLeft * 100) / unref(wrap).clientWidth
|
||||
}
|
||||
}
|
||||
|
||||
const update = () => {
|
||||
if (!unref(wrap)) return
|
||||
|
||||
const heightPercentage =
|
||||
(unref(wrap).clientHeight * 100) / unref(wrap).scrollHeight
|
||||
const widthPercentage =
|
||||
(unref(wrap).clientWidth * 100) / unref(wrap).scrollWidth
|
||||
|
||||
sizeHeight.value = heightPercentage < 100 ? heightPercentage + '%' : ''
|
||||
sizeWidth.value = widthPercentage < 100 ? widthPercentage + '%' : ''
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (props.native) return
|
||||
nextTick(update)
|
||||
if (!props.noresize) {
|
||||
addResizeListener(unref(resize), update)
|
||||
addResizeListener(unref(wrap), update)
|
||||
addEventListener('resize', update)
|
||||
}
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (props.native) return
|
||||
if (!props.noresize) {
|
||||
removeResizeListener(unref(resize), update)
|
||||
removeResizeListener(unref(wrap), update)
|
||||
removeEventListener('resize', update)
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
moveX,
|
||||
moveY,
|
||||
sizeWidth,
|
||||
sizeHeight,
|
||||
style,
|
||||
wrap,
|
||||
resize,
|
||||
update,
|
||||
handleScroll,
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.scrollbar {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
&__wrap {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
|
||||
&--hidden-default {
|
||||
scrollbar-width: none;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
width: 0;
|
||||
height: 0;
|
||||
opacity: 0%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__thumb {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
cursor: pointer;
|
||||
background-color: rgb(144 147 153 / 30%);
|
||||
border-radius: inherit;
|
||||
transition: 0.3s background-color;
|
||||
|
||||
&:hover {
|
||||
background-color: rgb(144 147 153 / 50%);
|
||||
}
|
||||
}
|
||||
|
||||
&__bar {
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
bottom: 2px;
|
||||
z-index: 1;
|
||||
border-radius: 4px;
|
||||
opacity: 0%;
|
||||
transition: opacity 80ms ease;
|
||||
|
||||
&.is-vertical {
|
||||
top: 2px;
|
||||
width: 6px;
|
||||
|
||||
& > div {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-horizontal {
|
||||
left: 2px;
|
||||
height: 6px;
|
||||
|
||||
& > div {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scrollbar:active > .scrollbar__bar,
|
||||
.scrollbar:focus > .scrollbar__bar,
|
||||
.scrollbar:hover > .scrollbar__bar {
|
||||
opacity: 100%;
|
||||
transition: opacity 340ms ease-out;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
export const BAR_MAP = {
|
||||
vertical: {
|
||||
offset: 'offsetHeight',
|
||||
scroll: 'scrollTop',
|
||||
scrollSize: 'scrollHeight',
|
||||
size: 'height',
|
||||
key: 'vertical',
|
||||
axis: 'Y',
|
||||
client: 'clientY',
|
||||
direction: 'top',
|
||||
},
|
||||
horizontal: {
|
||||
offset: 'offsetWidth',
|
||||
scroll: 'scrollLeft',
|
||||
scrollSize: 'scrollWidth',
|
||||
size: 'width',
|
||||
key: 'horizontal',
|
||||
axis: 'X',
|
||||
client: 'clientX',
|
||||
direction: 'left',
|
||||
},
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
export function renderThumbStyle({ move, size, bar }) {
|
||||
const style = {};
|
||||
const translate = `translate${bar.axis}(${move}%)`;
|
||||
|
||||
style[bar.size] = size;
|
||||
style.transform = translate;
|
||||
style.msTransform = translate;
|
||||
style.webkitTransform = translate;
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
function extend(to, _from) {
|
||||
return Object.assign(to, _from);
|
||||
}
|
||||
|
||||
export function toObject(arr) {
|
||||
const res = {};
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (arr[i]) {
|
||||
extend(res, arr[i]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<template>
|
||||
<svg
|
||||
:class="[prefixCls, $attrs.class, spin && 'svg-icon-spin']"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<use :xlink:href="symbolId" />
|
||||
</svg>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent, computed } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SvgIcon',
|
||||
props: {
|
||||
prefix: {
|
||||
type: String,
|
||||
default: 'icon',
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
spin: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const symbolId = computed(() => `#${props.prefix}-${props.name}`)
|
||||
const prefixCls = computed(() => `svg-icon`)
|
||||
return { symbolId, prefixCls }
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.svg-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
fill: currentcolor;
|
||||
vertical-align: -0.15em;
|
||||
}
|
||||
|
||||
.svg-icon-spin {
|
||||
animation: loadingCircle 1s infinite linear;
|
||||
}
|
||||
|
||||
@keyframes loadingCircle {
|
||||
0% {
|
||||
transform: rotate(0);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
const hostAPI = 'http://test-admin.haituaigc.com';
|
||||
|
||||
export default hostAPI;
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue'// svg component
|
||||
|
||||
export function registerSvgIcon(app) {
|
||||
app.component(SvgIcon.name, SvgIcon);
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1690348382971" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2433" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M761.6 489.6l-432-435.2c-9.6-9.6-25.6-9.6-35.2 0-9.6 9.6-9.6 25.6 0 35.2l416 416-416 425.6c-9.6 9.6-9.6 25.6 0 35.2s25.6 9.6 35.2 0l432-441.6C771.2 515.2 771.2 499.2 761.6 489.6z" p-id="2434"></path></svg>
|
||||
|
After Width: | Height: | Size: 538 B |
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg t="1690529853834" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="2284" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="128" height="128">
|
||||
<path
|
||||
d="M675.328 117.717333A425.429333 425.429333 0 0 0 512 85.333333C276.352 85.333333 85.333333 276.352 85.333333 512s191.018667 426.666667 426.666667 426.666667 426.666667-191.018667 426.666667-426.666667c0-56.746667-11.093333-112-32.384-163.328a21.333333 21.333333 0 0 0-39.402667 16.341333A382.762667 382.762667 0 0 1 896 512c0 212.074667-171.925333 384-384 384S128 724.074667 128 512 299.925333 128 512 128c51.114667 0 100.8 9.984 146.986667 29.12a21.333333 21.333333 0 0 0 16.341333-39.402667z m-324.693333 373.013334l174.464-174.485334a21.141333 21.141333 0 0 0-0.192-29.973333 21.141333 21.141333 0 0 0-29.973334-0.192l-208.256 208.256a20.821333 20.821333 0 0 0-6.122666 14.976c0.042667 5.418667 2.133333 10.837333 6.314666 14.997333l211.178667 211.2a21.141333 21.141333 0 0 0 29.973333 0.213334 21.141333 21.141333 0 0 0-0.213333-29.973334l-172.629333-172.629333 374.997333 2.602667a20.693333 20.693333 0 0 0 21.034667-21.034667 21.482667 21.482667 0 0 0-21.333334-21.333333l-379.242666-2.624z"
|
||||
fill="currentColor" p-id="2285"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg t="1690269116675" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="2291" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="128" height="128">
|
||||
<path
|
||||
d="M507.168 473.232L716.48 263.936a16 16 0 0 1 22.624 0l11.312 11.312a16 16 0 0 1 0 22.624L541.12 507.168 750.4 716.48a16 16 0 0 1 0 22.624l-11.312 11.312a16 16 0 0 1-22.624 0L507.168 541.12 297.872 750.4a16 16 0 0 1-22.624 0l-11.312-11.312a16 16 0 0 1 0-22.624l209.296-209.312-209.296-209.296a16 16 0 0 1 0-22.624l11.312-11.312a16 16 0 0 1 22.624 0l209.296 209.296z"
|
||||
fill="currentColor" p-id="2292"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 761 B |
|
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1689839410470" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8379" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M518.3 459c-3.2-4.1-9.4-4.1-12.6 0l-112 141.7c-4.1 5.2-0.4 12.9 6.3 12.9h73.9V856c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V613.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 459z" p-id="8380"></path><path d="M811.4 366.7C765.6 245.9 648.9 160 512.2 160S258.8 245.8 213 366.6C127.3 389.1 64 467.2 64 560c0 110.5 89.5 200 199.9 200H304c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8h-40.1c-33.7 0-65.4-13.4-89-37.7-23.5-24.2-36-56.8-34.9-90.6 0.9-26.4 9.9-51.2 26.2-72.1 16.7-21.3 40.1-36.8 66.1-43.7l37.9-9.9 13.9-36.6c8.6-22.8 20.6-44.1 35.7-63.4 14.9-19.2 32.6-35.9 52.4-49.9 41.1-28.9 89.5-44.2 140-44.2s98.9 15.3 140 44.2c19.9 14 37.5 30.8 52.4 49.9 15.1 19.3 27.1 40.7 35.7 63.4l13.8 36.5 37.8 10C846.1 454.5 884 503.8 884 560c0 33.1-12.9 64.3-36.3 87.7-23.4 23.4-54.5 36.3-87.6 36.3H720c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h40.1C870.5 760 960 670.5 960 560c0-92.7-63.1-170.7-148.6-193.3z" p-id="8381"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg t="1689839520218" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="9374" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="128" height="128">
|
||||
<path
|
||||
d="M768 384c-19.2 0-32 12.8-32 32l0 377.6c0 25.6-19.2 38.4-38.4 38.4L326.4 832c-25.6 0-38.4-19.2-38.4-38.4L288 416C288 396.8 275.2 384 256 384S224 396.8 224 416l0 377.6c0 57.6 44.8 102.4 102.4 102.4l364.8 0c57.6 0 102.4-44.8 102.4-102.4L793.6 416C800 396.8 787.2 384 768 384z"
|
||||
fill="currentColor" p-id="9375"></path>
|
||||
<path
|
||||
d="M460.8 736l0-320C460.8 396.8 448 384 435.2 384S396.8 396.8 396.8 416l0 320c0 19.2 12.8 32 32 32S460.8 755.2 460.8 736z"
|
||||
fill="currentColor" p-id="9376"></path>
|
||||
<path
|
||||
d="M627.2 736l0-320C627.2 396.8 608 384 588.8 384S563.2 396.8 563.2 416l0 320C563.2 755.2 576 768 588.8 768S627.2 755.2 627.2 736z"
|
||||
fill="currentColor" p-id="9377"></path>
|
||||
<path
|
||||
d="M832 256l-160 0L672 211.2C672 166.4 633.6 128 588.8 128L435.2 128C390.4 128 352 166.4 352 211.2L352 256 192 256C172.8 256 160 268.8 160 288S172.8 320 192 320l640 0c19.2 0 32-12.8 32-32S851.2 256 832 256zM416 211.2C416 198.4 422.4 192 435.2 192l153.6 0c12.8 0 19.2 6.4 19.2 19.2L608 256l-192 0L416 211.2z"
|
||||
fill="currentColor" p-id="9378"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg t="1689839944498" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="13991" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="128" height="128">
|
||||
<path
|
||||
d="M957.44 936.96l-199.68-204.8h81.92c30.72 0 51.2-20.48 51.2-51.2s-20.48-51.2-51.2-51.2h-204.8c-5.12 0-15.36 0-20.48 5.12-5.12 0-10.24 5.12-15.36 10.24-5.12 5.12-10.24 10.24-10.24 15.36 0 5.12-5.12 10.24-5.12 20.48v204.8c0 30.72 20.48 51.2 51.2 51.2s51.2-20.48 51.2-51.2v-81.92l204.8 199.68c20.48 20.48 51.2 20.48 71.68 0 15.36-15.36 15.36-46.08-5.12-66.56z"
|
||||
fill="currentColor" p-id="13992"></path>
|
||||
<path
|
||||
d="M445.44 1024H194.56C112.64 1024 51.2 957.44 51.2 880.64V143.36C51.2 66.56 112.64 0 194.56 0h476.16L972.8 276.48v215.04c0 30.72-20.48 51.2-51.2 51.2s-51.2-20.48-51.2-51.2V322.56L629.76 102.4H194.56c-25.6 0-40.96 20.48-40.96 40.96v737.28c0 20.48 15.36 40.96 40.96 40.96h250.88c30.72 0 51.2 20.48 51.2 51.2s-25.6 51.2-51.2 51.2z"
|
||||
fill="currentColor" p-id="13993"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg t="1690270189218" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="3276" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="128" height="128">
|
||||
<path
|
||||
d="M512 977.454545C255.301818 977.454545 46.545455 768.651636 46.545455 512S255.301818 46.545455 512 46.545455s465.454545 208.802909 465.454545 465.454545-208.802909 465.454545-465.454545 465.454545z m0-861.090909c-218.158545 0-395.636364 177.477818-395.636364 395.636364 0 218.158545 177.477818 395.636364 395.636364 395.636364s395.636364-177.477818 395.636364-395.636364c0-218.158545-177.477818-395.636364-395.636364-395.636364zM414.999273 673.000727V351.045818a34.909091 34.909091 0 0 0-69.818182 0v321.954909a34.909091 34.909091 0 0 0 69.818182 0z m263.773091 0V351.045818a34.909091 34.909091 0 0 0-69.818182 0v321.954909a34.909091 34.909091 0 0 0 69.818182 0z"
|
||||
fill="currentColor" p-id="3277"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
|
|
@ -0,0 +1 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1689668597068" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2301" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M960 416V192l-73.056 73.056a447.712 447.712 0 0 0-373.6-201.088C265.92 63.968 65.312 264.544 65.312 512S265.92 960.032 513.344 960.032a448.064 448.064 0 0 0 415.232-279.488 38.368 38.368 0 1 0-71.136-28.896 371.36 371.36 0 0 1-344.096 231.584C308.32 883.232 142.112 717.024 142.112 512S308.32 140.768 513.344 140.768c132.448 0 251.936 70.08 318.016 179.84L736 416h224z" p-id="2302"></path></svg>
|
||||
|
After Width: | Height: | Size: 728 B |
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg t="1690270224102" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="7524" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="128" height="128">
|
||||
<path
|
||||
d="M553.38 726.62L372.69 545.94c-18.72-18.72-18.72-49.16 0-67.88l180.69-180.69c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25L429.25 512l169.38 169.38c12.5 12.5 12.5 32.75 0 45.25-6.25 6.25-14.44 9.38-22.62 9.38s-16.39-3.13-22.63-9.39zM417.62 523.31h0.31-0.31z"
|
||||
fill="currentColor" p-id="7525"></path>
|
||||
<path
|
||||
d="M512 128c211.74 0 384 172.26 384 384S723.74 896 512 896 128 723.74 128 512s172.26-384 384-384m0-64C264.58 64 64 264.58 64 512s200.58 448 448 448 448-200.58 448-448S759.42 64 512 64z"
|
||||
fill="currentColor" p-id="7526"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 898 B |
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg t="1690272110347" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="8690" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="128" height="128">
|
||||
<path
|
||||
d="M950.186667 164.693333a42.666667 42.666667 0 0 0-42.666667-14.293333l-832 192a42.666667 42.666667 0 0 0-21.333333 69.76l134.186666 153.386667-58.026666 213.333333a42.666667 42.666667 0 0 0 66.56 45.653333l405.333333-298.666666a42.666667 42.666667 0 1 0-50.773333-68.693334L244.053333 682.666667l31.786667-116.266667a42.666667 42.666667 0 0 0-9.173333-39.466667l-102.186667-117.333333 680.106667-157.013333L621.226667 768l-85.333334-56.96a42.666667 42.666667 0 1 0-47.36 70.826667l128 85.333333A41.386667 41.386667 0 0 0 640 874.666667a47.786667 47.786667 0 0 0 12.16-1.706667 42.666667 42.666667 0 0 0 26.88-24.106667l277.333333-640a42.666667 42.666667 0 0 0-6.186666-44.16z"
|
||||
fill="currentColor" p-id="8691"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg t="1689837870587" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="2303" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="128" height="128">
|
||||
<path
|
||||
d="M686.480358 119.560026c0-32.377408 26.325575-58.644655 58.644655-58.644655 32.386618 0 58.645678 26.420743 58.645678 58.644655l0 781.930779c0 32.376385-26.325575 58.644655-58.645678 58.644655-32.385595 0-58.644655-26.419719-58.644655-58.644655L686.480358 119.560026zM217.321072 119.560026c0-32.377408 26.325575-58.644655 58.645678-58.644655 32.385595 0 58.644655 26.420743 58.644655 58.644655l0 781.930779c0 32.376385-26.325575 58.644655-58.644655 58.644655-32.385595 0-58.645678-26.419719-58.645678-58.644655L217.321072 119.560026z"
|
||||
fill="#currentColor" p-id="2304"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 931 B |
|
|
@ -0,0 +1,6 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="8.3199462890625" height="8.239997863769531" viewBox="0 0 8.3199462890625 8.239997863769531"
|
||||
fill="none">
|
||||
<path id="路径 1" fill-rule="evenodd" style="fill:currentColor" opacity="1"
|
||||
d="M7.99999 0L0.32 0C0.14 0 0 0.14 0 0.32L0 2.01C0 2.18 0.14 2.32 0.32 2.32C0.499999 2.32 0.639999 2.18 0.639999 2.01L0.639999 0.63L3.84 0.63L3.84 7.6L2.45 7.6C2.28 7.6 2.13 7.74 2.13 7.92C2.13 8.09 2.28 8.24 2.45 8.24L5.85999 8.24C6.03999 8.24 6.17999 8.09 6.17999 7.92C6.17999 7.74 6.03999 7.6 5.85999 7.6L4.47999 7.6L4.47999 0.63L7.67999 0.63L7.67999 2.01C7.67999 2.18 7.81999 2.32 7.99999 2.32C8.16999 2.32 8.31999 2.18 8.31999 2.01L8.31999 0.32C8.31999 0.14 8.16999 0 7.99999 0Z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 782 B |
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg t="1691136491391" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="1469" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="200" height="200">
|
||||
<path
|
||||
d="M264.789333 627.626667a42.965333 42.965333 0 0 1-60.288 0 41.856 41.856 0 0 1 0-59.648l247.210667-244.608a85.930667 85.930667 0 0 1 120.576 0l247.210667 244.608a41.856 41.856 0 0 1 0 59.648 42.965333 42.965333 0 0 1-60.288 0L512 383.018667 264.789333 627.626667z"
|
||||
fill="currentColor" p-id="1470"></path>
|
||||
<path
|
||||
d="M512 1024c282.752 0 512-229.248 512-512S794.752 0 512 0 0 229.248 0 512s229.248 512 512 512z m0-85.333333C276.352 938.666667 85.333333 747.648 85.333333 512S276.352 85.333333 512 85.333333s426.666667 191.018667 426.666667 426.666667-191.018667 426.666667-426.666667 426.666667z"
|
||||
fill="currentColor" p-id="1471"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 998 B |
|
|
@ -0,0 +1,6 @@
|
|||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="37px" height="37px">
|
||||
<image x="0px" y="0px" width="37px" height="37px" xlink:href="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAlCAQAAABvl+iIAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfnBxMJLhVeEnOzAAABu0lEQVRIx+2UT0gUYRiHn9ndEBaKNCMhiQ5Wh+iSFIhdKugUCR091KEQokM3QW/RpU7huWNBlzpEYBAZgUGgdYmkg4iJGdEfwkJMN306zOzurDOb2nSK/c1hvvm97/vwve98fMgGnrNuXz9rfUyXw+qkp7Oh9nnfqsbt/jvUHu+Z1HOPbg7V6i1/WU8PPLQxVIv9zteUPvKUA2twNzzwZ1TOi35P7CIQ8WXCv2pLPVSvc6kNHReD1NiiA+bXonp9U3c2JZ86XTf6wcEq6owjZtNrL1nE6xkxZd0p8Jg2zgOwRD+hhqL3Ex4S10H6otVN3gFwmf0AzHE7nFSo4coPCHf602LiqEyo+qryfSKqPVce+wV11vZKQt4ptS/lIB5WtTPmDKkjIjkARoF53lcaWeELMEZSbwGYiTkvgEkgQu0CttSUNAE7U1A7AGiOOa3A1irqn6iBaqAaqP8M9Rko1fjLwMeU/PBOm405X4EfAAUAuoFtdBEQALJKM3CSYhQva4U2AHqYIQ9AiSNAB00sBQJ8Sr3mNqMOpsIGFzIPKoAcV5imPTPqGdcKdLI3Mwh2c6zAXb6xmhmVY/Q3a2Hie2ZcC9EAAAAASUVORK5CYII=" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1003 B |
|
|
@ -0,0 +1,6 @@
|
|||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="41px" height="40px">
|
||||
<image x="0px" y="0px" width="41px" height="40px" xlink:href="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAACkAAAAoCAQAAADJNRvYAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfnBxMJLhbHGyIJAAADZklEQVRIx62WW4hVZRTHf8cz5TQXbQzyFNGNjDG6gJmTJCkpFfUgptA0RUm9VIQ+SAXRQyDVQwRRPWQwMF0gLYsuM5pgoKQGBmlRgeIUMSmZmuOcGae5nV8P851z9jln784uXPthr/2ttf7fWutba+0PSfVc6JNelU43HWDWfeqArecOcpbTtDiN9gzSUIF8eKegdJDDCMBv5wbyPO6imxYA3mY1zXUt6mRmvacsUkHVEV+udzxZL0oQNtmn6lYf8bQ65XrfUnW/VybYzLYJv3HMtTHCKzysHvZ2EQdVbRFvdrd6wo4Ym7sdcgg3qvqGN1QUzTpH1L02hb2HKopoi6ovmIvYXO2Lqr6H+JTjqu70Obt8wvdD7rpL6q0BclFp5ZWg84nr7HKDveF7Y7HUL3WTvxulXpdGPKiFxFvc7FjE4rQ9XlvdPQv8VZ30PluqchQHidjock+qw65wRlxDZj2jFmI6OQkScVSd9JL4hlzLLCDDS6k6qmjTCGR5LL7Ut6vPqmM2pPbyZ/Vxxx2Im0SXq3nxe/X6lJA3qqPiweiUKge+DNgH9ACdKcO+DfgI2AUsqQ38Q/V+cY56pnx+/+rlXnWh2K7+WB14mzoU+H71jhSQ89Szgf+pLC0G/jCwLfCbK8JIpmXAl4HfFklX2KVXfTRyUAMpvNyhrgj8IvWHaOCNTjjh+SXlo+ryOpCXqccj3/3qdeXAu2hgO+OlkD4FVtYJ+8FIqggp6CwH/rm6OrJjzgl/qePl11oxWm5yygPFwJ92yoLtFXk6pr5mJhHyGXXcORU2efVVM0gYTv0+5Hzneo0r/S78Z+YmQGbCv+iQnc435zxXeSDYNCO+G5l6oxF+d+nAar18J6L3d4TfaXZa4XVrqS/SQXG57Imx2RLtng4/9kQQDPqV96aoy1v9wpOlmb7DO6fXM5bLoJkcjUxynMGqgmnlKK1AB/urJC3kmMkEfzBUXGqIiEfoTzmByjTMkeqldHeifLhgpdqyIVGygIWBK3ABMwHYwJFgkeEQuxIsjX+WWp8eiLdN8nINcJBvyZZ2nvat6Hc7S1jDB/8l8DzQzZuJabmHvnCNraFoEcFiNtGETHExbZziz4TjK9BGjjzHyJJhkufZmgT5F21pzjSGmjlbZCu9+Ox/Au5hovzxDyCmVrQ+22sRAAAAAElFTkSuQmCC" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -0,0 +1,6 @@
|
|||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="37px" height="36px">
|
||||
<image x="0px" y="0px" width="37px" height="36px" xlink:href="data:img/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAkCAQAAACkyzstAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElNRQfnBxMJLhO3cdaGAAABuUlEQVRIx82TPUscURSG31kWUVjWmLiNUYkoYpNAgmgrQiABy0BAhPwA6zSmSJNCFPsQ8AdIqmAqGwXBVbAQLNUEVIKEpBD8WnXnSeFxd2ZnZxxnDPje4tz73nOeO/cMVyjGWOT1zVlxQCvAJc/To5a50gXP0qGWqKoUDYvCPGYTvy55mwTVzAH1NHR71KqV7rIHlNiw9TFPboeat8I1WvkJlOnivXl/6YiLyvHdipZxEC4A/YgZ838zEAeVZ8cK5hGiwBkAIwgxXunZy5tQObYtdd2ch4Z6ZevpCmw4ClVgy9L+0BKCEnMV2GA4qmgpB57GBlHiawWWD0O9AaDIA49XDyU+AjBFY3ivRlioceqjxGdm4z+caFRgZHRnukNUNmFdn17IleTqm0rpUGP6YLNH16ikFzy0eKpy2l5h0a1a9/8PftJTlZXViibTokbVJUlqS4byXnDX4n6yC97Ptv8nVLkmXunEYsnnngf2fSgn8jD/rhPYl8M7Tdi8Q02SpCP98qG65Ujar54vqUUFSZKrH/Z4vmTVqd6a78gFHElqD/nmHpt1Z9SQptUeNWa1oAbv+06ojBb/AcSXABJRGZ94AAAAAElFTkSuQmCC" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 999 B |
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg t="1690349868458" class="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg" p-id="6238" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="128" height="128">
|
||||
<path
|
||||
d="M873.411765 150.588235v722.82353H150.588235V150.588235h722.82353m30.117647-60.235294H120.470588c-16.564706 0-30.117647 13.552941-30.117647 30.117647v783.058824c0 16.564706 13.552941 30.117647 30.117647 30.117647h783.058824c16.564706 0 30.117647-13.552941 30.117647-30.117647V120.470588c0-16.564706-13.552941-30.117647-30.117647-30.117647z"
|
||||
fill="currentColor" p-id="6239"></path>
|
||||
<path
|
||||
d="M301.176471 271.058824c16.564706 0 30.117647 13.552941 30.117647 30.117647s-13.552941 30.117647-30.117647 30.117647-30.117647-13.552941-30.117647-30.117647 13.552941-30.117647 30.117647-30.117647m0-60.235295c-49.995294 0-90.352941 40.357647-90.352942 90.352942s40.357647 90.352941 90.352942 90.352941 90.352941-40.357647 90.352941-90.352941-40.357647-90.352941-90.352941-90.352942zM240.941176 602.352941a30.147765 30.147765 0 0 1-19.275294-53.308235l161.430589-134.625882c22.287059-18.672941 54.814118-18.672941 77.101176 0L602.352941 533.082353l161.430588-134.625882a30.117647 30.117647 0 1 1 38.550589 46.381176l-161.430589 134.625882c-22.287059 18.672941-54.814118 18.672941-77.101176 0L421.647059 460.8l-161.430588 134.625882c-5.722353 4.517647-12.348235 6.927059-19.275295 6.927059zM240.941176 813.176471c-16.564706 0-30.117647-13.552941-30.117647-30.117647v-120.470589c0-16.564706 13.552941-30.117647 30.117647-30.117647s30.117647 13.552941 30.117648 30.117647v120.470589c0 16.564706-13.552941 30.117647-30.117648 30.117647z"
|
||||
fill="currentColor" p-id="6240"></path>
|
||||
<path
|
||||
d="M421.647059 813.176471c-16.564706 0-30.117647-13.552941-30.117647-30.117647v-210.82353c0-16.564706 13.552941-30.117647 30.117647-30.117647s30.117647 13.552941 30.117647 30.117647v210.82353c0 16.564706-13.552941 30.117647-30.117647 30.117647zM602.352941 813.176471c-16.564706 0-30.117647-13.552941-30.117647-30.117647v-120.470589c0-16.564706 13.552941-30.117647 30.117647-30.117647s30.117647 13.552941 30.117647 30.117647v120.470589c0 16.564706-13.552941 30.117647-30.117647 30.117647zM783.058824 813.176471c-16.564706 0-30.117647-13.552941-30.117648-30.117647v-210.82353c0-16.564706 13.552941-30.117647 30.117648-30.117647s30.117647 13.552941 30.117647 30.117647v210.82353c0 16.564706-13.552941 30.117647-30.117647 30.117647zM752.941176 361.411765h-150.588235c-16.564706 0-30.117647-13.552941-30.117647-30.117647s13.552941-30.117647 30.117647-30.117647h150.588235c16.564706 0 30.117647 13.552941 30.117648 30.117647s-13.552941 30.117647-30.117648 30.117647zM512 361.411765c-1.807059 0-3.915294-0.301176-6.023529-0.602353a19.154824 19.154824 0 0 1-5.421177-1.807059 22.799059 22.799059 0 0 1-5.421176-2.710588l-4.517647-3.614118c-5.421176-5.722353-8.734118-13.552941-8.734118-21.383529 0-7.830588 3.312941-15.661176 8.734118-21.38353 1.505882-1.204706 3.011765-2.710588 4.517647-3.614117 1.807059-1.204706 3.614118-2.108235 5.421176-2.710589 1.807059-0.903529 3.614118-1.505882 5.421177-1.807058 9.938824-2.108235 20.178824 1.204706 27.407058 8.131764 5.421176 5.722353 8.734118 13.552941 8.734118 21.38353 0 7.830588-3.312941 15.661176-8.734118 21.383529-5.722353 5.421176-13.552941 8.734118-21.383529 8.734118zM752.941176 271.058824h-60.235294c-16.564706 0-30.117647-13.552941-30.117647-30.117648s13.552941-30.117647 30.117647-30.117647h60.235294c16.564706 0 30.117647 13.552941 30.117648 30.117647s-13.552941 30.117647-30.117648 30.117648z"
|
||||
fill="currentColor" p-id="6241"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
|
|
@ -0,0 +1,22 @@
|
|||
# replace default config
|
||||
|
||||
# multipass: true
|
||||
# full: true
|
||||
|
||||
plugins:
|
||||
|
||||
# - name
|
||||
#
|
||||
# or:
|
||||
# - name: false
|
||||
# - name: true
|
||||
#
|
||||
# or:
|
||||
# - name:
|
||||
# param1: 1
|
||||
# param2: 2
|
||||
|
||||
- removeAttrs:
|
||||
attrs:
|
||||
- 'fill'
|
||||
- 'fill-rule'
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* [本地缓存]
|
||||
* @Author: Fu Xiaochun
|
||||
* @Email: f2e.xiaochun@gmail.com
|
||||
*/
|
||||
|
||||
|
||||
function factory(engine){
|
||||
return {
|
||||
set: (key, data)=>{
|
||||
if(!key){ return; }
|
||||
engine.setItem(key, JSON.stringify(data));
|
||||
},
|
||||
get: (key)=>{
|
||||
if(!key){ return; }
|
||||
let data = engine.getItem(key);
|
||||
try {
|
||||
return JSON.parse(data);
|
||||
} catch (error) {
|
||||
return data;
|
||||
}
|
||||
},
|
||||
remove: (key)=>{
|
||||
if(!key){ return; }
|
||||
engine.removeItem(key);
|
||||
},
|
||||
clear: ()=>{
|
||||
engine.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const localCache = factory(localStorage);
|
||||
export const sessionCache = factory(sessionStorage);
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* [axios封装]
|
||||
* @Author: Fu Xiaochun
|
||||
* @Email: f2e.xiaochun@gmail.com
|
||||
*/
|
||||
|
||||
import axios from 'axios';
|
||||
|
||||
const http = (url = '', data = {}, type = 'POST', otherConfig = {}) => {
|
||||
let config = Object.assign({ isLoading: true, timeout: 10000 }, otherConfig);
|
||||
let promise;
|
||||
type = type.toUpperCase();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (type === 'GET') {
|
||||
promise = axios({
|
||||
method: type,
|
||||
url,
|
||||
params: data,
|
||||
timeout: config.timeout
|
||||
});
|
||||
} else if (['POST', 'DELETE', 'PUT', 'PATCH'].includes(type)) {
|
||||
promise = axios({
|
||||
method: type,
|
||||
url,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
'Accept': 'application/json; charset=UTF-8',
|
||||
'isLoading': config.isLoading,
|
||||
},
|
||||
data: data,
|
||||
timeout: config.timeout
|
||||
});
|
||||
} else {
|
||||
promise = Promise.reject('请求方法入参错误:', type);
|
||||
}
|
||||
|
||||
promise.then((response) => {
|
||||
if (response && response.status >= 200 && response.status < 300 && response.data.status == 0) {
|
||||
resolve(response.data);
|
||||
} else {
|
||||
if(response && response.data && response.data.status == 401){
|
||||
return false;
|
||||
}else if (response && response.data) {
|
||||
reject({ ...response.data, message: response.data.message ? response.data.message : response.data.msg });
|
||||
} else {
|
||||
reject('当前系统繁忙,请稍后再试');
|
||||
}
|
||||
}
|
||||
}).catch((error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export default http;
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
* [axios配置]
|
||||
* @Author: Fu Xiaochun
|
||||
* @Email: f2e.xiaochun@gmail.com
|
||||
*/
|
||||
|
||||
import axios from 'axios';
|
||||
import { localCache } from './cache';
|
||||
import router from "@/router";
|
||||
import hostAPI from '@/config/host.config'
|
||||
import { showToast } from 'vant';
|
||||
|
||||
export default function () {
|
||||
let _token = '';
|
||||
let requestCount = 0;//请求数量
|
||||
|
||||
// axios.defaults.baseURL = '//' + window.location.host;
|
||||
axios.defaults.baseURL = hostAPI;
|
||||
|
||||
// 请求超时时间为10秒
|
||||
axios.defaults.timeout = 10000;
|
||||
|
||||
// 请求发送拦截,并在头部加入token
|
||||
axios.interceptors.request.use(
|
||||
function (config) {
|
||||
|
||||
let nextToken = localCache.get('auth') && localCache.get('auth').token;
|
||||
let toeknType = localCache.get('auth') && localCache.get('auth').token_type;
|
||||
if (config.url.indexOf('/auth/login') > -1) {
|
||||
// 如果为登录接口,重置登录信息
|
||||
_token = '';
|
||||
} else if (_token == '') {
|
||||
// 第一次登录直接从缓存后去token
|
||||
_token = nextToken;
|
||||
} else {
|
||||
// 前后两次调用token不同,退出登录防止串token
|
||||
_token = _token != nextToken ? '' : nextToken;
|
||||
}
|
||||
if (_token) {
|
||||
config.headers['Authorization'] = `${toeknType} ${_token}`; // 存在将token写入请求头
|
||||
}
|
||||
// if (config.headers.isLoading !== false) showLoading();
|
||||
return config;
|
||||
},
|
||||
function (error) {
|
||||
// if (error.config.headers.isLoading !== false) hideLoading();
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
// 请求结果拦截,根据不同的错误码触发相应操作
|
||||
axios.interceptors.response.use(
|
||||
function (response) {
|
||||
try {
|
||||
if (response.data.status != 0) {
|
||||
if (response.data.status == 401 ) {
|
||||
// token失效
|
||||
showToast('账号过期或异地登录, 请重新登录');
|
||||
localCache.remove('auth');
|
||||
localCache.remove('userInfo');
|
||||
window.location.pathname='/home';
|
||||
// router.replace({name: 'Home', params: {auth: 'over'}});
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
showToast('后台' + response.data.status + '错误返回格式不正确');
|
||||
}
|
||||
// if (response.config.headers.isLoading !== false) hideLoading();
|
||||
return response;
|
||||
},
|
||||
function (error) {
|
||||
// if (error.config.headers.isLoading !== false) hideLoading();
|
||||
if (error.response) {
|
||||
switch (error.response.data.status) {
|
||||
case 401:
|
||||
// token失效
|
||||
showToast('账号过期或异地登录, 请重新登录');
|
||||
localCache.remove('auth');
|
||||
localCache.remove('userInfo');
|
||||
window.location.pathname='/home';
|
||||
break;
|
||||
case 500:
|
||||
// 500 服务端请求错误
|
||||
showToast('接口500错误:【' + error.response.data.path + '】');
|
||||
return Promise.reject(error.response);
|
||||
case 404:
|
||||
// 找不到资源
|
||||
showToast('接口404错误:【' + error.response.data.path + '】');
|
||||
return Promise.reject(error.response);
|
||||
default:
|
||||
return Promise.reject(error.response);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import "./assets/css/main.css";
|
||||
import 'virtual:svg-icons-register';
|
||||
import 'virtual:windi.css'
|
||||
|
||||
import { createApp } from "vue";
|
||||
import { createPinia } from "pinia";
|
||||
|
||||
import App from "./App.vue";
|
||||
import router from "./router";
|
||||
import { registerSvgIcon } from './icons/index.js'
|
||||
import httpConfig from "./io/httpConfig";
|
||||
import 'vant/es/toast/style';
|
||||
|
||||
|
||||
httpConfig();
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
registerSvgIcon(app);
|
||||
|
||||
app.use(createPinia());
|
||||
app.use(router);
|
||||
|
||||
app.mount("#app");
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import { createRouter, createWebHistory } from "vue-router";
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes: [
|
||||
{
|
||||
path: "/",
|
||||
name: "Layout",
|
||||
redirect: "/home",
|
||||
children: [{
|
||||
path: "home",
|
||||
name: "Home",
|
||||
mate: {
|
||||
title: "首页-AI助理",
|
||||
},
|
||||
component: () => import("@/views/home/index.vue"),
|
||||
}]
|
||||
}
|
||||
],
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { ref, computed } from "vue";
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
export const useAuthModal = defineStore("authModal", () => {
|
||||
const isShow = ref(false);
|
||||
const authModalType = ref('login');
|
||||
function showAuthModal() {
|
||||
isShow.value = true;
|
||||
}
|
||||
function hideAuthModal(){
|
||||
isShow.value = false;
|
||||
}
|
||||
function setAuthModalType(type){
|
||||
authModalType.value = type;
|
||||
}
|
||||
|
||||
return { isShow, authModalType, showAuthModal, hideAuthModal, setAuthModalType };
|
||||
});
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { ref, computed } from "vue";
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
export const useUserInfo = defineStore("userInfo", () => {
|
||||
const userData = ref({});
|
||||
function updateUserInfo(data) {
|
||||
userData.value = data;
|
||||
}
|
||||
|
||||
return { userData, updateUserInfo };
|
||||
});
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
export function copyToClip(text) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const input = document.createElement('textarea')
|
||||
input.setAttribute('readonly', 'readonly')
|
||||
input.value = text
|
||||
document.body.appendChild(input)
|
||||
input.select()
|
||||
if (document.execCommand('copy'))
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(input)
|
||||
resolve(text)
|
||||
}
|
||||
catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
|
||||
import { upperFirst } from 'lodash-es'
|
||||
|
||||
|
||||
export function getBoundingClientRect(element) {
|
||||
if (!element || !element.getBoundingClientRect) {
|
||||
return 0
|
||||
}
|
||||
return element.getBoundingClientRect()
|
||||
}
|
||||
|
||||
function trim(string) {
|
||||
return (string || '').replace(/^[\s\uFEFF]+|[\s\uFEFF]+$/g, '')
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
export function hasClass(el, cls) {
|
||||
if (!el || !cls) return false
|
||||
if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.')
|
||||
if (el.classList) {
|
||||
return el.classList.contains(cls)
|
||||
} else {
|
||||
return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1
|
||||
}
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
export function addClass(el, cls) {
|
||||
if (!el) return
|
||||
let curClass = el.className
|
||||
const classes = (cls || '').split(' ')
|
||||
|
||||
for (let i = 0, j = classes.length; i < j; i++) {
|
||||
const clsName = classes[i]
|
||||
if (!clsName) continue
|
||||
|
||||
if (el.classList) {
|
||||
el.classList.add(clsName)
|
||||
} else if (!hasClass(el, clsName)) {
|
||||
curClass += ' ' + clsName
|
||||
}
|
||||
}
|
||||
if (!el.classList) {
|
||||
el.className = curClass
|
||||
}
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
export function removeClass(el, cls) {
|
||||
if (!el || !cls) return
|
||||
const classes = cls.split(' ')
|
||||
let curClass = ' ' + el.className + ' '
|
||||
|
||||
for (let i = 0, j = classes.length; i < j; i++) {
|
||||
const clsName = classes[i]
|
||||
if (!clsName) continue
|
||||
|
||||
if (el.classList) {
|
||||
el.classList.remove(clsName)
|
||||
} else if (hasClass(el, clsName)) {
|
||||
curClass = curClass.replace(' ' + clsName + ' ', ' ')
|
||||
}
|
||||
}
|
||||
if (!el.classList) {
|
||||
el.className = trim(curClass)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Get the left and top offset of the current element
|
||||
* left: the distance between the leftmost element and the left side of the document
|
||||
* top: the distance from the top of the element to the top of the document
|
||||
* right: the distance from the far right of the element to the right of the document
|
||||
* bottom: the distance from the bottom of the element to the bottom of the document
|
||||
* rightIncludeBody: the distance between the leftmost element and the right side of the document
|
||||
* bottomIncludeBody: the distance from the bottom of the element to the bottom of the document
|
||||
*
|
||||
* @description:
|
||||
*/
|
||||
export function getViewportOffset(element) {
|
||||
const doc = document.documentElement
|
||||
|
||||
const docScrollLeft = doc.scrollLeft
|
||||
const docScrollTop = doc.scrollTop
|
||||
const docClientLeft = doc.clientLeft
|
||||
const docClientTop = doc.clientTop
|
||||
|
||||
const pageXOffset = window.pageXOffset
|
||||
const pageYOffset = window.pageYOffset
|
||||
|
||||
const box = getBoundingClientRect(element)
|
||||
|
||||
const { left: retLeft, top: rectTop, width: rectWidth, height: rectHeight } = box
|
||||
|
||||
const scrollLeft = (pageXOffset || docScrollLeft) - (docClientLeft || 0)
|
||||
const scrollTop = (pageYOffset || docScrollTop) - (docClientTop || 0)
|
||||
const offsetLeft = retLeft + pageXOffset
|
||||
const offsetTop = rectTop + pageYOffset
|
||||
|
||||
const left = offsetLeft - scrollLeft
|
||||
const top = offsetTop - scrollTop
|
||||
|
||||
const clientWidth = window.document.documentElement.clientWidth
|
||||
const clientHeight = window.document.documentElement.clientHeight
|
||||
return {
|
||||
left: left,
|
||||
top: top,
|
||||
right: clientWidth - rectWidth - left,
|
||||
bottom: clientHeight - rectHeight - top,
|
||||
rightIncludeBody: clientWidth - left,
|
||||
bottomIncludeBody: clientHeight - top,
|
||||
}
|
||||
}
|
||||
|
||||
export function hackCss(attr, value) {
|
||||
const prefix = ['webkit', 'Moz', 'ms', 'OT']
|
||||
|
||||
const styleObj = {}
|
||||
prefix.forEach((item) => {
|
||||
styleObj[`${item}${upperFirst(attr)}`] = value
|
||||
})
|
||||
return {
|
||||
...styleObj,
|
||||
[attr]: value,
|
||||
}
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
export function on(
|
||||
element,
|
||||
event,
|
||||
handler,
|
||||
) {
|
||||
if (element && event && handler) {
|
||||
element.addEventListener(event, handler, false)
|
||||
}
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
export function off(
|
||||
element,
|
||||
event,
|
||||
handler,
|
||||
) {
|
||||
if (element && event && handler) {
|
||||
element.removeEventListener(event, handler, false)
|
||||
}
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
export function once(el, event, fn) {
|
||||
const listener = function (self, ...args) {
|
||||
if (fn) {
|
||||
fn.apply(this, args)
|
||||
}
|
||||
off(el, event, listener)
|
||||
}
|
||||
on(el, event, listener)
|
||||
}
|
||||
|
||||
export function useRafThrottle(fn) {
|
||||
let locked = false
|
||||
// @ts-ignore
|
||||
return function (...args) {
|
||||
if (locked) return
|
||||
locked = true
|
||||
window.requestAnimationFrame(() => {
|
||||
// @ts-ignore
|
||||
fn.apply(this, args)
|
||||
locked = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
import ResizeObserver from 'resize-observer-polyfill'
|
||||
|
||||
const isServer = typeof window === 'undefined'
|
||||
|
||||
/* istanbul ignore next */
|
||||
function resizeHandler(entries) {
|
||||
for (const entry of entries) {
|
||||
const listeners = entry.target.__resizeListeners__ || []
|
||||
if (listeners.length) {
|
||||
listeners.forEach((fn) => {
|
||||
fn()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
export function addResizeListener(element, fn) {
|
||||
if (isServer) return
|
||||
if (!element.__resizeListeners__) {
|
||||
element.__resizeListeners__ = []
|
||||
element.__ro__ = new ResizeObserver(resizeHandler)
|
||||
element.__ro__.observe(element)
|
||||
}
|
||||
element.__resizeListeners__.push(fn)
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
export function removeResizeListener(element, fn) {
|
||||
if (!element || !element.__resizeListeners__) return
|
||||
element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1)
|
||||
if (!element.__resizeListeners__.length) {
|
||||
element.__ro__.disconnect()
|
||||
}
|
||||
}
|
||||
|
||||
export function triggerWindowResize() {
|
||||
const event = document.createEvent('HTMLEvents')
|
||||
event.initEvent('resize', true, true)
|
||||
;(event).eventType = 'message'
|
||||
window.dispatchEvent(event)
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
const toString = Object.prototype.toString
|
||||
|
||||
export function is(val, type) {
|
||||
return toString.call(val) === `[object ${type}]`
|
||||
}
|
||||
|
||||
export function isDef(val) {
|
||||
return typeof val !== 'undefined'
|
||||
}
|
||||
|
||||
export function isUnDef(val) {
|
||||
return !isDef(val)
|
||||
}
|
||||
|
||||
export function isObject(val) {
|
||||
return val !== null && is(val, 'Object')
|
||||
}
|
||||
|
||||
export function isEmpty(val) {
|
||||
if (isArray(val) || isString(val)) {
|
||||
return val.length === 0
|
||||
}
|
||||
|
||||
if (val instanceof Map || val instanceof Set) {
|
||||
return val.size === 0
|
||||
}
|
||||
|
||||
if (isObject(val)) {
|
||||
return Object.keys(val).length === 0
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
export function isDate(val) {
|
||||
return is(val, 'Date')
|
||||
}
|
||||
|
||||
export function isNull(val) {
|
||||
return val === null
|
||||
}
|
||||
|
||||
export function isNullAndUnDef(val) {
|
||||
return isUnDef(val) && isNull(val)
|
||||
}
|
||||
|
||||
export function isNullOrUnDef(val) {
|
||||
return isUnDef(val) || isNull(val)
|
||||
}
|
||||
|
||||
export function isNumber(val) {
|
||||
return is(val, 'Number')
|
||||
}
|
||||
|
||||
export function isPromise(val) {
|
||||
return is(val, 'Promise') && isObject(val) && isFunction(val.then) && isFunction(val.catch)
|
||||
}
|
||||
|
||||
export function isString(val) {
|
||||
return is(val, 'String')
|
||||
}
|
||||
|
||||
export function isFunction(val) {
|
||||
return typeof val === 'function'
|
||||
}
|
||||
|
||||
export function isBoolean(val) {
|
||||
return is(val, 'Boolean')
|
||||
}
|
||||
|
||||
export function isRegExp(val) {
|
||||
return is(val, 'RegExp')
|
||||
}
|
||||
|
||||
export function isArray(val) {
|
||||
return val && Array.isArray(val)
|
||||
}
|
||||
|
||||
export function isWindow(val) {
|
||||
return typeof window !== 'undefined' && is(val, 'Window')
|
||||
}
|
||||
|
||||
export function isElement(val) {
|
||||
return isObject(val) && !!val.tagName
|
||||
}
|
||||
|
||||
export function isMap(val) {
|
||||
return is(val, 'Map')
|
||||
}
|
||||
|
||||
export const isServer = typeof window === 'undefined'
|
||||
|
||||
export const isClient = !isServer
|
||||
|
||||
export function isUrl(path) {
|
||||
const reg =
|
||||
/^(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?(\/#\/)?(?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/
|
||||
return reg.test(path)
|
||||
}
|
||||
/**
|
||||
* 验证手机格式
|
||||
*/
|
||||
export function isMobile(value) {
|
||||
return /^1[3-9]\d{9}$/.test(value)
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<template>
|
||||
<div>
|
||||
移动端
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted } from 'vue';
|
||||
import { showToast } from 'vant';
|
||||
|
||||
onMounted(()=>{
|
||||
showToast('页面初始化');
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import { fileURLToPath, URL } from 'node:url'
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import WindiCSS from 'vite-plugin-windicss'
|
||||
|
||||
import Components from 'unplugin-vue-components/vite';
|
||||
import { VantResolver } from 'unplugin-vue-components/resolvers';
|
||||
|
||||
const path = require('path')
|
||||
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
|
||||
import hostAPI from './src/config/host.config'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
vueJsx(),
|
||||
WindiCSS(),
|
||||
createSvgIconsPlugin({
|
||||
iconDirs: [path.resolve(process.cwd(), 'src/icons/svg')],
|
||||
symbolId: 'icon-[name]',
|
||||
}),
|
||||
Components({
|
||||
resolvers: [
|
||||
VantResolver({
|
||||
importStyle: false, // css in js
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
},
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
//define global scss variable
|
||||
scss: {
|
||||
additionalData: `@import "@/assets/css/mixin.scss";`
|
||||
}
|
||||
}
|
||||
},
|
||||
server: {
|
||||
host: 'localhost',
|
||||
port: '8080',
|
||||
open: false,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: hostAPI,
|
||||
changeOrigin: true,
|
||||
// rewrite: (path) => path.replace(/^\/api/, ''),
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
export default {
|
||||
extend: {
|
||||
|
||||
},
|
||||
plugins: [
|
||||
require('windicss/plugin/line-clamp'),
|
||||
],
|
||||
}
|
||||