mirror of https://github.com/certd/certd
chore: code format
parent
04422a4637
commit
4fcfd089d8
|
@ -15,7 +15,8 @@
|
|||
"serve": "vite preview",
|
||||
"preview": "vite preview",
|
||||
"pretty-quick": "pretty-quick",
|
||||
"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/",
|
||||
"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue --ext .ts --ext .tsx src/",
|
||||
"format": "prettier --write src",
|
||||
"upgrade": "yarn upgrade-interactive --latest",
|
||||
"tsc": "vue-tsc --noEmit --skipLibCheck",
|
||||
"circle:check": "pnpm dependency-cruise --validate --output-type err-html -f dependency-report.html src",
|
||||
|
|
|
@ -10,6 +10,10 @@ import { cloneDeep, debounce as lodashDebounce } from "lodash-es";
|
|||
import { initWorkers } from "./workers";
|
||||
import { importJavascriptContribution, importJsonContribution, importMonacoYaml, importYamlContribution } from "./async-import";
|
||||
|
||||
defineOptions({
|
||||
name: "CodeEditor",
|
||||
});
|
||||
|
||||
/**
|
||||
* config:
|
||||
* value: '', // 编辑器初始文本
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
<script>
|
||||
export default {
|
||||
name: "PiContainer"
|
||||
name: "PiContainer",
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,21 +1,17 @@
|
|||
<template>
|
||||
<div class="cron-editor">
|
||||
<div class="flex-o">
|
||||
<cron-light :disabled="disabled" :readonly="readonly" :period="period" class="flex-o cron-ant"
|
||||
locale="zh-CN" format="quartz" :model-value="modelValue" @update:model-value="onUpdate"
|
||||
@error="onError" />
|
||||
</div>
|
||||
<div class="mt-5 flex">
|
||||
<a-input :disabled="true" :readonly="readonly" :value="modelValue" @change="onChange"></a-input>
|
||||
<fs-icon icon="ion:close-circle" class="pointer fs-16 ml-5 color-gray" :title="t('certd.cron.clearTip')"
|
||||
@click="onClear"></fs-icon>
|
||||
</div>
|
||||
<div class="helper">{{ t('certd.cron.nextTrigger') }}:{{ nextTime }}</div>
|
||||
<div class="fs-helper">{{ errorMessage }}</div>
|
||||
</div>
|
||||
<div class="cron-editor">
|
||||
<div class="flex-o">
|
||||
<cron-light :disabled="disabled" :readonly="readonly" :period="period" class="flex-o cron-ant" locale="zh-CN" format="quartz" :model-value="modelValue" @update:model-value="onUpdate" @error="onError" />
|
||||
</div>
|
||||
<div class="mt-5 flex">
|
||||
<a-input :disabled="true" :readonly="readonly" :value="modelValue" @change="onChange"></a-input>
|
||||
<fs-icon icon="ion:close-circle" class="pointer fs-16 ml-5 color-gray" :title="t('certd.cron.clearTip')" @click="onClear"></fs-icon>
|
||||
</div>
|
||||
<div class="helper">{{ t("certd.cron.nextTrigger") }}:{{ nextTime }}</div>
|
||||
<div class="fs-helper">{{ errorMessage }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script lang="ts" setup>
|
||||
import parser from "cron-parser";
|
||||
import { computed, ref } from "vue";
|
||||
|
@ -25,108 +21,107 @@ import { useI18n } from "vue-i18n";
|
|||
const { t } = useI18n();
|
||||
import { getCronNextTimes } from "/@/components/cron-editor/utils";
|
||||
defineOptions({
|
||||
name: "CronEditor",
|
||||
name: "CronEditor",
|
||||
});
|
||||
const props = defineProps<{
|
||||
modelValue?: string;
|
||||
disabled?: boolean;
|
||||
readonly?: boolean;
|
||||
allowEveryMin?: boolean;
|
||||
modelValue?: string;
|
||||
disabled?: boolean;
|
||||
readonly?: boolean;
|
||||
allowEveryMin?: boolean;
|
||||
}>();
|
||||
|
||||
const period = ref<string>("");
|
||||
if (props.modelValue == null || props.modelValue.endsWith("* * *")) {
|
||||
period.value = "day";
|
||||
period.value = "day";
|
||||
} else if (props.modelValue.endsWith("* *")) {
|
||||
period.value = "month";
|
||||
period.value = "month";
|
||||
} else if (props.modelValue.endsWith("*")) {
|
||||
period.value = "year";
|
||||
period.value = "year";
|
||||
}
|
||||
const emit = defineEmits<{
|
||||
"update:modelValue": any;
|
||||
change: any;
|
||||
"update:modelValue": any;
|
||||
change: any;
|
||||
}>();
|
||||
|
||||
const errorMessage = ref<string | null>(null);
|
||||
|
||||
const onUpdate = (value: string) => {
|
||||
if (value === props.modelValue) {
|
||||
return;
|
||||
}
|
||||
const arr: string[] = value.split(" ");
|
||||
if (arr[0] === "*") {
|
||||
arr[0] = "0";
|
||||
}
|
||||
if (!props.allowEveryMin) {
|
||||
if (arr[1] === "*") {
|
||||
arr[1] = "0";
|
||||
}
|
||||
}
|
||||
if (value === props.modelValue) {
|
||||
return;
|
||||
}
|
||||
const arr: string[] = value.split(" ");
|
||||
if (arr[0] === "*") {
|
||||
arr[0] = "0";
|
||||
}
|
||||
if (!props.allowEveryMin) {
|
||||
if (arr[1] === "*") {
|
||||
arr[1] = "0";
|
||||
}
|
||||
}
|
||||
|
||||
value = arr.join(" ");
|
||||
value = arr.join(" ");
|
||||
|
||||
emit("update:modelValue", value);
|
||||
errorMessage.value = undefined;
|
||||
emit("update:modelValue", value);
|
||||
errorMessage.value = undefined;
|
||||
};
|
||||
|
||||
const onPeriod = (value: string) => {
|
||||
period.value = value;
|
||||
period.value = value;
|
||||
};
|
||||
|
||||
const onChange = (e: any) => {
|
||||
const value = e.target.value;
|
||||
onUpdate(value);
|
||||
const value = e.target.value;
|
||||
onUpdate(value);
|
||||
};
|
||||
const onError = (error: any) => {
|
||||
errorMessage.value = error;
|
||||
errorMessage.value = error;
|
||||
};
|
||||
|
||||
const onClear = () => {
|
||||
if (props.disabled) {
|
||||
return;
|
||||
}
|
||||
onUpdate("");
|
||||
if (props.disabled) {
|
||||
return;
|
||||
}
|
||||
onUpdate("");
|
||||
};
|
||||
|
||||
const nextTime = computed(() => {
|
||||
if (props.modelValue == null) {
|
||||
return t("certd.cron.tip");
|
||||
}
|
||||
if (props.modelValue == null) {
|
||||
return t("certd.cron.tip");
|
||||
}
|
||||
|
||||
try {
|
||||
const nextTimes = getCronNextTimes(props.modelValue, 2);
|
||||
return nextTimes.join(",");
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return t("certd.cron.tip");
|
||||
}
|
||||
try {
|
||||
const nextTimes = getCronNextTimes(props.modelValue, 2);
|
||||
return nextTimes.join(",");
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return t("certd.cron.tip");
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
<style lang="less">
|
||||
.cron-editor {
|
||||
.cron-ant {
|
||||
flex-wrap: wrap;
|
||||
.cron-ant {
|
||||
flex-wrap: wrap;
|
||||
|
||||
&*> {
|
||||
margin-bottom: 2px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
&* > {
|
||||
margin-bottom: 2px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.vcron-select-list {
|
||||
min-width: 56px;
|
||||
}
|
||||
.vcron-select-list {
|
||||
min-width: 56px;
|
||||
}
|
||||
|
||||
.vcron-select-input {
|
||||
min-height: 22px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.vcron-select-input {
|
||||
min-height: 22px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.vcron-select-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
.vcron-select-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
import { defineComponent, onMounted, ref } from "vue";
|
||||
import * as api from "./api";
|
||||
import { Modal, notification } from "ant-design-vue";
|
||||
|
||||
defineOptions({
|
||||
name: "EmailEditor",
|
||||
});
|
||||
const props = defineProps<{}>();
|
||||
const VNodes = defineComponent({
|
||||
props: {
|
||||
|
|
|
@ -16,7 +16,7 @@ import dayjs from "dayjs";
|
|||
import { computed } from "vue";
|
||||
|
||||
defineOptions({
|
||||
name: "ExpiresTimeText"
|
||||
name: "ExpiresTimeText",
|
||||
});
|
||||
|
||||
const props = defineProps<{
|
||||
|
|
|
@ -15,7 +15,7 @@ Author: Pedro Oliveira <kanytu@gmail . com>
|
|||
.hljs-literal,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #6897BB;
|
||||
color: #6897bb;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
|
@ -42,7 +42,7 @@ Author: Pedro Oliveira <kanytu@gmail . com>
|
|||
.hljs-string,
|
||||
.hljs-attribute,
|
||||
.hljs-addition {
|
||||
color: #6A8759;
|
||||
color: #6a8759;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
|
|
|
@ -8,7 +8,7 @@ Arduino® Light Theme - Stefania Mellai <s.mellai@arduino.cc>
|
|||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #FFFFFF;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.hljs,
|
||||
|
@ -21,7 +21,7 @@ Arduino® Light Theme - Stefania Mellai <s.mellai@arduino.cc>
|
|||
.hljs-selector-tag,
|
||||
.hljs-doctag,
|
||||
.hljs-name {
|
||||
color: #00979D;
|
||||
color: #00979d;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
|
@ -29,7 +29,7 @@ Arduino® Light Theme - Stefania Mellai <s.mellai@arduino.cc>
|
|||
.hljs-bullet,
|
||||
.hljs-code,
|
||||
.hljs-addition {
|
||||
color: #D35400;
|
||||
color: #d35400;
|
||||
}
|
||||
|
||||
.hljs-regexp,
|
||||
|
@ -39,7 +39,7 @@ Arduino® Light Theme - Stefania Mellai <s.mellai@arduino.cc>
|
|||
.hljs-link,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo {
|
||||
color: #00979D;
|
||||
color: #00979d;
|
||||
}
|
||||
|
||||
.hljs-type,
|
||||
|
@ -49,7 +49,7 @@ Arduino® Light Theme - Stefania Mellai <s.mellai@arduino.cc>
|
|||
.hljs-quote,
|
||||
.hljs-template-tag,
|
||||
.hljs-deletion {
|
||||
color: #005C5F;
|
||||
color: #005c5f;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
|
@ -59,15 +59,15 @@ Arduino® Light Theme - Stefania Mellai <s.mellai@arduino.cc>
|
|||
}
|
||||
|
||||
.hljs-comment {
|
||||
color: rgba(149,165,166,.8);
|
||||
color: rgba(149, 165, 166, 0.8);
|
||||
}
|
||||
|
||||
.hljs-meta-keyword {
|
||||
color: #728E00;
|
||||
color: #728e00;
|
||||
}
|
||||
|
||||
.hljs-meta {
|
||||
color: #728E00;
|
||||
color: #728e00;
|
||||
color: #434f54;
|
||||
}
|
||||
|
||||
|
@ -80,9 +80,9 @@ Arduino® Light Theme - Stefania Mellai <s.mellai@arduino.cc>
|
|||
}
|
||||
|
||||
.hljs-function {
|
||||
color: #728E00;
|
||||
color: #728e00;
|
||||
}
|
||||
|
||||
.hljs-number {
|
||||
color: #8A7B52;
|
||||
color: #8a7b52;
|
||||
}
|
||||
|
|
|
@ -8,14 +8,14 @@ Brown Paper style from goldblog.com.ua (c) Zaripov Yura <yur4ik7@ukr.net>
|
|||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background:#b7a68e url(./brown-papersq.png);
|
||||
background: #b7a68e url(./brown-papersq.png);
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-literal {
|
||||
color:#005599;
|
||||
font-weight:bold;
|
||||
color: #005599;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs,
|
||||
|
|
|
@ -45,8 +45,6 @@ Ported by Fabrício Tavares de Oliveira
|
|||
color: #88f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-title,
|
||||
|
|
|
@ -4,7 +4,6 @@ Darcula color scheme from the JetBrains family of IDEs
|
|||
|
||||
*/
|
||||
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
Please use darcula.css instead.
|
||||
*/
|
||||
|
||||
@import url('darcula.css');
|
||||
@import url("darcula.css");
|
||||
|
|
|
@ -8,10 +8,9 @@ Original highlight.js style (c) Ivan Sagalaev <maniac@softwaremaniacs.org>
|
|||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #F0F0F0;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
|
||||
/* Base color: saturation 0; */
|
||||
|
||||
.hljs,
|
||||
|
@ -32,7 +31,6 @@ Original highlight.js style (c) Ivan Sagalaev <maniac@softwaremaniacs.org>
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
/* User color: hue: 0 */
|
||||
|
||||
.hljs-type,
|
||||
|
@ -59,14 +57,13 @@ Original highlight.js style (c) Ivan Sagalaev <maniac@softwaremaniacs.org>
|
|||
.hljs-link,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo {
|
||||
color: #BC6060;
|
||||
color: #bc6060;
|
||||
}
|
||||
|
||||
|
||||
/* Language color: hue: 90; */
|
||||
|
||||
.hljs-literal {
|
||||
color: #78A960;
|
||||
color: #78a960;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
|
@ -76,7 +73,6 @@ Original highlight.js style (c) Ivan Sagalaev <maniac@softwaremaniacs.org>
|
|||
color: #397300;
|
||||
}
|
||||
|
||||
|
||||
/* Meta color: hue: 200 */
|
||||
|
||||
.hljs-meta {
|
||||
|
@ -87,7 +83,6 @@ Original highlight.js style (c) Ivan Sagalaev <maniac@softwaremaniacs.org>
|
|||
color: #4d99bf;
|
||||
}
|
||||
|
||||
|
||||
/* Misc effects */
|
||||
|
||||
.hljs-emphasis {
|
||||
|
|
|
@ -10,7 +10,8 @@ Date: 2013-04-02
|
|||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #eee; color: black;
|
||||
background: #eee;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.hljs-link,
|
||||
|
|
|
@ -68,7 +68,7 @@ Google Code style (c) Aahan Krish <geekpanth3r@gmail.com>
|
|||
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class {
|
||||
color: #9B703F
|
||||
color: #9b703f;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
|
|
|
@ -60,8 +60,8 @@ grayscale style (c) MY Sun <simonmysun@gmail.com>
|
|||
}
|
||||
|
||||
.hljs-regexp {
|
||||
color: #333;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAICAYAAADA+m62AAAAPUlEQVQYV2NkQAN37979r6yszIgujiIAU4RNMVwhuiQ6H6wQl3XI4oy4FMHcCJPHcDS6J2A2EqUQpJhohQDexSef15DBCwAAAABJRU5ErkJggg==) repeat;
|
||||
color: #333;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAICAYAAADA+m62AAAAPUlEQVQYV2NkQAN37979r6yszIgujiIAU4RNMVwhuiQ6H6wQl3XI4oy4FMHcCJPHcDS6J2A2EqUQpJhohQDexSef15DBCwAAAABJRU5ErkJggg==) repeat;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
|
@ -84,7 +84,7 @@ grayscale style (c) MY Sun <simonmysun@gmail.com>
|
|||
|
||||
.hljs-deletion {
|
||||
color: #fff;
|
||||
background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAADCAYAAABS3WWCAAAAE0lEQVQIW2MMDQ39zzhz5kwIAQAyxweWgUHd1AAAAABJRU5ErkJggg==) repeat;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAADCAYAAABS3WWCAAAAE0lEQVQIW2MMDQ39zzhz5kwIAQAyxweWgUHd1AAAAABJRU5ErkJggg==) repeat;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
|
|
|
@ -47,7 +47,7 @@ vim-hybrid theme by w0ng (https://github.com/w0ng/vim-hybrid)
|
|||
.hljs-literal,
|
||||
.hljs-deletion,
|
||||
.hljs-link {
|
||||
color: #cc6666
|
||||
color: #cc6666;
|
||||
}
|
||||
|
||||
/*color: fg_green*/
|
||||
|
@ -64,7 +64,7 @@ vim-hybrid theme by w0ng (https://github.com/w0ng/vim-hybrid)
|
|||
.hljs-attribute,
|
||||
.hljs-code,
|
||||
.hljs-selector-id {
|
||||
color: #b294bb;
|
||||
color: #b294bb;
|
||||
}
|
||||
|
||||
/*color: fg_blue*/
|
||||
|
@ -72,7 +72,7 @@ vim-hybrid theme by w0ng (https://github.com/w0ng/vim-hybrid)
|
|||
.hljs-selector-tag,
|
||||
.hljs-bullet,
|
||||
.hljs-tag {
|
||||
color: #81a2be;
|
||||
color: #81a2be;
|
||||
}
|
||||
|
||||
/*color: fg_aqua*/
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
|
||||
.hljs-number,
|
||||
.hljs-deletion {
|
||||
color:#ff73fd;
|
||||
color: #ff73fd;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
|
|
|
@ -6,7 +6,8 @@ Monokai style - ported by Luigi Maselli - http://grigio.org
|
|||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #272822; color: #ddd;
|
||||
background: #272822;
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
.hljs-tag,
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
}
|
||||
|
||||
.hljs-selector-class {
|
||||
color: #A082BD
|
||||
color: #a082bd;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
|
|
|
@ -21,12 +21,13 @@ NOTE_2: Color names provided in comments were derived using "Name that Color" on
|
|||
http://chir.ag/projects/name-that-color
|
||||
*/
|
||||
|
||||
.hljs { /* Common set of rules required by highlight.js (don'r remove!) */
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #FFFFDF; /* Half and Half (approx.) */
|
||||
/* --- Uncomment to add PureBASIC native IDE styled font!
|
||||
.hljs {
|
||||
/* Common set of rules required by highlight.js (don'r remove!) */
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #ffffdf; /* Half and Half (approx.) */
|
||||
/* --- Uncomment to add PureBASIC native IDE styled font!
|
||||
font-family: Consolas;
|
||||
*/
|
||||
}
|
||||
|
@ -39,7 +40,7 @@ NOTE_2: Color names provided in comments were derived using "Name that Color" on
|
|||
.hljs-attr,
|
||||
.hljs-params,
|
||||
.hljs-subst {
|
||||
color: #000000; /* Black */
|
||||
color: #000000; /* Black */
|
||||
}
|
||||
|
||||
.hljs-comment, /* --- used for PureBASIC Comments --- */
|
||||
|
@ -47,14 +48,14 @@ NOTE_2: Color names provided in comments were derived using "Name that Color" on
|
|||
.hljs-section,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-addition {
|
||||
color: #00AAAA; /* Persian Green (approx.) */
|
||||
color: #00aaaa; /* Persian Green (approx.) */
|
||||
}
|
||||
|
||||
.hljs-title, /* --- used for PureBASIC Procedures Names --- */
|
||||
.hljs-tag,
|
||||
.hljs-variable,
|
||||
.hljs-code {
|
||||
color: #006666; /* Blue Stone (approx.) */
|
||||
.hljs-code {
|
||||
color: #006666; /* Blue Stone (approx.) */
|
||||
}
|
||||
|
||||
.hljs-keyword, /* --- used for PureBASIC Keywords --- */
|
||||
|
@ -63,34 +64,34 @@ NOTE_2: Color names provided in comments were derived using "Name that Color" on
|
|||
.hljs-selector-class,
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name {
|
||||
color: #006666; /* Blue Stone (approx.) */
|
||||
font-weight: bold;
|
||||
color: #006666; /* Blue Stone (approx.) */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-string, /* --- used for PureBASIC Strings --- */
|
||||
.hljs-selector-attr {
|
||||
color: #0080FF; /* Azure Radiance (approx.) */
|
||||
color: #0080ff; /* Azure Radiance (approx.) */
|
||||
}
|
||||
|
||||
.hljs-symbol, /* --- used for PureBASIC Constants --- */
|
||||
.hljs-link,
|
||||
.hljs-deletion,
|
||||
.hljs-attribute {
|
||||
color: #924B72; /* Cannon Pink (approx.) */
|
||||
color: #924b72; /* Cannon Pink (approx.) */
|
||||
}
|
||||
|
||||
.hljs-meta,
|
||||
.hljs-literal,
|
||||
.hljs-selector-id {
|
||||
color: #924B72; /* Cannon Pink (approx.) */
|
||||
font-weight: bold;
|
||||
color: #924b72; /* Cannon Pink (approx.) */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-strong,
|
||||
.hljs-name {
|
||||
font-weight: bold;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
font-style: italic;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ Qt Creator dark color scheme
|
|||
|
||||
*/
|
||||
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
|
@ -32,8 +31,7 @@ Qt Creator dark color scheme
|
|||
color: #ff55ff;
|
||||
}
|
||||
|
||||
.hljs-code
|
||||
.hljs-selector-class {
|
||||
.hljs-code .hljs-selector-class {
|
||||
color: #aaaaff;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ Qt Creator light color scheme
|
|||
|
||||
*/
|
||||
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
|
@ -32,8 +31,7 @@ Qt Creator light color scheme
|
|||
color: #000080;
|
||||
}
|
||||
|
||||
.hljs-code
|
||||
.hljs-selector-class {
|
||||
.hljs-code .hljs-selector-class {
|
||||
color: #800080;
|
||||
}
|
||||
|
||||
|
@ -59,7 +57,7 @@ Qt Creator light color scheme
|
|||
.hljs-variable,
|
||||
.hljs-params,
|
||||
.hljs-class .hljs-title {
|
||||
color: #0055AF;
|
||||
color: #0055af;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
|
|
|
@ -44,7 +44,6 @@ Railscasts-like style (c) Visoft, Inc. (Damien White)
|
|||
color: #da4939;
|
||||
}
|
||||
|
||||
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-built_in,
|
||||
|
|
|
@ -12,7 +12,6 @@ Style with support for rainbow parens
|
|||
color: #d1d9e1;
|
||||
}
|
||||
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #969896;
|
||||
|
@ -50,7 +49,7 @@ Style with support for rainbow parens
|
|||
.hljs-template-variable,
|
||||
.hljs-selector-id,
|
||||
.hljs-class .hljs-title {
|
||||
color: #ffcc66;
|
||||
color: #ffcc66;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #F0F0F0;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
/* Base color: saturation 0; */
|
||||
|
@ -31,15 +31,15 @@
|
|||
}
|
||||
|
||||
.hljs-attribute {
|
||||
color: #0E9A00;
|
||||
}
|
||||
color: #0e9a00;
|
||||
}
|
||||
|
||||
.hljs-function {
|
||||
color: #99069A;
|
||||
color: #99069a;
|
||||
}
|
||||
|
||||
.hljs-builtin-name {
|
||||
color: #99069A;
|
||||
color: #99069a;
|
||||
}
|
||||
|
||||
/* User color: hue: 0 */
|
||||
|
@ -68,24 +68,22 @@
|
|||
.hljs-link,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo {
|
||||
color: #BC6060;
|
||||
color: #bc6060;
|
||||
}
|
||||
|
||||
|
||||
/* Language color: hue: 90; */
|
||||
|
||||
.hljs-literal {
|
||||
color: #78A960;
|
||||
color: #78a960;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-bullet,
|
||||
.hljs-code,
|
||||
.hljs-addition {
|
||||
color: #0C9A9A;
|
||||
color: #0c9a9a;
|
||||
}
|
||||
|
||||
|
||||
/* Meta color: hue: 200 */
|
||||
|
||||
.hljs-meta {
|
||||
|
@ -96,7 +94,6 @@
|
|||
color: #4d99bf;
|
||||
}
|
||||
|
||||
|
||||
/* Misc effects */
|
||||
|
||||
.hljs-emphasis {
|
||||
|
|
|
@ -9,11 +9,11 @@ School Book style from goldblog.com.ua (c) Zaripov Yura <yur4ik7@ukr.net>
|
|||
overflow-x: auto;
|
||||
padding: 15px 0.5em 0.5em 30px;
|
||||
font-size: 11px;
|
||||
line-height:16px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
pre{
|
||||
background:#f6f6ae url(./school-book.png);
|
||||
pre {
|
||||
background: #f6f6ae url(./school-book.png);
|
||||
border-top: solid 2px #d2e8b9;
|
||||
border-bottom: solid 1px #d2e8b9;
|
||||
}
|
||||
|
@ -21,8 +21,8 @@ pre{
|
|||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-literal {
|
||||
color:#005599;
|
||||
font-weight:bold;
|
||||
color: #005599;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs,
|
||||
|
|
|
@ -58,7 +58,6 @@ Visual Studio-like style based on original C# coloring by Jason Diamond <jason@d
|
|||
color: #00b0e8;
|
||||
}
|
||||
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
|
|
@ -7,39 +7,39 @@
|
|||
display: block;
|
||||
overflow-x: auto;
|
||||
padding: 0.5em;
|
||||
background: #1E1E1E;
|
||||
color: #DCDCDC;
|
||||
background: #1e1e1e;
|
||||
color: #dcdcdc;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-literal,
|
||||
.hljs-symbol,
|
||||
.hljs-name {
|
||||
color: #569CD6;
|
||||
color: #569cd6;
|
||||
}
|
||||
.hljs-link {
|
||||
color: #569CD6;
|
||||
color: #569cd6;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-type {
|
||||
color: #4EC9B0;
|
||||
color: #4ec9b0;
|
||||
}
|
||||
|
||||
.hljs-number,
|
||||
.hljs-class {
|
||||
color: #B8D7A3;
|
||||
color: #b8d7a3;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-meta-string {
|
||||
color: #D69D85;
|
||||
color: #d69d85;
|
||||
}
|
||||
|
||||
.hljs-regexp,
|
||||
.hljs-template-tag {
|
||||
color: #9A5334;
|
||||
color: #9a5334;
|
||||
}
|
||||
|
||||
.hljs-subst,
|
||||
|
@ -47,34 +47,34 @@
|
|||
.hljs-title,
|
||||
.hljs-params,
|
||||
.hljs-formula {
|
||||
color: #DCDCDC;
|
||||
color: #dcdcdc;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #57A64A;
|
||||
color: #57a64a;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-doctag {
|
||||
color: #608B4E;
|
||||
color: #608b4e;
|
||||
}
|
||||
|
||||
.hljs-meta,
|
||||
.hljs-meta-keyword,
|
||||
.hljs-tag {
|
||||
color: #9B9B9B;
|
||||
color: #9b9b9b;
|
||||
}
|
||||
|
||||
.hljs-variable,
|
||||
.hljs-template-variable {
|
||||
color: #BD63C5;
|
||||
color: #bd63c5;
|
||||
}
|
||||
|
||||
.hljs-attr,
|
||||
.hljs-attribute,
|
||||
.hljs-builtin-name {
|
||||
color: #9CDCFE;
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
.hljs-section {
|
||||
|
@ -99,7 +99,7 @@
|
|||
.hljs-selector-class,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo {
|
||||
color: #D7BA7D;
|
||||
color: #d7ba7d;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
/*
|
||||
xt256.css
|
||||
|
||||
|
|
|
@ -70,7 +70,6 @@ based on dark.css by Ivan Sagalaev
|
|||
color: #7f9f7f;
|
||||
}
|
||||
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
|
|
@ -18,18 +18,18 @@ export default defineComponent({
|
|||
code: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: ""
|
||||
default: "",
|
||||
},
|
||||
formatHtml: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
lang: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: ""
|
||||
}
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
setup(props: any, ctx: any) {
|
||||
const highlightHTMLRef: Ref = ref("");
|
||||
|
@ -42,7 +42,7 @@ export default defineComponent({
|
|||
doHighlight();
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -52,9 +52,9 @@ export default defineComponent({
|
|||
}
|
||||
return {
|
||||
highlightHTMLRef,
|
||||
doHighlight
|
||||
doHighlight,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -3,40 +3,40 @@
|
|||
// 功能
|
||||
// 将HTML字符串格式化
|
||||
|
||||
const format = (function() {
|
||||
const format = (function () {
|
||||
function style_html(html_source, indent_size, indent_character, max_char) {
|
||||
var Parser, multi_parser;
|
||||
function Parser() {
|
||||
this.pos = 0;
|
||||
this.token = '';
|
||||
this.current_mode = 'CONTENT';
|
||||
this.token = "";
|
||||
this.current_mode = "CONTENT";
|
||||
this.tags = {
|
||||
parent: 'parent1',
|
||||
parent: "parent1",
|
||||
parentcount: 1,
|
||||
parent1: ''
|
||||
parent1: "",
|
||||
};
|
||||
this.tag_type = '';
|
||||
this.token_text = this.last_token = this.last_text = this.token_type = '';
|
||||
this.tag_type = "";
|
||||
this.token_text = this.last_token = this.last_text = this.token_type = "";
|
||||
this.Utils = {
|
||||
whitespace: "\n\r\t ".split(''),
|
||||
single_token: 'br,input,link,meta,!doctype,basefont,base,area,hr,wbr,param,img,isindex,?xml,embed'.split(','),
|
||||
extra_liners: 'head,body,/html'.split(','),
|
||||
in_array: function(what, arr) {
|
||||
whitespace: "\n\r\t ".split(""),
|
||||
single_token: "br,input,link,meta,!doctype,basefont,base,area,hr,wbr,param,img,isindex,?xml,embed".split(","),
|
||||
extra_liners: "head,body,/html".split(","),
|
||||
in_array: function (what, arr) {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (what === arr[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this.get_content = function() {
|
||||
var char = '';
|
||||
},
|
||||
};
|
||||
this.get_content = function () {
|
||||
var char = "";
|
||||
var content = [];
|
||||
var space = false;
|
||||
while (this.input.charAt(this.pos) !== '<') {
|
||||
while (this.input.charAt(this.pos) !== "<") {
|
||||
if (this.pos >= this.input.length) {
|
||||
return content.length ? content.join('') : ['', 'TK_EOF'];
|
||||
return content.length ? content.join("") : ["", "TK_EOF"];
|
||||
}
|
||||
char = this.input.charAt(this.pos);
|
||||
this.pos++;
|
||||
|
@ -49,78 +49,78 @@ const format = (function() {
|
|||
continue;
|
||||
} else if (space) {
|
||||
if (this.line_char_count >= this.max_char) {
|
||||
content.push('\n');
|
||||
content.push("\n");
|
||||
for (var i = 0; i < this.indent_level; i++) {
|
||||
content.push(this.indent_string);
|
||||
}
|
||||
this.line_char_count = 0;
|
||||
} else {
|
||||
content.push(' ');
|
||||
content.push(" ");
|
||||
this.line_char_count++;
|
||||
}
|
||||
space = false;
|
||||
}
|
||||
content.push(char);
|
||||
}
|
||||
return content.length ? content.join('') : '';
|
||||
}
|
||||
this.get_script = function() {
|
||||
var char = '';
|
||||
return content.length ? content.join("") : "";
|
||||
};
|
||||
this.get_script = function () {
|
||||
var char = "";
|
||||
var content = [];
|
||||
var reg_match = new RegExp('\<\/script' + '\>', 'igm');
|
||||
var reg_match = new RegExp("</script" + ">", "igm");
|
||||
reg_match.lastIndex = this.pos;
|
||||
var reg_array = reg_match.exec(this.input);
|
||||
var end_script = reg_array ? reg_array.index: this.input.length;
|
||||
var end_script = reg_array ? reg_array.index : this.input.length;
|
||||
while (this.pos < end_script) {
|
||||
if (this.pos >= this.input.length) {
|
||||
return content.length ? content.join('') : ['', 'TK_EOF'];
|
||||
return content.length ? content.join("") : ["", "TK_EOF"];
|
||||
}
|
||||
char = this.input.charAt(this.pos);
|
||||
this.pos++;
|
||||
content.push(char);
|
||||
}
|
||||
return content.length ? content.join('') : '';
|
||||
}
|
||||
this.record_tag = function(tag) {
|
||||
if (this.tags[tag + 'count']) {
|
||||
this.tags[tag + 'count']++;
|
||||
this.tags[tag + this.tags[tag + 'count']] = this.indent_level;
|
||||
return content.length ? content.join("") : "";
|
||||
};
|
||||
this.record_tag = function (tag) {
|
||||
if (this.tags[tag + "count"]) {
|
||||
this.tags[tag + "count"]++;
|
||||
this.tags[tag + this.tags[tag + "count"]] = this.indent_level;
|
||||
} else {
|
||||
this.tags[tag + 'count'] = 1;
|
||||
this.tags[tag + this.tags[tag + 'count']] = this.indent_level;
|
||||
this.tags[tag + "count"] = 1;
|
||||
this.tags[tag + this.tags[tag + "count"]] = this.indent_level;
|
||||
}
|
||||
this.tags[tag + this.tags[tag + 'count'] + 'parent'] = this.tags.parent;
|
||||
this.tags.parent = tag + this.tags[tag + 'count'];
|
||||
}
|
||||
this.retrieve_tag = function(tag) {
|
||||
if (this.tags[tag + 'count']) {
|
||||
this.tags[tag + this.tags[tag + "count"] + "parent"] = this.tags.parent;
|
||||
this.tags.parent = tag + this.tags[tag + "count"];
|
||||
};
|
||||
this.retrieve_tag = function (tag) {
|
||||
if (this.tags[tag + "count"]) {
|
||||
var temp_parent = this.tags.parent;
|
||||
while (temp_parent) {
|
||||
if (tag + this.tags[tag + 'count'] === temp_parent) {
|
||||
if (tag + this.tags[tag + "count"] === temp_parent) {
|
||||
break;
|
||||
}
|
||||
temp_parent = this.tags[temp_parent + 'parent'];
|
||||
temp_parent = this.tags[temp_parent + "parent"];
|
||||
}
|
||||
if (temp_parent) {
|
||||
this.indent_level = this.tags[tag + this.tags[tag + 'count']];
|
||||
this.tags.parent = this.tags[temp_parent + 'parent'];
|
||||
this.indent_level = this.tags[tag + this.tags[tag + "count"]];
|
||||
this.tags.parent = this.tags[temp_parent + "parent"];
|
||||
}
|
||||
delete this.tags[tag + this.tags[tag + 'count'] + 'parent'];
|
||||
delete this.tags[tag + this.tags[tag + 'count']];
|
||||
if (this.tags[tag + 'count'] == 1) {
|
||||
delete this.tags[tag + 'count'];
|
||||
delete this.tags[tag + this.tags[tag + "count"] + "parent"];
|
||||
delete this.tags[tag + this.tags[tag + "count"]];
|
||||
if (this.tags[tag + "count"] == 1) {
|
||||
delete this.tags[tag + "count"];
|
||||
} else {
|
||||
this.tags[tag + 'count']--;
|
||||
this.tags[tag + "count"]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.get_tag = function() {
|
||||
var char = '';
|
||||
};
|
||||
this.get_tag = function () {
|
||||
var char = "";
|
||||
var content = [];
|
||||
var space = false;
|
||||
do {
|
||||
if (this.pos >= this.input.length) {
|
||||
return content.length ? content.join('') : ['', 'TK_EOF'];
|
||||
return content.length ? content.join("") : ["", "TK_EOF"];
|
||||
}
|
||||
char = this.input.charAt(this.pos);
|
||||
this.pos++;
|
||||
|
@ -131,92 +131,92 @@ const format = (function() {
|
|||
continue;
|
||||
}
|
||||
if (char === "'" || char === '"') {
|
||||
if (!content[1] || content[1] !== '!') {
|
||||
if (!content[1] || content[1] !== "!") {
|
||||
char += this.get_unformatted(char);
|
||||
space = true;
|
||||
}
|
||||
}
|
||||
if (char === '=') {
|
||||
if (char === "=") {
|
||||
space = false;
|
||||
}
|
||||
if (content.length && content[content.length - 1] !== '=' && char !== '>' && space) {
|
||||
if (content.length && content[content.length - 1] !== "=" && char !== ">" && space) {
|
||||
if (this.line_char_count >= this.max_char) {
|
||||
this.print_newline(false, content);
|
||||
this.line_char_count = 0;
|
||||
} else {
|
||||
content.push(' ');
|
||||
content.push(" ");
|
||||
this.line_char_count++;
|
||||
}
|
||||
space = false;
|
||||
}
|
||||
content.push(char);
|
||||
} while ( char !== '>');
|
||||
var tag_complete = content.join('');
|
||||
} while (char !== ">");
|
||||
var tag_complete = content.join("");
|
||||
var tag_index;
|
||||
if (tag_complete.indexOf(' ') != -1) {
|
||||
tag_index = tag_complete.indexOf(' ');
|
||||
if (tag_complete.indexOf(" ") != -1) {
|
||||
tag_index = tag_complete.indexOf(" ");
|
||||
} else {
|
||||
tag_index = tag_complete.indexOf('>');
|
||||
tag_index = tag_complete.indexOf(">");
|
||||
}
|
||||
var tag_check = tag_complete.substring(1, tag_index).toLowerCase();
|
||||
if (tag_complete.charAt(tag_complete.length - 2) === '/' || this.Utils.in_array(tag_check, this.Utils.single_token)) {
|
||||
this.tag_type = 'SINGLE';
|
||||
} else if (tag_check === 'script') {
|
||||
if (tag_complete.charAt(tag_complete.length - 2) === "/" || this.Utils.in_array(tag_check, this.Utils.single_token)) {
|
||||
this.tag_type = "SINGLE";
|
||||
} else if (tag_check === "script") {
|
||||
this.record_tag(tag_check);
|
||||
this.tag_type = 'SCRIPT';
|
||||
} else if (tag_check === 'style') {
|
||||
this.tag_type = "SCRIPT";
|
||||
} else if (tag_check === "style") {
|
||||
this.record_tag(tag_check);
|
||||
this.tag_type = 'STYLE';
|
||||
} else if (tag_check.charAt(0) === '!') {
|
||||
if (tag_check.indexOf('[if') != -1) {
|
||||
if (tag_complete.indexOf('!IE') != -1) {
|
||||
var comment = this.get_unformatted('-->', tag_complete);
|
||||
this.tag_type = "STYLE";
|
||||
} else if (tag_check.charAt(0) === "!") {
|
||||
if (tag_check.indexOf("[if") != -1) {
|
||||
if (tag_complete.indexOf("!IE") != -1) {
|
||||
var comment = this.get_unformatted("-->", tag_complete);
|
||||
content.push(comment);
|
||||
}
|
||||
this.tag_type = 'START';
|
||||
} else if (tag_check.indexOf('[endif') != -1) {
|
||||
this.tag_type = 'END';
|
||||
this.tag_type = "START";
|
||||
} else if (tag_check.indexOf("[endif") != -1) {
|
||||
this.tag_type = "END";
|
||||
this.unindent();
|
||||
} else if (tag_check.indexOf('[cdata[') != -1) {
|
||||
var comment = this.get_unformatted(']]>', tag_complete);
|
||||
} else if (tag_check.indexOf("[cdata[") != -1) {
|
||||
var comment = this.get_unformatted("]]>", tag_complete);
|
||||
content.push(comment);
|
||||
this.tag_type = 'SINGLE';
|
||||
this.tag_type = "SINGLE";
|
||||
} else {
|
||||
var comment = this.get_unformatted('-->', tag_complete);
|
||||
var comment = this.get_unformatted("-->", tag_complete);
|
||||
content.push(comment);
|
||||
this.tag_type = 'SINGLE';
|
||||
this.tag_type = "SINGLE";
|
||||
}
|
||||
} else {
|
||||
if (tag_check.charAt(0) === '/') {
|
||||
if (tag_check.charAt(0) === "/") {
|
||||
this.retrieve_tag(tag_check.substring(1));
|
||||
this.tag_type = 'END';
|
||||
this.tag_type = "END";
|
||||
} else {
|
||||
this.record_tag(tag_check);
|
||||
this.tag_type = 'START';
|
||||
this.tag_type = "START";
|
||||
}
|
||||
if (this.Utils.in_array(tag_check, this.Utils.extra_liners)) {
|
||||
this.print_newline(true, this.output);
|
||||
}
|
||||
}
|
||||
return content.join('');
|
||||
}
|
||||
this.get_unformatted = function(delimiter, orig_tag) {
|
||||
return content.join("");
|
||||
};
|
||||
this.get_unformatted = function (delimiter, orig_tag) {
|
||||
if (orig_tag && orig_tag.indexOf(delimiter) != -1) {
|
||||
return '';
|
||||
return "";
|
||||
}
|
||||
var char = '';
|
||||
var content = '';
|
||||
var char = "";
|
||||
var content = "";
|
||||
var space = true;
|
||||
do {
|
||||
char = this.input.charAt(this.pos);
|
||||
this.pos++
|
||||
this.pos++;
|
||||
if (this.Utils.in_array(char, this.Utils.whitespace)) {
|
||||
if (!space) {
|
||||
this.line_char_count--;
|
||||
continue;
|
||||
}
|
||||
if (char === '\n' || char === '\r') {
|
||||
content += '\n';
|
||||
if (char === "\n" || char === "\r") {
|
||||
content += "\n";
|
||||
for (var i = 0; i < this.indent_level; i++) {
|
||||
content += this.indent_string;
|
||||
}
|
||||
|
@ -228,44 +228,43 @@ const format = (function() {
|
|||
content += char;
|
||||
this.line_char_count++;
|
||||
space = true;
|
||||
|
||||
} while ( content . indexOf ( delimiter ) == -1);
|
||||
} while (content.indexOf(delimiter) == -1);
|
||||
return content;
|
||||
}
|
||||
this.get_token = function() {
|
||||
};
|
||||
this.get_token = function () {
|
||||
var token;
|
||||
if (this.last_token === 'TK_TAG_SCRIPT') {
|
||||
if (this.last_token === "TK_TAG_SCRIPT") {
|
||||
var temp_token = this.get_script();
|
||||
if (typeof temp_token !== 'string') {
|
||||
if (typeof temp_token !== "string") {
|
||||
return temp_token;
|
||||
}
|
||||
//token = js_beautify(temp_token, this.indent_size, this.indent_character, this.indent_level);
|
||||
//return [token, 'TK_CONTENT'];
|
||||
return [temp_token, 'TK_CONTENT'];
|
||||
return [temp_token, "TK_CONTENT"];
|
||||
}
|
||||
if (this.current_mode === 'CONTENT') {
|
||||
if (this.current_mode === "CONTENT") {
|
||||
token = this.get_content();
|
||||
if (typeof token !== 'string') {
|
||||
if (typeof token !== "string") {
|
||||
return token;
|
||||
} else {
|
||||
return [token, 'TK_CONTENT'];
|
||||
return [token, "TK_CONTENT"];
|
||||
}
|
||||
}
|
||||
if (this.current_mode === 'TAG') {
|
||||
if (this.current_mode === "TAG") {
|
||||
token = this.get_tag();
|
||||
if (typeof token !== 'string') {
|
||||
if (typeof token !== "string") {
|
||||
return token;
|
||||
} else {
|
||||
var tag_name_type = 'TK_TAG_' + this.tag_type;
|
||||
var tag_name_type = "TK_TAG_" + this.tag_type;
|
||||
return [token, tag_name_type];
|
||||
}
|
||||
}
|
||||
}
|
||||
this.printer = function(js_source, indent_character, indent_size, max_char) {
|
||||
this.input = js_source || '';
|
||||
};
|
||||
this.printer = function (js_source, indent_character, indent_size, max_char) {
|
||||
this.input = js_source || "";
|
||||
this.output = [];
|
||||
this.indent_character = indent_character || ' ';
|
||||
this.indent_string = '';
|
||||
this.indent_character = indent_character || " ";
|
||||
this.indent_string = "";
|
||||
this.indent_size = indent_size || 2;
|
||||
this.indent_level = 0;
|
||||
this.max_char = max_char || 70;
|
||||
|
@ -273,7 +272,7 @@ const format = (function() {
|
|||
for (var i = 0; i < this.indent_size; i++) {
|
||||
this.indent_string += this.indent_character;
|
||||
}
|
||||
this.print_newline = function(ignore, arr) {
|
||||
this.print_newline = function (ignore, arr) {
|
||||
this.line_char_count = 0;
|
||||
if (!arr || !arr.length) {
|
||||
return;
|
||||
|
@ -283,23 +282,23 @@ const format = (function() {
|
|||
arr.pop();
|
||||
}
|
||||
}
|
||||
arr.push('\n');
|
||||
arr.push("\n");
|
||||
for (var i = 0; i < this.indent_level; i++) {
|
||||
arr.push(this.indent_string);
|
||||
}
|
||||
}
|
||||
this.print_token = function(text) {
|
||||
};
|
||||
this.print_token = function (text) {
|
||||
this.output.push(text);
|
||||
}
|
||||
this.indent = function() {
|
||||
};
|
||||
this.indent = function () {
|
||||
this.indent_level++;
|
||||
}
|
||||
this.unindent = function() {
|
||||
};
|
||||
this.unindent = function () {
|
||||
if (this.indent_level > 0) {
|
||||
this.indent_level--;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
return this;
|
||||
}
|
||||
multi_parser = new Parser();
|
||||
|
@ -308,58 +307,56 @@ const format = (function() {
|
|||
var t = multi_parser.get_token();
|
||||
multi_parser.token_text = t[0];
|
||||
multi_parser.token_type = t[1];
|
||||
if (multi_parser.token_type === 'TK_EOF') {
|
||||
if (multi_parser.token_type === "TK_EOF") {
|
||||
break;
|
||||
}
|
||||
switch (multi_parser.token_type) {
|
||||
case 'TK_TAG_START':
|
||||
case 'TK_TAG_SCRIPT':
|
||||
case 'TK_TAG_STYLE':
|
||||
multi_parser.print_newline(false, multi_parser.output);
|
||||
multi_parser.print_token(multi_parser.token_text);
|
||||
multi_parser.indent();
|
||||
multi_parser.current_mode = 'CONTENT';
|
||||
break;
|
||||
case 'TK_TAG_END':
|
||||
multi_parser.print_newline(true, multi_parser.output);
|
||||
multi_parser.print_token(multi_parser.token_text);
|
||||
multi_parser.current_mode = 'CONTENT';
|
||||
break;
|
||||
case 'TK_TAG_SINGLE':
|
||||
multi_parser.print_newline(false, multi_parser.output);
|
||||
multi_parser.print_token(multi_parser.token_text);
|
||||
multi_parser.current_mode = 'CONTENT';
|
||||
break;
|
||||
case 'TK_CONTENT':
|
||||
if (multi_parser.token_text !== '') {
|
||||
case "TK_TAG_START":
|
||||
case "TK_TAG_SCRIPT":
|
||||
case "TK_TAG_STYLE":
|
||||
multi_parser.print_newline(false, multi_parser.output);
|
||||
multi_parser.print_token(multi_parser.token_text);
|
||||
}
|
||||
multi_parser.current_mode = 'TAG';
|
||||
break;
|
||||
multi_parser.indent();
|
||||
multi_parser.current_mode = "CONTENT";
|
||||
break;
|
||||
case "TK_TAG_END":
|
||||
multi_parser.print_newline(true, multi_parser.output);
|
||||
multi_parser.print_token(multi_parser.token_text);
|
||||
multi_parser.current_mode = "CONTENT";
|
||||
break;
|
||||
case "TK_TAG_SINGLE":
|
||||
multi_parser.print_newline(false, multi_parser.output);
|
||||
multi_parser.print_token(multi_parser.token_text);
|
||||
multi_parser.current_mode = "CONTENT";
|
||||
break;
|
||||
case "TK_CONTENT":
|
||||
if (multi_parser.token_text !== "") {
|
||||
multi_parser.print_newline(false, multi_parser.output);
|
||||
multi_parser.print_token(multi_parser.token_text);
|
||||
}
|
||||
multi_parser.current_mode = "TAG";
|
||||
break;
|
||||
}
|
||||
multi_parser.last_token = multi_parser.token_type;
|
||||
multi_parser.last_text = multi_parser.token_text;
|
||||
}
|
||||
return multi_parser.output.join('');
|
||||
return multi_parser.output.join("");
|
||||
}
|
||||
return function(data) {
|
||||
var dataHolder = ['__dataHolder_', [Math.random(), Math.random(), Math.random(), Math.random()].join('_').replace(/[^0-9]/g, '_'), '_'].join('_');
|
||||
return function (data) {
|
||||
var dataHolder = ["__dataHolder_", [Math.random(), Math.random(), Math.random(), Math.random()].join("_").replace(/[^0-9]/g, "_"), "_"].join("_");
|
||||
var dataHolders = {};
|
||||
var index = 0;
|
||||
data = data.replace(/(\")(data:[^\"]*)(\")/g,
|
||||
function($0, $1, $2, $3) {
|
||||
data = data.replace(/(\")(data:[^\"]*)(\")/g, function ($0, $1, $2, $3) {
|
||||
var name = dataHolder + index++;
|
||||
dataHolders[name] = $2;
|
||||
return $1 + name + $3;
|
||||
})
|
||||
data = style_html(data, 2, ' ', 0x10000000);
|
||||
data = data.replace(new RegExp(dataHolder + '[0-9]+', 'g'),
|
||||
function($0) {
|
||||
});
|
||||
data = style_html(data, 2, " ", 0x10000000);
|
||||
data = data.replace(new RegExp(dataHolder + "[0-9]+", "g"), function ($0) {
|
||||
return dataHolders[$0];
|
||||
});
|
||||
return data;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
export default format
|
||||
export default format;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<a-select>
|
||||
<a-select-option v-for="item of options" :keu="item.value" :value="item.value" :label="item.label">
|
||||
<a-select-option v-for="item of options" :key="item.value" :value="item.value" :label="item.label">
|
||||
<span class="flex-o">
|
||||
<fs-icon :icon="item.icon" class="fs-16 color-blue mr-5" />
|
||||
{{ item.label }}
|
||||
|
|
|
@ -10,12 +10,12 @@ export default {
|
|||
props: {
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: undefined
|
||||
default: undefined,
|
||||
},
|
||||
// eslint-disable-next-line vue/require-default-prop
|
||||
from: {
|
||||
type: [String, Array]
|
||||
}
|
||||
type: [String, Array],
|
||||
},
|
||||
},
|
||||
emits: ["update:modelValue"],
|
||||
setup(props: any, ctx: any) {
|
||||
|
@ -35,7 +35,7 @@ export default {
|
|||
currentStageIndex: currentStageIndex.value,
|
||||
currentTaskIndex: currentTaskIndex.value,
|
||||
currentStepIndex: currentStepIndex.value,
|
||||
currentTask: currentTask.value
|
||||
currentTask: currentTask.value,
|
||||
});
|
||||
if (props.from) {
|
||||
if (typeof props.from === "string") {
|
||||
|
@ -73,9 +73,9 @@ export default {
|
|||
}
|
||||
return {
|
||||
options,
|
||||
onChanged
|
||||
onChanged,
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
import { ref } from "vue";
|
||||
import TutorialSteps from "/@/components/tutorial/tutorial-steps.vue";
|
||||
|
||||
defineOptions({
|
||||
name: "TutorialModal",
|
||||
});
|
||||
|
||||
const props = defineProps<{
|
||||
showIcon?: boolean;
|
||||
}>();
|
||||
|
@ -16,23 +20,18 @@ const slots = defineSlots();
|
|||
<template>
|
||||
<div class="tutorial-button pointer" @click="open">
|
||||
<template v-if="!slots.default">
|
||||
<fs-icon
|
||||
v-if="showIcon === false"
|
||||
icon="ant-design:question-circle-outlined"
|
||||
class="mr-0.5"
|
||||
></fs-icon>
|
||||
<div class="hidden md:block">{{$t('tutorial.title')}}</div>
|
||||
<fs-icon v-if="showIcon === false" icon="ant-design:question-circle-outlined" class="mr-0.5"></fs-icon>
|
||||
<div class="hidden md:block">{{ $t("tutorial.title") }}</div>
|
||||
</template>
|
||||
<slot></slot>
|
||||
<a-modal v-model:open="openedRef" class="tutorial-modal" width="90%">
|
||||
<template #title>{{$t('tutorial.title')}}</template>
|
||||
<template #title>{{ $t("tutorial.title") }}</template>
|
||||
<tutorial-steps v-if="openedRef" />
|
||||
<template #footer></template>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<style lang="less">
|
||||
.tutorial-modal {
|
||||
top: 50px;
|
||||
|
|
|
@ -15,11 +15,7 @@ type Step = {
|
|||
|
||||
import { ref } from "vue";
|
||||
|
||||
const steps = ref<Step[]>([
|
||||
{ title: t('certd.steps.createPipeline') },
|
||||
{ title: t('certd.steps.addTask') },
|
||||
{ title: t('certd.steps.scheduledRun') }
|
||||
]);
|
||||
const steps = ref<Step[]>([{ title: t("certd.steps.createPipeline") }, { title: t("certd.steps.addTask") }, { title: t("certd.steps.scheduledRun") }]);
|
||||
|
||||
const router = useRouter();
|
||||
function goPipeline() {
|
||||
|
|
|
@ -20,10 +20,9 @@
|
|||
</div>
|
||||
|
||||
<div class="flex-center actions">
|
||||
<fs-button class="m-10" icon="ion:arrow-back-outline" @click="prev()">{{ t('guide.buttons.prev') }}</fs-button>
|
||||
<fs-button class="m-10" type="primary" icon-right="ion:arrow-forward-outline" @click="next()">{{ t('guide.buttons.next') }}</fs-button>
|
||||
<fs-button class="m-10" icon="ion:arrow-back-outline" @click="prev()">{{ t("guide.buttons.prev") }}</fs-button>
|
||||
<fs-button class="m-10" type="primary" icon-right="ion:arrow-forward-outline" @click="next()">{{ t("guide.buttons.next") }}</fs-button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -49,16 +48,13 @@ type StepItems = {
|
|||
import { computed, nextTick, ref } from "vue";
|
||||
|
||||
const steps = ref<Step[]>([
|
||||
{
|
||||
{
|
||||
title: t("guide.createCertPipeline.title"),
|
||||
description: t("guide.createCertPipeline.description"),
|
||||
items: [
|
||||
{
|
||||
title: t("guide.createCertPipeline.items.tutorialTitle"),
|
||||
descriptions: [
|
||||
t("guide.createCertPipeline.items.tutorialDesc1"),
|
||||
t("guide.createCertPipeline.items.tutorialDesc2"),
|
||||
],
|
||||
descriptions: [t("guide.createCertPipeline.items.tutorialDesc1"), t("guide.createCertPipeline.items.tutorialDesc2")],
|
||||
body: () => {
|
||||
return <SimpleSteps></SimpleSteps>;
|
||||
},
|
||||
|
@ -86,26 +82,17 @@ const steps = ref<Step[]>([
|
|||
{
|
||||
image: "/static/doc/images/5-1-add-host.png",
|
||||
title: t("guide.addDeployTask.items.addTaskTitle"),
|
||||
descriptions: [
|
||||
t("guide.addDeployTask.items.addTaskDesc1"),
|
||||
t("guide.addDeployTask.items.addTaskDesc2"),
|
||||
],
|
||||
descriptions: [t("guide.addDeployTask.items.addTaskDesc1"), t("guide.addDeployTask.items.addTaskDesc2")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/5-2-add-host.png",
|
||||
title: t("guide.addDeployTask.items.fillParamsTitle"),
|
||||
descriptions: [
|
||||
t("guide.addDeployTask.items.fillParamsDesc1"),
|
||||
t("guide.addDeployTask.items.fillParamsDesc2"),
|
||||
],
|
||||
descriptions: [t("guide.addDeployTask.items.fillParamsDesc1"), t("guide.addDeployTask.items.fillParamsDesc2")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/5-3-add-host.png",
|
||||
title: t("guide.addDeployTask.items.activateCertTitle"),
|
||||
descriptions: [
|
||||
t("guide.addDeployTask.items.activateCertDesc1"),
|
||||
t("guide.addDeployTask.items.activateCertDesc2"),
|
||||
],
|
||||
descriptions: [t("guide.addDeployTask.items.activateCertDesc1"), t("guide.addDeployTask.items.activateCertDesc2")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/5-4-add-host.png",
|
||||
|
@ -119,81 +106,72 @@ const steps = ref<Step[]>([
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: t('guide.runAndTestTask.runAndTestTitle'),
|
||||
description: t('guide.runAndTestTask.runAndTestDescription'),
|
||||
items: [
|
||||
{
|
||||
image: "/static/doc/images/9-start.png",
|
||||
title: t('guide.runAndTestTask.runTestOnce'),
|
||||
descriptions: [t('guide.runAndTestTask.clickManualTriggerToTest')],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/10-1-log.png",
|
||||
title: t('guide.runAndTestTask.viewLogs'),
|
||||
descriptions: [t('guide.runAndTestTask.clickTaskToViewStatusAndLogs')],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/11-1-error.png",
|
||||
title: t('guide.runAndTestTask.howToTroubleshootFailure'),
|
||||
descriptions: [t('guide.runAndTestTask.viewErrorLogs')],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/11-2-error.png",
|
||||
title: t('guide.runAndTestTask.howToTroubleshootFailure'),
|
||||
descriptions: [
|
||||
t('guide.runAndTestTask.viewErrorLogs'),
|
||||
t('guide.runAndTestTask.nginxContainerNotExistFix'),
|
||||
],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/12-1-log-success.png",
|
||||
title: t('guide.runAndTestTask.executionSuccess'),
|
||||
descriptions: [t('guide.runAndTestTask.retryAfterFix')],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/12-2-skip-log.png",
|
||||
title: t('guide.runAndTestTask.autoSkipAfterSuccess'),
|
||||
descriptions: [t('guide.runAndTestTask.successSkipExplanation')],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/13-1-result.png",
|
||||
title: t('guide.runAndTestTask.viewCertDeploymentSuccess'),
|
||||
descriptions: [t('guide.runAndTestTask.visitNginxToSeeCert')],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/13-3-download.png",
|
||||
title: t('guide.runAndTestTask.downloadCertManualDeploy'),
|
||||
descriptions: [t('guide.runAndTestTask.downloadIfNoAutoDeployPlugin')],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: t('guide.scheduleAndEmailTask.title'),
|
||||
description: t('guide.scheduleAndEmailTask.description'),
|
||||
items: [
|
||||
{
|
||||
image: "/static/doc/images/14-timer.png",
|
||||
title: t('guide.scheduleAndEmailTask.setSchedule'),
|
||||
descriptions: [
|
||||
t('guide.scheduleAndEmailTask.pipelineSuccessThenSchedule'),
|
||||
t('guide.scheduleAndEmailTask.recommendDailyRun'),
|
||||
],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/15-1-email.png",
|
||||
title: t('guide.scheduleAndEmailTask.setEmailNotification'),
|
||||
descriptions: [
|
||||
t('guide.scheduleAndEmailTask.suggestErrorAndRecoveryEmails'),
|
||||
t('guide.scheduleAndEmailTask.basicVersionNeedsMailServer'),
|
||||
],
|
||||
},
|
||||
{
|
||||
title: t('guide.scheduleAndEmailTask.tutorialEndTitle'),
|
||||
descriptions: [t('guide.scheduleAndEmailTask.thanksForWatching')],
|
||||
},
|
||||
],
|
||||
}
|
||||
{
|
||||
title: t("guide.runAndTestTask.runAndTestTitle"),
|
||||
description: t("guide.runAndTestTask.runAndTestDescription"),
|
||||
items: [
|
||||
{
|
||||
image: "/static/doc/images/9-start.png",
|
||||
title: t("guide.runAndTestTask.runTestOnce"),
|
||||
descriptions: [t("guide.runAndTestTask.clickManualTriggerToTest")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/10-1-log.png",
|
||||
title: t("guide.runAndTestTask.viewLogs"),
|
||||
descriptions: [t("guide.runAndTestTask.clickTaskToViewStatusAndLogs")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/11-1-error.png",
|
||||
title: t("guide.runAndTestTask.howToTroubleshootFailure"),
|
||||
descriptions: [t("guide.runAndTestTask.viewErrorLogs")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/11-2-error.png",
|
||||
title: t("guide.runAndTestTask.howToTroubleshootFailure"),
|
||||
descriptions: [t("guide.runAndTestTask.viewErrorLogs"), t("guide.runAndTestTask.nginxContainerNotExistFix")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/12-1-log-success.png",
|
||||
title: t("guide.runAndTestTask.executionSuccess"),
|
||||
descriptions: [t("guide.runAndTestTask.retryAfterFix")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/12-2-skip-log.png",
|
||||
title: t("guide.runAndTestTask.autoSkipAfterSuccess"),
|
||||
descriptions: [t("guide.runAndTestTask.successSkipExplanation")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/13-1-result.png",
|
||||
title: t("guide.runAndTestTask.viewCertDeploymentSuccess"),
|
||||
descriptions: [t("guide.runAndTestTask.visitNginxToSeeCert")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/13-3-download.png",
|
||||
title: t("guide.runAndTestTask.downloadCertManualDeploy"),
|
||||
descriptions: [t("guide.runAndTestTask.downloadIfNoAutoDeployPlugin")],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: t("guide.scheduleAndEmailTask.title"),
|
||||
description: t("guide.scheduleAndEmailTask.description"),
|
||||
items: [
|
||||
{
|
||||
image: "/static/doc/images/14-timer.png",
|
||||
title: t("guide.scheduleAndEmailTask.setSchedule"),
|
||||
descriptions: [t("guide.scheduleAndEmailTask.pipelineSuccessThenSchedule"), t("guide.scheduleAndEmailTask.recommendDailyRun")],
|
||||
},
|
||||
{
|
||||
image: "/static/doc/images/15-1-email.png",
|
||||
title: t("guide.scheduleAndEmailTask.setEmailNotification"),
|
||||
descriptions: [t("guide.scheduleAndEmailTask.suggestErrorAndRecoveryEmails"), t("guide.scheduleAndEmailTask.basicVersionNeedsMailServer")],
|
||||
},
|
||||
{
|
||||
title: t("guide.scheduleAndEmailTask.tutorialEndTitle"),
|
||||
descriptions: [t("guide.scheduleAndEmailTask.thanksForWatching")],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const current = ref(0);
|
||||
|
|
|
@ -10,7 +10,7 @@ export default {
|
|||
function checkPlus() {
|
||||
// 事件处理代码
|
||||
notification.warn({
|
||||
message: "此为专业版功能,请升级到专业版"
|
||||
message: "此为专业版功能,请升级到专业版",
|
||||
});
|
||||
}
|
||||
el.addEventListener("click", function (event: any) {
|
||||
|
@ -20,5 +20,5 @@ export default {
|
|||
checkPlus();
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<template>
|
||||
<div v-if="!settingStore.isComm || userStore.isAdmin" class="layout-vip isPlus" @click="openUpgrade">
|
||||
<contextHolder />
|
||||
<fs-icon icon="mingcute:vip-1-line" :title="text.title" />
|
||||
<div v-if="!settingStore.isComm || userStore.isAdmin" class="layout-vip isPlus" @click="openUpgrade">
|
||||
<contextHolder />
|
||||
<fs-icon icon="mingcute:vip-1-line" :title="text.title" />
|
||||
|
||||
<div v-if="mode !== 'icon'" class="text hidden md:block ml-0.5">
|
||||
<a-tooltip>
|
||||
<template #title> {{ text.title }}</template>
|
||||
<span class="">{{ text.name }}</span>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="mode !== 'icon'" class="text hidden md:block ml-0.5">
|
||||
<a-tooltip>
|
||||
<template #title> {{ text.title }}</template>
|
||||
<span class="">{{ text.name }}</span>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="tsx" setup>
|
||||
import { computed, onMounted, reactive } from "vue";
|
||||
|
@ -104,7 +104,6 @@ const text = computed<Text>(() => {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
const expireTime = computed(() => {
|
||||
if (settingStore.isPlus) {
|
||||
return dayjs(settingStore.plusInfo.expireTime).format("YYYY-MM-DD");
|
||||
|
@ -157,7 +156,6 @@ async function doActive() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
const computedSiteId = computed(() => settingStore.installInfo?.siteId);
|
||||
const [modal, contextHolder] = Modal.useModal();
|
||||
const userStore = useUserStore();
|
||||
|
@ -169,17 +167,16 @@ function goAccount() {
|
|||
|
||||
async function getVipTrial() {
|
||||
const res = await api.getVipTrial();
|
||||
message.success(t('vip.congratulations_vip_trial', { duration: res.duration }));
|
||||
message.success(t("vip.congratulations_vip_trial", { duration: res.duration }));
|
||||
await settingStore.init();
|
||||
}
|
||||
|
||||
|
||||
function openTrialModal() {
|
||||
Modal.destroyAll();
|
||||
|
||||
modal.confirm({
|
||||
title: t('vip.trial_modal_title'),
|
||||
okText: t('vip.trial_modal_ok_text'),
|
||||
title: t("vip.trial_modal_title"),
|
||||
okText: t("vip.trial_modal_ok_text"),
|
||||
onOk() {
|
||||
getVipTrial();
|
||||
},
|
||||
|
@ -187,15 +184,14 @@ function openTrialModal() {
|
|||
content: () => {
|
||||
return (
|
||||
<div class="flex-col mt-10 mb-10">
|
||||
<div>{t('vip.trial_modal_thanks')}</div>
|
||||
<div>{t('vip.trial_modal_click_confirm')}</div>
|
||||
<div>{t("vip.trial_modal_thanks")}</div>
|
||||
<div>{t("vip.trial_modal_click_confirm")}</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function openStarModal() {
|
||||
Modal.destroyAll();
|
||||
const goGithub = () => {
|
||||
|
@ -221,207 +217,176 @@ function openStarModal() {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
function openUpgrade() {
|
||||
if (!userStore.isAdmin) {
|
||||
message.info(t("vip.admin_only_operation"));
|
||||
return;
|
||||
}
|
||||
const placeholder = t("vip.enter_activation_code");
|
||||
const isPlus = settingStore.isPlus;
|
||||
let title = t("vip.activate_pro_business");
|
||||
if (settingStore.isComm) {
|
||||
title = t("vip.renew_business");
|
||||
} else if (settingStore.isPlus) {
|
||||
title = t("vip.renew_pro_upgrade_business");
|
||||
}
|
||||
if (!userStore.isAdmin) {
|
||||
message.info(t("vip.admin_only_operation"));
|
||||
return;
|
||||
}
|
||||
const placeholder = t("vip.enter_activation_code");
|
||||
const isPlus = settingStore.isPlus;
|
||||
let title = t("vip.activate_pro_business");
|
||||
if (settingStore.isComm) {
|
||||
title = t("vip.renew_business");
|
||||
} else if (settingStore.isPlus) {
|
||||
title = t("vip.renew_pro_upgrade_business");
|
||||
}
|
||||
|
||||
|
||||
const productInfo = settingStore.productInfo;
|
||||
const vipTypeDefine = {
|
||||
free: {
|
||||
title: t("vip.basic_edition"),
|
||||
desc: t("vip.community_free_version"),
|
||||
type: "free",
|
||||
icon: "lucide:package-open",
|
||||
privilege: [
|
||||
t("vip.unlimited_certificate_application"),
|
||||
t("vip.unlimited_domain_count"),
|
||||
t("vip.unlimited_certificate_pipelines"),
|
||||
t("vip.common_deployment_plugins"),
|
||||
t("vip.email_webhook_notifications"),
|
||||
],
|
||||
},
|
||||
plus: {
|
||||
title: t("vip.professional_edition"),
|
||||
desc: t("vip.open_source_support"),
|
||||
type: "plus",
|
||||
privilege: [
|
||||
t("vip.vip_group_priority"),
|
||||
t("vip.unlimited_site_certificate_monitoring"),
|
||||
t("vip.more_notification_methods"),
|
||||
t("vip.plugins_fully_open"),
|
||||
],
|
||||
trial: {
|
||||
title: t("vip.click_to_get_7_day_trial"),
|
||||
click: () => {
|
||||
openStarModal();
|
||||
const productInfo = settingStore.productInfo;
|
||||
const vipTypeDefine = {
|
||||
free: {
|
||||
title: t("vip.basic_edition"),
|
||||
desc: t("vip.community_free_version"),
|
||||
type: "free",
|
||||
icon: "lucide:package-open",
|
||||
privilege: [t("vip.unlimited_certificate_application"), t("vip.unlimited_domain_count"), t("vip.unlimited_certificate_pipelines"), t("vip.common_deployment_plugins"), t("vip.email_webhook_notifications")],
|
||||
},
|
||||
plus: {
|
||||
title: t("vip.professional_edition"),
|
||||
desc: t("vip.open_source_support"),
|
||||
type: "plus",
|
||||
privilege: [t("vip.vip_group_priority"), t("vip.unlimited_site_certificate_monitoring"), t("vip.more_notification_methods"), t("vip.plugins_fully_open")],
|
||||
trial: {
|
||||
title: t("vip.click_to_get_7_day_trial"),
|
||||
click: () => {
|
||||
openStarModal();
|
||||
},
|
||||
},
|
||||
icon: "stash:thumb-up",
|
||||
price: productInfo.plus.price,
|
||||
price3: `¥${productInfo.plus.price3}/3${t("vip.years")}`,
|
||||
tooltip: productInfo.plus.tooltip,
|
||||
get() {
|
||||
return (
|
||||
<a-tooltip title={t("vip.afdian_support_vip")}>
|
||||
<a-button size="small" type="primary" href="https://afdian.com/a/greper" target="_blank">
|
||||
{t("vip.get_after_support")}
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
);
|
||||
},
|
||||
},
|
||||
icon: "stash:thumb-up",
|
||||
price: productInfo.plus.price,
|
||||
price3: `¥${productInfo.plus.price3}/3${t("vip.years")}`,
|
||||
tooltip: productInfo.plus.tooltip,
|
||||
get() {
|
||||
return (
|
||||
<a-tooltip title={t("vip.afdian_support_vip")}>
|
||||
<a-button size="small" type="primary" href="https://afdian.com/a/greper" target="_blank">
|
||||
{t("vip.get_after_support")}
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
comm: {
|
||||
title: t("vip.business_edition"),
|
||||
desc: t("vip.commercial_license"),
|
||||
type: "comm",
|
||||
icon: "vaadin:handshake",
|
||||
privilege: [t("vip.all_pro_privileges"), t("vip.allow_commercial_use_modify_logo_title"), t("vip.data_statistics"), t("vip.plugin_management"), t("vip.unlimited_multi_users"), t("vip.support_user_payment")],
|
||||
price: productInfo.comm.price,
|
||||
price3: `¥${productInfo.comm.price3}/3${t("vip.years")}`,
|
||||
tooltip: productInfo.comm.tooltip,
|
||||
get() {
|
||||
return <a-button size="small">{t("vip.contact_author_for_trial")}</a-button>;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const modalRef = modal.confirm({
|
||||
title,
|
||||
async onOk() {
|
||||
return await doActive();
|
||||
},
|
||||
maskClosable: true,
|
||||
okText: t("vip.activate"),
|
||||
width: 1000,
|
||||
content: () => {
|
||||
let activationCodeGetWay = (
|
||||
<span>
|
||||
<a href="https://afdian.com/a/greper" target="_blank">
|
||||
{t("vip.get_pro_code_after_support")}
|
||||
</a>
|
||||
<span> {t("vip.business_contact_author")}</span>
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
comm: {
|
||||
title: t("vip.business_edition"),
|
||||
desc: t("vip.commercial_license"),
|
||||
type: "comm",
|
||||
icon: "vaadin:handshake",
|
||||
privilege: [
|
||||
t("vip.all_pro_privileges"),
|
||||
t("vip.allow_commercial_use_modify_logo_title"),
|
||||
t("vip.data_statistics"),
|
||||
t("vip.plugin_management"),
|
||||
t("vip.unlimited_multi_users"),
|
||||
t("vip.support_user_payment"),
|
||||
],
|
||||
price: productInfo.comm.price,
|
||||
price3: `¥${productInfo.comm.price3}/3${t("vip.years")}`,
|
||||
tooltip: productInfo.comm.tooltip,
|
||||
get() {
|
||||
return <a-button size="small">{t("vip.contact_author_for_trial")}</a-button>;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
const modalRef = modal.confirm({
|
||||
title,
|
||||
async onOk() {
|
||||
return await doActive();
|
||||
},
|
||||
maskClosable: true,
|
||||
okText: t("vip.activate"),
|
||||
width: 1000,
|
||||
content: () => {
|
||||
let activationCodeGetWay = (
|
||||
<span>
|
||||
<a href="https://afdian.com/a/greper" target="_blank">
|
||||
{t("vip.get_pro_code_after_support")}
|
||||
</a>
|
||||
<span> {t("vip.business_contact_author")}</span>
|
||||
</span>
|
||||
);
|
||||
const vipLabel = settingStore.vipLabel;
|
||||
const slots = [];
|
||||
for (const key in vipTypeDefine) {
|
||||
// @ts-ignore
|
||||
const item = vipTypeDefine[key];
|
||||
const vipBlockClass = `vip-block ${key === settingStore.plusInfo.vipType ? "current" : ""}`;
|
||||
slots.push(
|
||||
<a-col span={8}>
|
||||
<div class={vipBlockClass}>
|
||||
<h3 class="block-header ">
|
||||
<span class="flex-o">{item.title}</span>
|
||||
{item.trial && (
|
||||
<span class="trial">
|
||||
<a-tooltip title={item.trial.message}>
|
||||
<a onClick={item.trial.click}>{item.trial.title}</a>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
)}
|
||||
</h3>
|
||||
<div style="color:green" class="flex-o">
|
||||
<fs-icon icon={item.icon} class="fs-16 flex-o" />
|
||||
{item.desc}
|
||||
</div>
|
||||
<ul class="flex-1 privilege">
|
||||
{item.privilege.map((p: string) => (
|
||||
<li class="flex-baseline">
|
||||
<fs-icon class="color-green" icon="ion:checkmark-sharp" />
|
||||
{p}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div class="footer flex-between flex-vc">
|
||||
<div class="price-show">
|
||||
{item.price && (
|
||||
<span class="flex">
|
||||
<span class="-text">¥{item.price}</span>
|
||||
<span>/</span>
|
||||
{t("vip.year")}
|
||||
<a-tooltip class="ml-5" title={item.price3}>
|
||||
<fs-icon class="pointer color-red" icon="ic:outline-discount"></fs-icon>
|
||||
const vipLabel = settingStore.vipLabel;
|
||||
const slots = [];
|
||||
for (const key in vipTypeDefine) {
|
||||
// @ts-ignore
|
||||
const item = vipTypeDefine[key];
|
||||
const vipBlockClass = `vip-block ${key === settingStore.plusInfo.vipType ? "current" : ""}`;
|
||||
slots.push(
|
||||
<a-col span={8}>
|
||||
<div class={vipBlockClass}>
|
||||
<h3 class="block-header ">
|
||||
<span class="flex-o">{item.title}</span>
|
||||
{item.trial && (
|
||||
<span class="trial">
|
||||
<a-tooltip title={item.trial.message}>
|
||||
<a onClick={item.trial.click}>{item.trial.title}</a>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
)}
|
||||
{!item.price && (
|
||||
<span>
|
||||
<span class="price-text">{t("vip.freee")}</span>
|
||||
</span>
|
||||
)}
|
||||
</h3>
|
||||
<div style="color:green" class="flex-o">
|
||||
<fs-icon icon={item.icon} class="fs-16 flex-o" />
|
||||
{item.desc}
|
||||
</div>
|
||||
<div class="get-show">{item.get && <div>{item.get()}</div>}</div>
|
||||
<ul class="flex-1 privilege">
|
||||
{item.privilege.map((p: string) => (
|
||||
<li class="flex-baseline">
|
||||
<fs-icon class="color-green" icon="ion:checkmark-sharp" />
|
||||
{p}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div class="footer flex-between flex-vc">
|
||||
<div class="price-show">
|
||||
{item.price && (
|
||||
<span class="flex">
|
||||
<span class="-text">¥{item.price}</span>
|
||||
<span>/</span>
|
||||
{t("vip.year")}
|
||||
<a-tooltip class="ml-5" title={item.price3}>
|
||||
<fs-icon class="pointer color-red" icon="ic:outline-discount"></fs-icon>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
)}
|
||||
{!item.price && (
|
||||
<span>
|
||||
<span class="price-text">{t("vip.freee")}</span>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div class="get-show">{item.get && <div>{item.get()}</div>}</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div class="mt-10 mb-10 vip-active-modal">
|
||||
{productInfo.notice && (
|
||||
<div class="mb-10">
|
||||
<a-alert type="error" message={productInfo.notice}></a-alert>
|
||||
</div>
|
||||
)}
|
||||
<div class="vip-type-vs">
|
||||
<a-row gutter={20}>{slots}</a-row>
|
||||
</div>
|
||||
<div class="mt-10">
|
||||
<h3 class="block-header">{isPlus ? t("vip.renew") : t("vip.activate_immediately")}</h3>
|
||||
<div>{isPlus ? `${t("vip.current")} ${vipLabel} ${t("vip.activated_expire_time")}` + dayjs(settingStore.plusInfo.expireTime).format("YYYY-MM-DD") : ""}</div>
|
||||
<div class="mt-10">
|
||||
<div class="flex-o w-100">
|
||||
<span>{t("vip.site_id")}:</span>
|
||||
<fs-copyable class="flex-1" v-model={computedSiteId.value}></fs-copyable>
|
||||
</div>
|
||||
<a-input class="mt-10" v-model:value={formState.code} placeholder={placeholder} />
|
||||
<a-input class="mt-10" v-model:value={formState.inviteCode} placeholder={t("vip.invite_code_optional")} />
|
||||
</div>
|
||||
|
||||
<div class="mt-10">
|
||||
{t("vip.no_activation_code")}
|
||||
{activationCodeGetWay}
|
||||
</div>
|
||||
<div class="mt-10">
|
||||
{t("vip.activation_code_one_use")}
|
||||
<a onClick={goAccount}>{t("vip.bind_account")}</a>,{t("vip.transfer_vip")}
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div class="mt-10 mb-10 vip-active-modal">
|
||||
{productInfo.notice && (
|
||||
<div class="mb-10">
|
||||
<a-alert type="error" message={productInfo.notice}></a-alert>
|
||||
</div>
|
||||
)}
|
||||
<div class="vip-type-vs">
|
||||
<a-row gutter={20}>{slots}</a-row>
|
||||
</div>
|
||||
<div class="mt-10">
|
||||
<h3 class="block-header">{isPlus ? t("vip.renew") : t("vip.activate_immediately")}</h3>
|
||||
<div>
|
||||
{isPlus
|
||||
? `${t("vip.current")} ${vipLabel} ${t("vip.activated_expire_time")}` +
|
||||
dayjs(settingStore.plusInfo.expireTime).format("YYYY-MM-DD")
|
||||
: ""}
|
||||
</div>
|
||||
<div class="mt-10">
|
||||
<div class="flex-o w-100">
|
||||
<span>{t("vip.site_id")}:</span>
|
||||
<fs-copyable class="flex-1" v-model={computedSiteId.value}></fs-copyable>
|
||||
</div>
|
||||
<a-input class="mt-10" v-model:value={formState.code} placeholder={placeholder} />
|
||||
<a-input
|
||||
class="mt-10"
|
||||
v-model:value={formState.inviteCode}
|
||||
placeholder={t("vip.invite_code_optional")}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mt-10">
|
||||
{t("vip.no_activation_code")}
|
||||
{activationCodeGetWay}
|
||||
</div>
|
||||
<div class="mt-10">
|
||||
{t("vip.activation_code_one_use")}<a onClick={goAccount}>{t("vip.bind_account")}</a>
|
||||
,{t("vip.transfer_vip")}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
},
|
||||
});
|
||||
}
|
||||
onMounted(() => {
|
||||
mitter.on("openVipModal", () => {
|
||||
|
@ -434,75 +399,76 @@ onMounted(() => {
|
|||
|
||||
<style lang="less">
|
||||
.layout-vip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
|
||||
&.isPlus {
|
||||
color: #c5913f;
|
||||
}
|
||||
&.isPlus {
|
||||
color: #c5913f;
|
||||
}
|
||||
|
||||
.text {}
|
||||
.text {
|
||||
}
|
||||
}
|
||||
|
||||
.vip-active-modal {
|
||||
.vip-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 5px;
|
||||
height: 250px;
|
||||
.vip-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 5px;
|
||||
height: 250px;
|
||||
|
||||
//background-color: rgba(250, 237, 167, 0.79);
|
||||
&.current {
|
||||
border-color: green;
|
||||
}
|
||||
//background-color: rgba(250, 237, 167, 0.79);
|
||||
&.current {
|
||||
border-color: green;
|
||||
}
|
||||
|
||||
.block-header {
|
||||
padding: 0px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.block-header {
|
||||
padding: 0px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
.trial {
|
||||
font-size: 12px;
|
||||
font-wight: 400;
|
||||
}
|
||||
}
|
||||
.trial {
|
||||
font-size: 12px;
|
||||
font-wight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding-top: 5px;
|
||||
margin-top: 0px;
|
||||
border-top: 1px solid #eee;
|
||||
.footer {
|
||||
padding-top: 5px;
|
||||
margin-top: 0px;
|
||||
border-top: 1px solid #eee;
|
||||
|
||||
.price-text {
|
||||
font-size: 18px;
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
.price-text {
|
||||
font-size: 18px;
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: unset;
|
||||
margin-left: 0px;
|
||||
padding: 0;
|
||||
}
|
||||
ul {
|
||||
list-style-type: unset;
|
||||
margin-left: 0px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.color-green {
|
||||
color: green;
|
||||
}
|
||||
.color-green {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.vip-type-vs {
|
||||
.privilege {
|
||||
.fs-icon {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
.vip-type-vs {
|
||||
.privilege {
|
||||
.fs-icon {
|
||||
color: green;
|
||||
}
|
||||
}
|
||||
|
||||
.fs-icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
.fs-icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -35,7 +35,7 @@ export default {
|
|||
forEach(map, (item, key) => {
|
||||
list.push({
|
||||
key,
|
||||
label: item.label
|
||||
label: item.label,
|
||||
});
|
||||
});
|
||||
return list;
|
||||
|
@ -54,9 +54,9 @@ export default {
|
|||
return {
|
||||
languages,
|
||||
current,
|
||||
changeLocale
|
||||
changeLocale,
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
.fs-menu-wrapper{
|
||||
.fs-menu-wrapper {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
&.fs-menu-better-scroll{
|
||||
&.fs-menu-better-scroll {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.menu-item-title{
|
||||
.menu-item-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.fs-icon{
|
||||
font-size: 16px !important;
|
||||
min-width: 16px !important;
|
||||
.fs-icon {
|
||||
font-size: 16px !important;
|
||||
min-width: 16px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import { utils } from "@fast-crud/fast-crud";
|
|||
import * as _ from "lodash-es";
|
||||
|
||||
defineOptions({
|
||||
name: "FsMenu"
|
||||
name: "FsMenu",
|
||||
});
|
||||
|
||||
const props = defineProps<{
|
||||
|
@ -37,7 +37,7 @@ function buildItemMenus(menus: any) {
|
|||
title: sub.title,
|
||||
icon: () => {
|
||||
return <fsIcon icon={sub.icon ?? sub.meta?.icon} />;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
list.push(item);
|
||||
|
@ -50,7 +50,7 @@ function buildItemMenus(menus: any) {
|
|||
|
||||
watch(
|
||||
() => props.menus,
|
||||
(menus) => {
|
||||
menus => {
|
||||
items.value = buildItemMenus(menus);
|
||||
},
|
||||
{ immediate: true }
|
||||
|
@ -77,7 +77,7 @@ function openSelectedParents(fullPath: any) {
|
|||
return;
|
||||
}
|
||||
if (value.path === fullPath) {
|
||||
_.forEach(context.parents, (item) => {
|
||||
_.forEach(context.parents, item => {
|
||||
if (item.value instanceof Array) {
|
||||
return;
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ watch(
|
|||
() => {
|
||||
return route.fullPath;
|
||||
},
|
||||
(path) => {
|
||||
path => {
|
||||
// path = route.fullPath;
|
||||
selectedKeys.value = [path];
|
||||
const changed = openSelectedParents(path);
|
||||
|
@ -108,7 +108,7 @@ watch(
|
|||
}
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
|
|
@ -6,7 +6,7 @@ import "./index.less";
|
|||
import { utils } from "@fast-crud/fast-crud";
|
||||
import { routerUtils } from "/@/utils/util.router";
|
||||
|
||||
defineOptions()
|
||||
defineOptions();
|
||||
|
||||
export default defineComponent({
|
||||
name: "FsMenu",
|
||||
|
@ -14,9 +14,9 @@ export default defineComponent({
|
|||
props: {
|
||||
menus: {},
|
||||
expandSelected: {
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
scroll: {}
|
||||
scroll: {},
|
||||
},
|
||||
setup(props, ctx) {
|
||||
async function onSelect(item: any) {
|
||||
|
@ -37,7 +37,7 @@ export default defineComponent({
|
|||
title: sub.title,
|
||||
icon: () => {
|
||||
return <fsIcon icon={sub.icon ?? sub.meta?.icon} />;
|
||||
}
|
||||
},
|
||||
};
|
||||
list.push(item);
|
||||
if (sub.children && sub.children.length > 0) {
|
||||
|
@ -80,7 +80,7 @@ export default defineComponent({
|
|||
default: () => {
|
||||
return buildMenus(sub.children);
|
||||
},
|
||||
title
|
||||
title,
|
||||
};
|
||||
function onTitleClick() {
|
||||
if (sub.path && ctx.attrs.mode === "horizontal") {
|
||||
|
@ -101,7 +101,7 @@ export default defineComponent({
|
|||
const slots = {
|
||||
default() {
|
||||
return buildMenus(props.menus);
|
||||
}
|
||||
},
|
||||
};
|
||||
const selectedKeys = ref([]);
|
||||
const openKeys = ref([]);
|
||||
|
@ -123,7 +123,7 @@ export default defineComponent({
|
|||
return;
|
||||
}
|
||||
if (value.path === fullPath) {
|
||||
_.forEach(context.parents, (item) => {
|
||||
_.forEach(context.parents, item => {
|
||||
if (item.value instanceof Array) {
|
||||
return;
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ export default defineComponent({
|
|||
() => {
|
||||
return route.fullPath;
|
||||
},
|
||||
(path) => {
|
||||
path => {
|
||||
// path = route.fullPath;
|
||||
selectedKeys.value = [path];
|
||||
const changed = openSelectedParents(path);
|
||||
|
@ -157,7 +157,7 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
return () => {
|
||||
|
@ -170,7 +170,7 @@ export default defineComponent({
|
|||
// onOpenChange={onOpenChange}
|
||||
v-models={[
|
||||
[openKeys.value, "openKeys"],
|
||||
[selectedKeys.value, "selectedKeys"]
|
||||
[selectedKeys.value, "selectedKeys"],
|
||||
]}
|
||||
items={items.value}
|
||||
inlineCollapsed={!props.expandSelected}
|
||||
|
@ -179,5 +179,5 @@ export default defineComponent({
|
|||
const classNames = { "fs-menu-wrapper": true, "fs-menu-better-scroll": props.scroll };
|
||||
return <div>{menu}</div>;
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ export default defineComponent({
|
|||
() => {
|
||||
return router.currentRoute.value.fullPath;
|
||||
},
|
||||
(value) => {
|
||||
value => {
|
||||
showSourceLink.value = value !== "/index";
|
||||
},
|
||||
{ immediate: true }
|
||||
|
@ -29,9 +29,9 @@ export default defineComponent({
|
|||
}
|
||||
return {
|
||||
goSource,
|
||||
showSourceLink
|
||||
showSourceLink,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -2,14 +2,7 @@
|
|||
<div class="fs-multiple-page-control-group">
|
||||
<div class="fs-multiple-page-control-content">
|
||||
<div class="fs-multiple-page-control-content-inner">
|
||||
<a-tabs
|
||||
class="fs-multiple-page-control fs-multiple-page-sort"
|
||||
:active-key="page.getCurrent"
|
||||
type="editable-card"
|
||||
hide-add
|
||||
@tab-click="handleClick"
|
||||
@edit="handleTabEdit"
|
||||
>
|
||||
<a-tabs class="fs-multiple-page-control fs-multiple-page-sort" :active-key="page.getCurrent" type="editable-card" hide-add @tab-click="handleClick" @edit="handleTabEdit">
|
||||
<a-tab-pane v-for="item in page.getOpened" :key="item.fullPath" :name="item.fullPath" :closable="isTabClosable(item)">
|
||||
<template #tab>
|
||||
<span class="flex-o">
|
||||
|
@ -75,7 +68,7 @@ export default {
|
|||
closeRight: pageStore.closeRight,
|
||||
closeOther: pageStore.closeOther,
|
||||
closeAll: pageStore.closeAll,
|
||||
openedSort: pageStore.openedSort
|
||||
openedSort: pageStore.openedSort,
|
||||
};
|
||||
const computeOpened = computed(() => {
|
||||
return pageStore.getOpened;
|
||||
|
@ -84,7 +77,7 @@ export default {
|
|||
return {
|
||||
page: pageStore,
|
||||
...actions,
|
||||
computeOpened
|
||||
computeOpened,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
|
@ -97,9 +90,9 @@ export default {
|
|||
{ icon: "arrow-left", title: "关闭左侧", value: "left" },
|
||||
{ icon: "arrow-right", title: "关闭右侧", value: "right" },
|
||||
{ icon: "times", title: "关闭其它", value: "other" },
|
||||
{ icon: "times-circle", title: "关闭全部", value: "all" }
|
||||
{ icon: "times-circle", title: "关闭全部", value: "all" },
|
||||
],
|
||||
tagName: "/index"
|
||||
tagName: "/index",
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
@ -195,8 +188,8 @@ export default {
|
|||
if (action === "remove") {
|
||||
this.close({ tagName });
|
||||
}
|
||||
}
|
||||
} as any
|
||||
},
|
||||
} as any,
|
||||
};
|
||||
</script>
|
||||
<style lang="less">
|
||||
|
|
|
@ -19,44 +19,44 @@ import { defineComponent, ref } from "vue";
|
|||
const colorListDefine = [
|
||||
{
|
||||
key: "薄暮",
|
||||
color: "#f5222d"
|
||||
color: "#f5222d",
|
||||
},
|
||||
{
|
||||
key: "火山",
|
||||
color: "#fa541c"
|
||||
color: "#fa541c",
|
||||
},
|
||||
{
|
||||
key: "日暮",
|
||||
color: "#faad14"
|
||||
color: "#faad14",
|
||||
},
|
||||
{
|
||||
key: "明青",
|
||||
color: "#13c2c2"
|
||||
color: "#13c2c2",
|
||||
},
|
||||
{
|
||||
key: "极光绿",
|
||||
color: "#52c41a"
|
||||
color: "#52c41a",
|
||||
},
|
||||
{
|
||||
key: "拂晓蓝(默认)",
|
||||
color: "#1890ff"
|
||||
color: "#1890ff",
|
||||
},
|
||||
{
|
||||
key: "极客蓝",
|
||||
color: "#2f54eb"
|
||||
color: "#2f54eb",
|
||||
},
|
||||
{
|
||||
key: "酱紫",
|
||||
color: "#722ed1"
|
||||
}
|
||||
color: "#722ed1",
|
||||
},
|
||||
];
|
||||
export default defineComponent({
|
||||
name: "FsThemeColorPicker",
|
||||
props: {
|
||||
primaryColor: {
|
||||
type: String,
|
||||
default: "#1890ff"
|
||||
}
|
||||
default: "#1890ff",
|
||||
},
|
||||
},
|
||||
emits: ["change"],
|
||||
setup(props, ctx) {
|
||||
|
@ -66,9 +66,9 @@ export default defineComponent({
|
|||
}
|
||||
return {
|
||||
colorList,
|
||||
changeColor
|
||||
changeColor,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<style lang="less">
|
||||
|
|
|
@ -27,9 +27,9 @@ export default defineComponent({
|
|||
visible,
|
||||
show,
|
||||
afterVisibleChange,
|
||||
setting
|
||||
setting,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -29,9 +29,9 @@ export default defineComponent({
|
|||
};
|
||||
return {
|
||||
setting,
|
||||
onChange
|
||||
onChange,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<template>
|
||||
<a-dropdown>
|
||||
<div class="fs-user-info">{{ t('user.greeting') }},{{ userStore.getUserInfo?.nickName || userStore.getUserInfo?.username }}</div>
|
||||
<div class="fs-user-info">{{ t("user.greeting") }},{{ userStore.getUserInfo?.nickName || userStore.getUserInfo?.username }}</div>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item>
|
||||
<div @click="goUserProfile">{{ t('user.profile') }}</div>
|
||||
<div @click="goUserProfile">{{ t("user.profile") }}</div>
|
||||
</a-menu-item>
|
||||
<a-menu-item>
|
||||
<div @click="doLogout">{{ t('user.logout') }}</div>
|
||||
<div @click="doLogout">{{ t("user.logout") }}</div>
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
<!-- <fs-menu class="header-menu" mode="horizontal" :expand-selected="false" :selectable="false" :menus="frameworkMenus" />-->
|
||||
<div
|
||||
v-for="menu of resourceStore.authedTopMenus"
|
||||
:key="menu.name"
|
||||
class="top-menu flex-center header-btn"
|
||||
:class="{ current: resourceStore.currentTopMenu === menu }"
|
||||
:style="{ color: resourceStore.currentTopMenu === menu ? token.colorPrimary : '' }"
|
||||
|
|
|
@ -3,7 +3,7 @@ import App from "./App.vue";
|
|||
// import Antd from "ant-design-vue";
|
||||
import Antd from "./plugin/antdv-async/index";
|
||||
import "./style/common.less";
|
||||
import { i18n, loadLocaleMessages } from "/@/locales"
|
||||
import { i18n, loadLocaleMessages } from "/@/locales";
|
||||
import components from "./components";
|
||||
import router from "./router";
|
||||
import plugin from "./plugin/";
|
||||
|
@ -15,15 +15,15 @@ import { initPreferences } from "/@/vben/preferences";
|
|||
// import "./components/code-editor/import-works";
|
||||
// @ts-ignore
|
||||
async function bootstrap() {
|
||||
const app = createApp(App);
|
||||
// app.use(Antd);
|
||||
app.use(Antd);
|
||||
await setupVben(app, { loadLocaleMessages, router });
|
||||
app.use(router);
|
||||
// app.use(i18n);
|
||||
// app.use(store);
|
||||
app.use(components);
|
||||
app.use(plugin, { i18n });
|
||||
const app = createApp(App);
|
||||
// app.use(Antd);
|
||||
app.use(Antd);
|
||||
await setupVben(app, { loadLocaleMessages, router });
|
||||
app.use(router);
|
||||
// app.use(i18n);
|
||||
// app.use(store);
|
||||
app.use(components);
|
||||
app.use(plugin, { i18n });
|
||||
|
||||
const envMode = util.env.MODE;
|
||||
const namespace = `${import.meta.env.VITE_APP_NAMESPACE}-${envMode}`;
|
||||
|
|
|
@ -177,10 +177,10 @@ const mockUtil: any = {
|
|||
records: records,
|
||||
total: data.length,
|
||||
limit,
|
||||
offset
|
||||
}
|
||||
offset,
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/" + name + "/get",
|
||||
|
@ -192,9 +192,9 @@ const mockUtil: any = {
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: current
|
||||
data: current,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/" + name + "/byIds",
|
||||
|
@ -205,9 +205,9 @@ const mockUtil: any = {
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: res
|
||||
data: res,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/" + name + "/add",
|
||||
|
@ -218,9 +218,9 @@ const mockUtil: any = {
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: cloneDeep(req.body)
|
||||
data: cloneDeep(req.body),
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/" + name + "/update",
|
||||
|
@ -241,9 +241,9 @@ const mockUtil: any = {
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: null
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/" + name + "/delete",
|
||||
|
@ -253,9 +253,9 @@ const mockUtil: any = {
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: null
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/" + name + "/batchDelete",
|
||||
|
@ -271,9 +271,9 @@ const mockUtil: any = {
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: null
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/" + name + "/delete",
|
||||
|
@ -283,9 +283,9 @@ const mockUtil: any = {
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: null
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/" + name + "/all",
|
||||
|
@ -294,9 +294,9 @@ const mockUtil: any = {
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: list
|
||||
data: list,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/" + name + "/cellUpdate",
|
||||
|
@ -317,7 +317,7 @@ const mockUtil: any = {
|
|||
} else {
|
||||
item = {
|
||||
id: ++options.idGenerator,
|
||||
[req.body.key]: req.body.value
|
||||
[req.body.key]: req.body.value,
|
||||
};
|
||||
list.unshift(item);
|
||||
}
|
||||
|
@ -325,9 +325,9 @@ const mockUtil: any = {
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: item
|
||||
data: item,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/" + name + "/columnUpdate",
|
||||
|
@ -350,12 +350,12 @@ const mockUtil: any = {
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: null
|
||||
data: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default mockUtil;
|
||||
|
|
|
@ -9,21 +9,21 @@ export default [
|
|||
children: [
|
||||
{
|
||||
value: "yizhi",
|
||||
label: "一致"
|
||||
label: "一致",
|
||||
},
|
||||
{
|
||||
value: "fankui",
|
||||
label: "反馈"
|
||||
label: "反馈",
|
||||
},
|
||||
{
|
||||
value: "xiaolv",
|
||||
label: "效率"
|
||||
label: "效率",
|
||||
},
|
||||
{
|
||||
value: "kekong",
|
||||
label: "可控"
|
||||
}
|
||||
]
|
||||
label: "可控",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "daohang",
|
||||
|
@ -31,15 +31,15 @@ export default [
|
|||
children: [
|
||||
{
|
||||
value: "cexiangdaohang",
|
||||
label: "侧向导航"
|
||||
label: "侧向导航",
|
||||
},
|
||||
{
|
||||
value: "dingbudaohang",
|
||||
label: "顶部导航"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
label: "顶部导航",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "zujian",
|
||||
|
@ -51,25 +51,25 @@ export default [
|
|||
children: [
|
||||
{
|
||||
value: "layout",
|
||||
label: "Layout 布局"
|
||||
label: "Layout 布局",
|
||||
},
|
||||
{
|
||||
value: "color",
|
||||
label: "Color 色彩"
|
||||
label: "Color 色彩",
|
||||
},
|
||||
{
|
||||
value: "typography",
|
||||
label: "Typography 字体"
|
||||
label: "Typography 字体",
|
||||
},
|
||||
{
|
||||
value: "icon",
|
||||
label: "Icon 图标"
|
||||
label: "Icon 图标",
|
||||
},
|
||||
{
|
||||
value: "button",
|
||||
label: "Button 按钮"
|
||||
}
|
||||
]
|
||||
label: "Button 按钮",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "form",
|
||||
|
@ -77,61 +77,61 @@ export default [
|
|||
children: [
|
||||
{
|
||||
value: "radio",
|
||||
label: "Radio 单选框"
|
||||
label: "Radio 单选框",
|
||||
},
|
||||
{
|
||||
value: "checkbox",
|
||||
label: "Checkbox 多选框"
|
||||
label: "Checkbox 多选框",
|
||||
},
|
||||
{
|
||||
value: "input",
|
||||
label: "Input 输入框"
|
||||
label: "Input 输入框",
|
||||
},
|
||||
{
|
||||
value: "input-number",
|
||||
label: "InputNumber 计数器"
|
||||
label: "InputNumber 计数器",
|
||||
},
|
||||
{
|
||||
value: "select",
|
||||
label: "Select 选择器"
|
||||
label: "Select 选择器",
|
||||
},
|
||||
{
|
||||
value: "cascader",
|
||||
label: "Cascader 级联选择器"
|
||||
label: "Cascader 级联选择器",
|
||||
},
|
||||
{
|
||||
value: "switch",
|
||||
label: "Switch 开关"
|
||||
label: "Switch 开关",
|
||||
},
|
||||
{
|
||||
value: "slider",
|
||||
label: "Slider 滑块"
|
||||
label: "Slider 滑块",
|
||||
},
|
||||
{
|
||||
value: "time-picker",
|
||||
label: "TimePicker 时间选择器"
|
||||
label: "TimePicker 时间选择器",
|
||||
},
|
||||
{
|
||||
value: "date-picker",
|
||||
label: "DatePicker 日期选择器"
|
||||
label: "DatePicker 日期选择器",
|
||||
},
|
||||
{
|
||||
value: "datetime-picker",
|
||||
label: "DateTimePicker 日期时间选择器"
|
||||
label: "DateTimePicker 日期时间选择器",
|
||||
},
|
||||
{
|
||||
value: "upload",
|
||||
label: "Upload 上传"
|
||||
label: "Upload 上传",
|
||||
},
|
||||
{
|
||||
value: "rate",
|
||||
label: "Rate 评分"
|
||||
label: "Rate 评分",
|
||||
},
|
||||
{
|
||||
value: "form1",
|
||||
label: "Form 表单"
|
||||
}
|
||||
]
|
||||
label: "Form 表单",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "data",
|
||||
|
@ -139,29 +139,29 @@ export default [
|
|||
children: [
|
||||
{
|
||||
value: "table",
|
||||
label: "Table 表格"
|
||||
label: "Table 表格",
|
||||
},
|
||||
{
|
||||
value: "tag",
|
||||
label: "Tag 标签"
|
||||
label: "Tag 标签",
|
||||
},
|
||||
{
|
||||
value: "progress",
|
||||
label: "Progress 进度条"
|
||||
label: "Progress 进度条",
|
||||
},
|
||||
{
|
||||
value: "tree",
|
||||
label: "Tree 树形控件"
|
||||
label: "Tree 树形控件",
|
||||
},
|
||||
{
|
||||
value: "pagination",
|
||||
label: "Pagination 分页"
|
||||
label: "Pagination 分页",
|
||||
},
|
||||
{
|
||||
value: "badge",
|
||||
label: "Badge 标记"
|
||||
}
|
||||
]
|
||||
label: "Badge 标记",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "notice",
|
||||
|
@ -169,25 +169,25 @@ export default [
|
|||
children: [
|
||||
{
|
||||
value: "alert",
|
||||
label: "Alert 警告"
|
||||
label: "Alert 警告",
|
||||
},
|
||||
{
|
||||
value: "loading",
|
||||
label: "Loading 加载"
|
||||
label: "Loading 加载",
|
||||
},
|
||||
{
|
||||
value: "message",
|
||||
label: "Message 消息提示"
|
||||
label: "Message 消息提示",
|
||||
},
|
||||
{
|
||||
value: "message-box",
|
||||
label: "MessageBox 弹框"
|
||||
label: "MessageBox 弹框",
|
||||
},
|
||||
{
|
||||
value: "notification",
|
||||
label: "Notification 通知"
|
||||
}
|
||||
]
|
||||
label: "Notification 通知",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "navigation",
|
||||
|
@ -195,25 +195,25 @@ export default [
|
|||
children: [
|
||||
{
|
||||
value: "menu",
|
||||
label: "NavMenu 导航菜单"
|
||||
label: "NavMenu 导航菜单",
|
||||
},
|
||||
{
|
||||
value: "tabs",
|
||||
label: "Tabs 标签页"
|
||||
label: "Tabs 标签页",
|
||||
},
|
||||
{
|
||||
value: "breadcrumb",
|
||||
label: "Breadcrumb 面包屑"
|
||||
label: "Breadcrumb 面包屑",
|
||||
},
|
||||
{
|
||||
value: "dropdown",
|
||||
label: "Dropdown 下拉菜单"
|
||||
label: "Dropdown 下拉菜单",
|
||||
},
|
||||
{
|
||||
value: "steps",
|
||||
label: "Steps 步骤条"
|
||||
}
|
||||
]
|
||||
label: "Steps 步骤条",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "others",
|
||||
|
@ -221,31 +221,31 @@ export default [
|
|||
children: [
|
||||
{
|
||||
value: "dialog",
|
||||
label: "Dialog 对话框"
|
||||
label: "Dialog 对话框",
|
||||
},
|
||||
{
|
||||
value: "tooltip",
|
||||
label: "Tooltip 文字提示"
|
||||
label: "Tooltip 文字提示",
|
||||
},
|
||||
{
|
||||
value: "popover",
|
||||
label: "Popover 弹出框"
|
||||
label: "Popover 弹出框",
|
||||
},
|
||||
{
|
||||
value: "card",
|
||||
label: "Card 卡片"
|
||||
label: "Card 卡片",
|
||||
},
|
||||
{
|
||||
value: "carousel",
|
||||
label: "Carousel 走马灯"
|
||||
label: "Carousel 走马灯",
|
||||
},
|
||||
{
|
||||
value: "collapse",
|
||||
label: "Collapse 折叠面板"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
label: "Collapse 折叠面板",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: "ziyuan",
|
||||
|
@ -253,16 +253,16 @@ export default [
|
|||
children: [
|
||||
{
|
||||
value: "axure",
|
||||
label: "Axure Components"
|
||||
label: "Axure Components",
|
||||
},
|
||||
{
|
||||
value: "sketch",
|
||||
label: "Sketch Templates"
|
||||
label: "Sketch Templates",
|
||||
},
|
||||
{
|
||||
value: "jiaohu",
|
||||
label: "组件交互文档"
|
||||
}
|
||||
]
|
||||
}
|
||||
label: "组件交互文档",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
|
@ -7,25 +7,25 @@ import { cloneDeep } from "lodash-es";
|
|||
const openStatus = [
|
||||
{ value: "1", label: "打开", color: "success", icon: "ion:radio-button-on" },
|
||||
{ value: "2", label: "停止", color: "cyan" },
|
||||
{ value: "0", label: "关闭", color: "red", icon: "ion:radio-button-off" }
|
||||
{ value: "0", label: "关闭", color: "red", icon: "ion:radio-button-off" },
|
||||
];
|
||||
|
||||
const moreOpenStatus = [
|
||||
{ value: "1", label: "打开(open)", color: "success" },
|
||||
{ value: "2", label: "停止(stop)", color: "cyan" },
|
||||
{ value: "0", label: "关闭(close)", color: "red" }
|
||||
{ value: "0", label: "关闭(close)", color: "red" },
|
||||
];
|
||||
|
||||
const textStatus = [
|
||||
{ id: "1", text: "打开", color: "success" },
|
||||
{ id: "2", text: "停止", color: "cyan" },
|
||||
{ id: "0", text: "关闭", color: "red" }
|
||||
{ id: "0", text: "关闭", color: "red" },
|
||||
];
|
||||
|
||||
let manyStatus = [
|
||||
{ value: "1", label: "打开", color: "success", icon: "ion:radio-button-on" },
|
||||
{ value: "2", label: "停止", color: "cyan" },
|
||||
{ value: "0", label: "关闭", color: "red", icon: "ion:radio-button-off" }
|
||||
{ value: "0", label: "关闭", color: "red", icon: "ion:radio-button-off" },
|
||||
];
|
||||
let tempManyStatus: any[] = [];
|
||||
for (let i = 0; i < 100; i++) {
|
||||
|
@ -54,9 +54,9 @@ export default [
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: openStatus
|
||||
data: openStatus,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/dicts/_OpenStatusEnum2",
|
||||
|
@ -65,9 +65,9 @@ export default [
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: textStatus
|
||||
data: textStatus,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/dicts/ManyOpenStatusEnum",
|
||||
|
@ -76,9 +76,9 @@ export default [
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: manyStatus
|
||||
data: manyStatus,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/dicts/moreOpenStatusEnum",
|
||||
|
@ -87,9 +87,9 @@ export default [
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: moreOpenStatus
|
||||
data: moreOpenStatus,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/dicts/cascaderData",
|
||||
|
@ -98,9 +98,9 @@ export default [
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: cascaderData
|
||||
data: cascaderData,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/dicts/pca",
|
||||
|
@ -110,9 +110,9 @@ export default [
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: data
|
||||
data: data,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/dicts/littlePca",
|
||||
|
@ -121,9 +121,9 @@ export default [
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: pcaDataLittle
|
||||
data: pcaDataLittle,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/tree/GetTreeChildrenByParentId",
|
||||
|
@ -133,9 +133,9 @@ export default [
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: list
|
||||
data: list,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "/mock/tree/GetNodesByValues",
|
||||
|
@ -145,8 +145,8 @@ export default [
|
|||
return {
|
||||
code: 0,
|
||||
msg: "success",
|
||||
data: list
|
||||
data: list,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
|
|
|
@ -9,13 +9,13 @@ export default [
|
|||
children: [
|
||||
{
|
||||
code: "3",
|
||||
name: "海淀"
|
||||
name: "海淀",
|
||||
},
|
||||
{
|
||||
code: "4",
|
||||
name: "朝阳"
|
||||
}
|
||||
]
|
||||
name: "朝阳",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
code: "5",
|
||||
|
@ -23,15 +23,15 @@ export default [
|
|||
children: [
|
||||
{
|
||||
code: "6",
|
||||
name: "海淀郊区"
|
||||
name: "海淀郊区",
|
||||
},
|
||||
{
|
||||
code: "7",
|
||||
name: "朝阳郊区"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
name: "朝阳郊区",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
code: "11",
|
||||
|
@ -43,13 +43,13 @@ export default [
|
|||
children: [
|
||||
{
|
||||
code: "13",
|
||||
name: "南山"
|
||||
name: "南山",
|
||||
},
|
||||
{
|
||||
code: "14",
|
||||
name: "福田"
|
||||
}
|
||||
]
|
||||
name: "福田",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
code: "15",
|
||||
|
@ -57,14 +57,14 @@ export default [
|
|||
children: [
|
||||
{
|
||||
code: "16",
|
||||
name: "南山郊区"
|
||||
name: "南山郊区",
|
||||
},
|
||||
{
|
||||
code: "17",
|
||||
name: "福田郊区"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
name: "福田郊区",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
|
@ -17,7 +17,7 @@ export const TreeNodesLazyLoader = {
|
|||
if (!(values instanceof Array)) {
|
||||
values = [values];
|
||||
}
|
||||
return getPcasData().then((data) => {
|
||||
return getPcasData().then(data => {
|
||||
const nodes = [];
|
||||
for (const value of values) {
|
||||
const found = this.getNode(data, value);
|
||||
|
@ -44,7 +44,7 @@ export const TreeNodesLazyLoader = {
|
|||
}
|
||||
},
|
||||
getChildren(parent: any) {
|
||||
return getPcasData().then((data) => {
|
||||
return getPcasData().then(data => {
|
||||
const list = this.getChildrenByParent(parent, data);
|
||||
if (list == null) {
|
||||
return [];
|
||||
|
@ -85,5 +85,5 @@ export const TreeNodesLazyLoader = {
|
|||
}
|
||||
console.log("found children:", newList);
|
||||
return newList;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -38,7 +38,7 @@ list.forEach((apiFile: any) => {
|
|||
|
||||
const req = {
|
||||
body: data,
|
||||
params: params
|
||||
params: params,
|
||||
};
|
||||
const ret = await item.handle(req);
|
||||
utils.logger.debug("response:", ret);
|
||||
|
|
|
@ -10,5 +10,5 @@ function install(app: App, options: any = {}) {
|
|||
}
|
||||
|
||||
export default {
|
||||
install
|
||||
install,
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ import { request } from "/src/api/service";
|
|||
export async function getPermissions() {
|
||||
const ret = await request({
|
||||
url: "/sys/authority/user/permissions",
|
||||
method: "post"
|
||||
method: "post",
|
||||
});
|
||||
// 如果使用你自己的后端,需要在此处将返回结果改造为本模块需要的结构
|
||||
// 结构详情,请参考示例中打印的日志 ”获取权限数据成功:{...}“ (实际上就是“资源管理”页面中列出来的数据)
|
||||
|
|
|
@ -7,5 +7,5 @@ const install = function (app: any) {
|
|||
|
||||
export default {
|
||||
install,
|
||||
...permission
|
||||
...permission,
|
||||
};
|
||||
|
|
|
@ -7,5 +7,5 @@ export default {
|
|||
if (!hasPermission) {
|
||||
el.parentNode && el.parentNode.removeChild(el);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@ export * from "./errors";
|
|||
|
||||
export function usePermission() {
|
||||
return {
|
||||
...util
|
||||
...util,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -19,5 +19,5 @@ export default {
|
|||
// 通过路由守卫,在登录成功后拦截路由,从后台加载权限数据
|
||||
// 然后将权限数据转化为菜单和路由,添加到系统中
|
||||
registerRouterHook();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -56,7 +56,7 @@ export const usePermissionStore = defineStore({
|
|||
id: "app.permission",
|
||||
state: (): PermissionState => ({
|
||||
permissions: [],
|
||||
inited: false
|
||||
inited: false,
|
||||
}),
|
||||
getters: {
|
||||
// @ts-ignore
|
||||
|
@ -68,7 +68,7 @@ export const usePermissionStore = defineStore({
|
|||
isInited() {
|
||||
// @ts-ignore
|
||||
return this.inited;
|
||||
}
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
init({ permissions }: any) {
|
||||
|
@ -101,6 +101,6 @@ export const usePermissionStore = defineStore({
|
|||
}
|
||||
}
|
||||
this.resolve(permissionTree);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -47,16 +47,16 @@ export function useCrudPermission({ permission }: UseCrudPermissionProps) {
|
|||
{
|
||||
actionbar: {
|
||||
buttons: {
|
||||
add: { show: hasActionPermission("add") }
|
||||
}
|
||||
add: { show: hasActionPermission("add") },
|
||||
},
|
||||
},
|
||||
rowHandle: {
|
||||
buttons: {
|
||||
edit: { show: hasActionPermission("edit") },
|
||||
remove: { show: hasActionPermission("remove") },
|
||||
view: { show: hasActionPermission("view") }
|
||||
}
|
||||
}
|
||||
view: { show: hasActionPermission("view") },
|
||||
},
|
||||
},
|
||||
},
|
||||
extra
|
||||
);
|
||||
|
|
|
@ -26,7 +26,7 @@ const util = {
|
|||
message.error("对不起,您没有权限执行此操作");
|
||||
throw new NoPermissionError();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default util;
|
||||
|
|
|
@ -6,7 +6,7 @@ import { createRouterGuard } from "/@/router/guard";
|
|||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
routes
|
||||
routes,
|
||||
});
|
||||
/**
|
||||
|
||||
|
|
|
@ -1,74 +1,69 @@
|
|||
.ant-layout .ant-layout-sider{
|
||||
background-color: #ebf1f6;
|
||||
}
|
||||
|
||||
.ant-layout .ant-layout-header{
|
||||
.ant-layout .ant-layout-sider {
|
||||
background-color: #ebf1f6;
|
||||
}
|
||||
|
||||
.fs-multiple-page-control-group .fs-multiple-page-control-content{
|
||||
.ant-layout .ant-layout-header {
|
||||
background-color: #ebf1f6;
|
||||
}
|
||||
|
||||
.fs-multiple-page-control-group .fs-multiple-page-control-content {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.fs-multiple-page-control-group .fs-multiple-page-control-btn .ant-btn{
|
||||
border-bottom-left-radius:0;
|
||||
border-bottom-right-radius:0;
|
||||
.fs-multiple-page-control-group .fs-multiple-page-control-btn .ant-btn {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
.ant-menu-horizontal{
|
||||
.ant-menu-horizontal {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.fs-framework .header-menu{
|
||||
.fs-framework .header-menu {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.ant-btn.ant-btn-icon-only{
|
||||
padding-inline:revert;
|
||||
.ant-btn.ant-btn-icon-only {
|
||||
padding-inline: revert;
|
||||
}
|
||||
|
||||
.fs-form-wrapper .fs-form-header {
|
||||
padding-right: 30px !important;
|
||||
}
|
||||
|
||||
|
||||
.fs-values-format .fs-tag{
|
||||
.fs-values-format .fs-tag {
|
||||
display: inline-flex;
|
||||
.fs-icon{
|
||||
.fs-icon {
|
||||
margin-right: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.fs-search .ant-row{
|
||||
|
||||
.fs-search .ant-row {
|
||||
}
|
||||
|
||||
|
||||
//适配手机端
|
||||
.ant-tour{
|
||||
max-width: 90vw
|
||||
.ant-tour {
|
||||
max-width: 90vw;
|
||||
}
|
||||
|
||||
.fs-page{
|
||||
.fs-page-header{
|
||||
.fs-page {
|
||||
.fs-page-header {
|
||||
background-color: hsl(var(--card));
|
||||
}
|
||||
.fs-crud-table{
|
||||
.fs-crud-table {
|
||||
background-color: hsl(var(--card));
|
||||
}
|
||||
}
|
||||
|
||||
footer{
|
||||
footer {
|
||||
background-color: hsl(var(--card)) !important;
|
||||
}
|
||||
|
||||
|
||||
.ant-select-multiple .ant-select-selection-item-remove{
|
||||
.ant-select-multiple .ant-select-selection-item-remove {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
.ant-progress.ant-progress-show-info .ant-progress-outer {
|
||||
margin-inline-end: calc(-3em - 8px);
|
||||
padding-inline-end: calc(3em + 8px);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,18 +2,17 @@
|
|||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size:16px;
|
||||
font-size: 16px;
|
||||
}
|
||||
.fs-icon {
|
||||
font-size:16px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.ant-btn {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.fs-iconify{
|
||||
|
||||
.fs-iconify {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +36,6 @@
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
.ant-drawer-content {
|
||||
&.fullscreen {
|
||||
position: fixed;
|
||||
|
@ -51,10 +49,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.icon-button {
|
||||
cursor: pointer;
|
||||
font-size: 22px
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.ant-drawer {
|
||||
|
@ -76,7 +73,7 @@
|
|||
margin: 20px;
|
||||
}
|
||||
|
||||
.fs-crud-table{
|
||||
.fs-crud-table {
|
||||
.ant-table-body {
|
||||
height: 60vh;
|
||||
table {
|
||||
|
@ -84,40 +81,39 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
body a{
|
||||
color: #1890ff;
|
||||
&:hover{
|
||||
body a {
|
||||
color: #1890ff;
|
||||
&:hover {
|
||||
color: #40a9ff;
|
||||
}
|
||||
}
|
||||
|
||||
span.fs-icon-svg{
|
||||
span.fs-icon-svg {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ant-btn .fs-icon:last-child{
|
||||
margin-right:0px
|
||||
.ant-btn .fs-icon:last-child {
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.fs-iconify fs-icon{
|
||||
svg{
|
||||
vertical-align:0 !important;
|
||||
.fs-iconify fs-icon {
|
||||
svg {
|
||||
vertical-align: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.fs-button{
|
||||
span{
|
||||
&:first-child{
|
||||
.fs-button {
|
||||
span {
|
||||
&:first-child {
|
||||
margin-right: 5px;
|
||||
}
|
||||
&:last-child{
|
||||
&:last-child {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
.fs-icon,.fs-button-icon{
|
||||
.fs-icon,
|
||||
.fs-button-icon {
|
||||
margin: 0 !important;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
@import './theme/index.less';
|
||||
@import './theme/default.less';
|
||||
@import './scroll.less';
|
||||
@import './transition.less';
|
||||
@import './fix-windicss.less';
|
||||
@import './antdv4.less';
|
||||
@import './certd.less';
|
||||
@import "./theme/index.less";
|
||||
@import "./theme/default.less";
|
||||
@import "./scroll.less";
|
||||
@import "./transition.less";
|
||||
@import "./fix-windicss.less";
|
||||
@import "./antdv4.less";
|
||||
@import "./certd.less";
|
||||
|
||||
html, body {
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
|
@ -15,10 +16,15 @@ html, body {
|
|||
}
|
||||
|
||||
div#app {
|
||||
height: 100%
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin-bottom: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
@ -30,17 +36,14 @@ h1, h2, h3, h4, h5, h6 {
|
|||
margin-right: 5px;
|
||||
}
|
||||
|
||||
|
||||
.ant-btn-link {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
|
||||
.ant-input-affix-wrapper {
|
||||
padding: 4px 11px;
|
||||
}
|
||||
|
||||
|
||||
.anticon {
|
||||
vertical-align: 0 !important;
|
||||
}
|
||||
|
@ -54,17 +57,17 @@ h1, h2, h3, h4, h5, h6 {
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.flex-vc{
|
||||
.flex-vc {
|
||||
align-items: center;
|
||||
}
|
||||
.flex-vb{
|
||||
.flex-vb {
|
||||
align-items: baseline;
|
||||
}
|
||||
.flex-o {
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
}
|
||||
.flex-baseline{
|
||||
.flex-baseline {
|
||||
display: flex !important;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
@ -94,77 +97,76 @@ h1, h2, h3, h4, h5, h6 {
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.align-left{
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
.align-right{
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.scroll-y {
|
||||
overflow-y: auto;
|
||||
|
||||
}
|
||||
.m-0{
|
||||
margin:0 !important;
|
||||
.m-0 {
|
||||
margin: 0 !important;
|
||||
}
|
||||
.m-2{
|
||||
margin:2px !important;
|
||||
.m-2 {
|
||||
margin: 2px !important;
|
||||
}
|
||||
.m-3{
|
||||
margin:3px !important;
|
||||
.m-3 {
|
||||
margin: 3px !important;
|
||||
}
|
||||
.m-5{
|
||||
margin:5px !important;
|
||||
.m-5 {
|
||||
margin: 5px !important;
|
||||
}
|
||||
.m-10 {
|
||||
margin: 10px !important;;
|
||||
margin: 10px !important;
|
||||
}
|
||||
|
||||
.m-20{
|
||||
margin:20px !important;
|
||||
.m-20 {
|
||||
margin: 20px !important;
|
||||
}
|
||||
.mb-2 {
|
||||
margin-bottom: 2px !important;;
|
||||
margin-bottom: 2px !important;
|
||||
}
|
||||
|
||||
.mb-5 {
|
||||
margin-bottom: 5px !important;;
|
||||
margin-bottom: 5px !important;
|
||||
}
|
||||
.ml-5 {
|
||||
margin-left: 5px !important;;
|
||||
margin-left: 5px !important;
|
||||
}
|
||||
|
||||
.ml-10 {
|
||||
margin-left: 10px !important;;
|
||||
margin-left: 10px !important;
|
||||
}
|
||||
|
||||
.ml-20 {
|
||||
margin-left: 20px !important;;
|
||||
margin-left: 20px !important;
|
||||
}
|
||||
|
||||
.ml-15 {
|
||||
margin-left: 15px !important;;
|
||||
margin-left: 15px !important;
|
||||
}
|
||||
|
||||
.mr-5 {
|
||||
margin-right: 5px !important;;
|
||||
margin-right: 5px !important;
|
||||
}
|
||||
|
||||
.mr-10 {
|
||||
margin-right: 10px !important;;
|
||||
margin-right: 10px !important;
|
||||
}
|
||||
|
||||
.mr-20 {
|
||||
margin-right: 20px !important;;
|
||||
margin-right: 20px !important;
|
||||
}
|
||||
|
||||
.mr-15 {
|
||||
margin-right: 15px !important;;
|
||||
margin-right: 15px !important;
|
||||
}
|
||||
|
||||
.mt-5 {
|
||||
margin-top: 5px !important;;
|
||||
margin-top: 5px !important;
|
||||
}
|
||||
|
||||
.mt-10 {
|
||||
|
@ -172,20 +174,19 @@ h1, h2, h3, h4, h5, h6 {
|
|||
}
|
||||
|
||||
.mb-10 {
|
||||
margin-bottom: 10px !important;;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
|
||||
|
||||
.p-5 {
|
||||
padding: 5px !important;;
|
||||
padding: 5px !important;
|
||||
}
|
||||
|
||||
.p-10 {
|
||||
padding: 10px !important;;
|
||||
padding: 10px !important;
|
||||
}
|
||||
|
||||
.p-20 {
|
||||
padding: 20px !important;;
|
||||
padding: 20px !important;
|
||||
}
|
||||
.ellipsis {
|
||||
white-space: nowrap;
|
||||
|
@ -212,7 +213,7 @@ h1, h2, h3, h4, h5, h6 {
|
|||
border-bottom: 1px solid #dedede;
|
||||
}
|
||||
|
||||
.color-plus{
|
||||
.color-plus {
|
||||
color: #c5913f;
|
||||
}
|
||||
.color-blue {
|
||||
|
@ -230,8 +231,8 @@ h1, h2, h3, h4, h5, h6 {
|
|||
color: gray;
|
||||
}
|
||||
|
||||
.iconify{
|
||||
//font-size: 16px;
|
||||
.iconify {
|
||||
//font-size: 16px;
|
||||
}
|
||||
|
||||
.icon-box {
|
||||
|
@ -250,7 +251,6 @@ h1, h2, h3, h4, h5, h6 {
|
|||
color: #c5913f !important;
|
||||
}
|
||||
|
||||
|
||||
.deleted {
|
||||
color: #c7c7c7;
|
||||
//删除线
|
||||
|
@ -268,18 +268,17 @@ h1, h2, h3, h4, h5, h6 {
|
|||
.helper {
|
||||
color: #aeaeae;
|
||||
font-size: 12px;
|
||||
margin-top:3px;
|
||||
margin-bottom:3px;
|
||||
&.error{
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
&.error {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.fs-copyable {
|
||||
display: inline-flex;
|
||||
.text {
|
||||
flex: 1
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.copy-button {
|
||||
|
@ -288,23 +287,20 @@ h1, h2, h3, h4, h5, h6 {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.fs-16{
|
||||
font-size: 16px;
|
||||
.fs-16 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.w-50\%{
|
||||
width: 50%;
|
||||
.w-50\% {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
|
||||
.ant-drawer-content-wrapper {
|
||||
max-width: 90vw;
|
||||
}
|
||||
|
||||
|
||||
.block-title{
|
||||
.block-title {
|
||||
font-size: 14px;
|
||||
padding:10px;
|
||||
color : #6e6e6e;
|
||||
}
|
||||
padding: 10px;
|
||||
color: #6e6e6e;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
img.ant-image-preview-img{
|
||||
img.ant-image-preview-img {
|
||||
display: initial;
|
||||
}
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
|
||||
::-webkit-scrollbar-track {
|
||||
width: 8px;
|
||||
background: rgba(#101F1C, 0.1);
|
||||
background: rgba(#101f1c, 0.1);
|
||||
-webkit-border-radius: 2em;
|
||||
-moz-border-radius: 2em;
|
||||
border-radius: 2em;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
// background-color: rgba(#101F1C, 0.5);
|
||||
// background-color: rgba(#101F1C, 0.5);
|
||||
background-clip: padding-box;
|
||||
min-height: 28px;
|
||||
-webkit-border-radius: 2em;
|
||||
|
@ -23,6 +23,5 @@
|
|||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
|
||||
//background-color: rgba(#101F1C, 1);
|
||||
}
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
.ant-layout{
|
||||
.ant-layout {
|
||||
background-color: @colorPrimaryBg;
|
||||
}
|
||||
.ant-layout-header {
|
||||
background-color: @colorPrimaryBg
|
||||
background-color: @colorPrimaryBg;
|
||||
}
|
||||
.ant-layout-sider {
|
||||
background-color:@colorPrimaryBg
|
||||
}
|
||||
.ant-menu{
|
||||
background-color: @colorPrimaryBg;
|
||||
&.ant-menu-submenu-popup{
|
||||
}
|
||||
.ant-menu {
|
||||
background-color: @colorPrimaryBg;
|
||||
&.ant-menu-submenu-popup {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
.aside-menu{
|
||||
.ant-menu-submenu > .ant-menu{
|
||||
background-color:@colorPrimaryBg
|
||||
.aside-menu {
|
||||
.ant-menu-submenu > .ant-menu {
|
||||
background-color: @colorPrimaryBg;
|
||||
}
|
||||
|
||||
.ant-menu-item-active{
|
||||
.ant-menu-item-active {
|
||||
background-color: @bg-menu-item-color;
|
||||
}
|
||||
.ant-menu-item-selected{
|
||||
.ant-menu-item-selected {
|
||||
background-color: @bg-menu-item-color !important;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
@bg-menu-item-color:hsla(0,0%,100%,.5);
|
||||
@colorPrimaryBg:#ebf1f6;
|
||||
@primary-color: #1890ff;
|
||||
@bg-menu-item-color:hsla (0,0%,100%,.5);
|
||||
@colorPrimaryBg: #ebf1f6;
|
||||
@primary-color: #1890ff;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// 过渡动画 横向渐变
|
||||
.fade-transverse-leave-active,
|
||||
.fade-transverse-enter-active {
|
||||
transition: all .5s;
|
||||
transition: all 0.5s;
|
||||
}
|
||||
.fade-transverse-enter-from {
|
||||
opacity: 0;
|
||||
|
@ -24,7 +24,7 @@
|
|||
// 过渡动画 缩放渐变
|
||||
.fade-scale-leave-active,
|
||||
.fade-scale-enter-active {
|
||||
transition: all .3s;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.fade-scale-enter {
|
||||
opacity: 0;
|
||||
|
|
|
@ -13,7 +13,7 @@ export function useReference(formItem: any) {
|
|||
const ctx = {
|
||||
compute,
|
||||
asyncCompute,
|
||||
computed
|
||||
computed,
|
||||
};
|
||||
const script = formItem.mergeScript;
|
||||
const func = new Function("ctx", script);
|
||||
|
@ -30,7 +30,7 @@ export function useReference(formItem: any) {
|
|||
formItem.helper = {
|
||||
render: () => {
|
||||
return <div innerHTML={helper}></div>;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {forEach} from "lodash-es";
|
||||
import { forEach } from "lodash-es";
|
||||
export function getEnvValue(key: string) {
|
||||
// @ts-ignore
|
||||
return import.meta.env["VITE_APP_" + key];
|
||||
|
|
|
@ -21,5 +21,5 @@ async function open(path: any) {
|
|||
}
|
||||
|
||||
export const routerUtils = {
|
||||
open
|
||||
open,
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export function eachTree(tree: any[], callback: (item: any) => void) {
|
||||
tree.forEach((item) => {
|
||||
tree.forEach(item => {
|
||||
callback(item);
|
||||
if (item.children) {
|
||||
eachTree(item.children, callback);
|
||||
|
@ -19,5 +19,5 @@ export function treeMap(tree: any[], mapFunc: (item: any) => {}) {
|
|||
|
||||
export const treeUtils = {
|
||||
eachTree,
|
||||
treeMap
|
||||
treeMap,
|
||||
};
|
||||
|
|
|
@ -25,12 +25,12 @@ interface Props {
|
|||
}
|
||||
|
||||
defineOptions({
|
||||
name: "AccessControl"
|
||||
name: "AccessControl",
|
||||
});
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
codes: () => [],
|
||||
type: "role"
|
||||
type: "role",
|
||||
});
|
||||
|
||||
const { hasAccessByCodes, hasAccessByRoles } = useAccess();
|
||||
|
|
|
@ -12,7 +12,7 @@ async function generateAccessible(mode: AccessModeType, options: GenerateMenuAnd
|
|||
const root = router.getRoutes().find((item: any) => item.path === "/");
|
||||
|
||||
// 动态添加到router实例内
|
||||
accessibleRoutes.forEach((route) => {
|
||||
accessibleRoutes.forEach(route => {
|
||||
if (root && !route.meta?.noBasicLayout) {
|
||||
// 为了兼容之前的版本用法,如果包含子路由,则将component移除,以免出现多层BasicLayout
|
||||
// 如果你的项目已经跟进了本次修改,移除了所有自定义菜单首级的BasicLayout,可以将这段if代码删除
|
||||
|
@ -62,7 +62,7 @@ async function generateRoutes(mode: AccessModeType, options: GenerateMenuAndRout
|
|||
* 调整路由树,做以下处理:
|
||||
* 1. 对未添加redirect的路由添加redirect
|
||||
*/
|
||||
resultRoutes = mapTree(resultRoutes, (route) => {
|
||||
resultRoutes = mapTree(resultRoutes, route => {
|
||||
// 如果有redirect或者没有子路由,则直接返回
|
||||
if (route.redirect || !route.children || route.children.length === 0) {
|
||||
return route;
|
||||
|
|
|
@ -4,23 +4,17 @@
|
|||
* @Example v-access:role="[ROLE_NAME]" or v-access:role="ROLE_NAME"
|
||||
* @Example v-access:code="[ROLE_CODE]" or v-access:code="ROLE_CODE"
|
||||
*/
|
||||
import type { App, Directive, DirectiveBinding } from 'vue';
|
||||
import type { App, Directive, DirectiveBinding } from "vue";
|
||||
|
||||
import { useAccess } from './use-access';
|
||||
import { useAccess } from "./use-access";
|
||||
|
||||
function isAccessible(
|
||||
el: Element,
|
||||
binding: DirectiveBinding<string | string[]>,
|
||||
) {
|
||||
function isAccessible(el: Element, binding: DirectiveBinding<string | string[]>) {
|
||||
const { accessMode, hasAccessByCodes, hasAccessByRoles } = useAccess();
|
||||
|
||||
const value = binding.value;
|
||||
|
||||
if (!value) return;
|
||||
const authMethod =
|
||||
accessMode.value === 'frontend' && binding.arg === 'role'
|
||||
? hasAccessByRoles
|
||||
: hasAccessByCodes;
|
||||
const authMethod = accessMode.value === "frontend" && binding.arg === "role" ? hasAccessByRoles : hasAccessByCodes;
|
||||
|
||||
const values = Array.isArray(value) ? value : [value];
|
||||
|
||||
|
@ -38,5 +32,5 @@ const authDirective: Directive = {
|
|||
};
|
||||
|
||||
export function registerAccessDirective(app: App) {
|
||||
app.directive('access', authDirective);
|
||||
app.directive("access", authDirective);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export { default as AccessControl } from './access-control.vue';
|
||||
export * from './accessible';
|
||||
export * from './directive';
|
||||
export * from './use-access';
|
||||
export { default as AccessControl } from "./access-control.vue";
|
||||
export * from "./accessible";
|
||||
export * from "./directive";
|
||||
export * from "./use-access";
|
||||
|
|
|
@ -17,7 +17,7 @@ function useAccess() {
|
|||
*/
|
||||
function hasAccessByRoles(roles: string[]) {
|
||||
const userRoleSet = new Set(userStore.userRoles);
|
||||
const intersection = roles.filter((item) => userRoleSet.has(item));
|
||||
const intersection = roles.filter(item => userRoleSet.has(item));
|
||||
return intersection.length > 0;
|
||||
}
|
||||
|
||||
|
@ -29,15 +29,15 @@ function useAccess() {
|
|||
function hasAccessByCodes(codes: string[]) {
|
||||
const userCodesSet = new Set(accessStore.accessCodes);
|
||||
|
||||
const intersection = codes.filter((item) => userCodesSet.has(item));
|
||||
const intersection = codes.filter(item => userCodesSet.has(item));
|
||||
return intersection.length > 0;
|
||||
}
|
||||
|
||||
async function toggleAccessMode() {
|
||||
updatePreferences({
|
||||
app: {
|
||||
accessMode: preferences.app.accessMode === "frontend" ? "backend" : "frontend"
|
||||
}
|
||||
accessMode: preferences.app.accessMode === "frontend" ? "backend" : "frontend",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ function useAccess() {
|
|||
accessMode,
|
||||
hasAccessByCodes,
|
||||
hasAccessByRoles,
|
||||
toggleAccessMode
|
||||
toggleAccessMode,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||
afterFetch: undefined,
|
||||
modelPropName: "modelValue",
|
||||
api: undefined,
|
||||
options: () => []
|
||||
options: () => [],
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -96,13 +96,13 @@ const getOptions = computed(() => {
|
|||
const refOptionsData = unref(refOptions);
|
||||
|
||||
function transformData(data: OptionsItem[]): OptionsItem[] {
|
||||
return data.map((item) => {
|
||||
return data.map(item => {
|
||||
const value = get(item, valueField);
|
||||
return {
|
||||
...objectOmit(item, [labelField, valueField, childrenField]),
|
||||
label: get(item, labelField),
|
||||
value: numberToString ? `${value}` : value,
|
||||
...(childrenField && item[childrenField] ? { children: transformData(item[childrenField]) } : {})
|
||||
...(childrenField && item[childrenField] ? { children: transformData(item[childrenField]) } : {}),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -122,9 +122,9 @@ const bindProps = computed(() => {
|
|||
...objectOmit(attrs, [`onUpdate:${props.modelPropName}`]),
|
||||
...(props.visibleEvent
|
||||
? {
|
||||
[props.visibleEvent]: handleFetchForVisible
|
||||
[props.visibleEvent]: handleFetchForVisible,
|
||||
}
|
||||
: {})
|
||||
: {}),
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
export { default as ApiComponent } from './api-component.vue';
|
||||
export { default as ApiComponent } from "./api-component.vue";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { CaptchaPoint } from '../types';
|
||||
import type { CaptchaPoint } from "../types";
|
||||
|
||||
import { reactive } from 'vue';
|
||||
import { reactive } from "vue";
|
||||
|
||||
export function useCaptchaPoints() {
|
||||
const points = reactive<CaptchaPoint[]>([]);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export { default as PointSelectionCaptcha } from './point-selection-captcha/index.vue';
|
||||
export { default as PointSelectionCaptchaCard } from './point-selection-captcha/index.vue';
|
||||
export { default as PointSelectionCaptcha } from "./point-selection-captcha/index.vue";
|
||||
export { default as PointSelectionCaptchaCard } from "./point-selection-captcha/index.vue";
|
||||
|
||||
export { default as SliderCaptcha } from './slider-captcha/index.vue';
|
||||
export { default as SliderRotateCaptcha } from './slider-rotate-captcha/index.vue';
|
||||
export type * from './types';
|
||||
export { default as SliderCaptcha } from "./slider-captcha/index.vue";
|
||||
export { default as SliderRotateCaptcha } from "./slider-rotate-captcha/index.vue";
|
||||
export type * from "./types";
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
<script setup lang="ts">
|
||||
import type { CaptchaPoint, PointSelectionCaptchaProps } from '../types';
|
||||
import type { CaptchaPoint, PointSelectionCaptchaProps } from "../types";
|
||||
|
||||
import { RotateCw } from '/@/vben/icons';
|
||||
import { $t } from '/@/locales';
|
||||
import { RotateCw } from "/@/vben/icons";
|
||||
import { $t } from "/@/locales";
|
||||
|
||||
import { VbenButton, VbenIconButton } from '/@/vben/shadcn-ui';
|
||||
import { VbenButton, VbenIconButton } from "/@/vben/shadcn-ui";
|
||||
|
||||
import { useCaptchaPoints } from '../hooks/useCaptchaPoints';
|
||||
import CaptchaCard from './point-selection-captcha-card.vue';
|
||||
import { useCaptchaPoints } from "../hooks/useCaptchaPoints";
|
||||
import CaptchaCard from "./point-selection-captcha-card.vue";
|
||||
|
||||
const props = withDefaults(defineProps<PointSelectionCaptchaProps>(), {
|
||||
height: '220px',
|
||||
hintImage: '',
|
||||
hintText: '',
|
||||
paddingX: '12px',
|
||||
paddingY: '16px',
|
||||
height: "220px",
|
||||
hintImage: "",
|
||||
hintText: "",
|
||||
paddingX: "12px",
|
||||
paddingY: "16px",
|
||||
showConfirm: false,
|
||||
title: '',
|
||||
width: '300px',
|
||||
title: "",
|
||||
width: "300px",
|
||||
});
|
||||
const emit = defineEmits<{
|
||||
click: [CaptchaPoint];
|
||||
|
@ -27,7 +27,7 @@ const emit = defineEmits<{
|
|||
const { addPoint, clearPoints, points } = useCaptchaPoints();
|
||||
|
||||
if (!props.hintImage && !props.hintText) {
|
||||
console.warn('At least one of hint image or hint text must be provided');
|
||||
console.warn("At least one of hint image or hint text must be provided");
|
||||
}
|
||||
|
||||
const POINT_OFFSET = 11;
|
||||
|
@ -43,15 +43,15 @@ function getElementPosition(element: HTMLElement) {
|
|||
function handleClick(e: MouseEvent) {
|
||||
try {
|
||||
const dom = e.currentTarget as HTMLElement;
|
||||
if (!dom) throw new Error('Element not found');
|
||||
if (!dom) throw new Error("Element not found");
|
||||
|
||||
const { x: domX, y: domY } = getElementPosition(dom);
|
||||
|
||||
const mouseX = e.clientX + window.scrollX;
|
||||
const mouseY = e.clientY + window.scrollY;
|
||||
|
||||
if (typeof mouseX !== 'number' || typeof mouseY !== 'number') {
|
||||
throw new TypeError('Mouse coordinates not found');
|
||||
if (typeof mouseX !== "number" || typeof mouseY !== "number") {
|
||||
throw new TypeError("Mouse coordinates not found");
|
||||
}
|
||||
|
||||
const xPos = mouseX - domX;
|
||||
|
@ -61,7 +61,7 @@ function handleClick(e: MouseEvent) {
|
|||
|
||||
// 点击位置边界校验
|
||||
if (xPos < 0 || yPos < 0 || xPos > rect.width || yPos > rect.height) {
|
||||
console.warn('Click position is out of the valid range');
|
||||
console.warn("Click position is out of the valid range");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -77,11 +77,11 @@ function handleClick(e: MouseEvent) {
|
|||
|
||||
addPoint(point);
|
||||
|
||||
emit('click', point);
|
||||
emit("click", point);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
} catch (error) {
|
||||
console.error('Error in handleClick:', error);
|
||||
console.error("Error in handleClick:", error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,58 +89,40 @@ function clear() {
|
|||
try {
|
||||
clearPoints();
|
||||
} catch (error) {
|
||||
console.error('Error in clear:', error);
|
||||
console.error("Error in clear:", error);
|
||||
}
|
||||
}
|
||||
|
||||
function handleRefresh() {
|
||||
try {
|
||||
clear();
|
||||
emit('refresh');
|
||||
emit("refresh");
|
||||
} catch (error) {
|
||||
console.error('Error in handleRefresh:', error);
|
||||
console.error("Error in handleRefresh:", error);
|
||||
}
|
||||
}
|
||||
|
||||
function handleConfirm() {
|
||||
if (!props.showConfirm) return;
|
||||
try {
|
||||
emit('confirm', points, clear);
|
||||
emit("confirm", points, clear);
|
||||
} catch (error) {
|
||||
console.error('Error in handleConfirm:', error);
|
||||
console.error("Error in handleConfirm:", error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<CaptchaCard
|
||||
:captcha-image="captchaImage"
|
||||
:height="height"
|
||||
:padding-x="paddingX"
|
||||
:padding-y="paddingY"
|
||||
:title="title"
|
||||
:width="width"
|
||||
@click="handleClick"
|
||||
>
|
||||
<CaptchaCard :captcha-image="captchaImage" :height="height" :padding-x="paddingX" :padding-y="paddingY" :title="title" :width="width" @click="handleClick">
|
||||
<template #title>
|
||||
<slot name="title">{{ $t('ui.captcha.title') }}</slot>
|
||||
<slot name="title">{{ $t("ui.captcha.title") }}</slot>
|
||||
</template>
|
||||
|
||||
<template #extra>
|
||||
<VbenIconButton
|
||||
:aria-label="$t('ui.captcha.refreshAriaLabel')"
|
||||
class="ml-1"
|
||||
@click="handleRefresh"
|
||||
>
|
||||
<VbenIconButton :aria-label="$t('ui.captcha.refreshAriaLabel')" class="ml-1" @click="handleRefresh">
|
||||
<RotateCw class="size-5" />
|
||||
</VbenIconButton>
|
||||
<VbenButton
|
||||
v-if="showConfirm"
|
||||
:aria-label="$t('ui.captcha.confirmAriaLabel')"
|
||||
class="ml-2"
|
||||
size="sm"
|
||||
@click="handleConfirm"
|
||||
>
|
||||
{{ $t('ui.captcha.confirm') }}
|
||||
<VbenButton v-if="showConfirm" :aria-label="$t('ui.captcha.confirmAriaLabel')" class="ml-2" size="sm" @click="handleConfirm">
|
||||
{{ $t("ui.captcha.confirm") }}
|
||||
</VbenButton>
|
||||
</template>
|
||||
|
||||
|
@ -159,17 +141,9 @@ function handleConfirm() {
|
|||
{{ index + 1 }}
|
||||
</div>
|
||||
<template #footer>
|
||||
<img
|
||||
v-if="hintImage"
|
||||
:alt="$t('ui.captcha.alt')"
|
||||
:src="hintImage"
|
||||
class="border-border h-10 w-full rounded border"
|
||||
/>
|
||||
<div
|
||||
v-else-if="hintText"
|
||||
class="border-border flex-center h-10 w-full rounded border"
|
||||
>
|
||||
{{ `${$t('ui.captcha.clickInOrder')}` + `【${hintText}】` }}
|
||||
<img v-if="hintImage" :alt="$t('ui.captcha.alt')" :src="hintImage" class="border-border h-10 w-full rounded border" />
|
||||
<div v-else-if="hintText" class="border-border flex-center h-10 w-full rounded border">
|
||||
{{ `${$t("ui.captcha.clickInOrder")}` + `【${hintText}】` }}
|
||||
</div>
|
||||
</template>
|
||||
</CaptchaCard>
|
||||
|
|
|
@ -1,24 +1,18 @@
|
|||
<script setup lang="ts">
|
||||
import type { PointSelectionCaptchaCardProps } from '../types';
|
||||
import type { PointSelectionCaptchaCardProps } from "../types";
|
||||
|
||||
import { computed } from 'vue';
|
||||
import { computed } from "vue";
|
||||
|
||||
import { $t } from '/@/locales';
|
||||
import { $t } from "/@/locales";
|
||||
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '/@/vben/shadcn-ui';
|
||||
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "/@/vben/shadcn-ui";
|
||||
|
||||
const props = withDefaults(defineProps<PointSelectionCaptchaCardProps>(), {
|
||||
height: '220px',
|
||||
paddingX: '12px',
|
||||
paddingY: '16px',
|
||||
title: '',
|
||||
width: '300px',
|
||||
height: "220px",
|
||||
paddingX: "12px",
|
||||
paddingY: "16px",
|
||||
title: "",
|
||||
width: "300px",
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -26,7 +20,7 @@ const emit = defineEmits<{
|
|||
}>();
|
||||
|
||||
const parseValue = (value: number | string) => {
|
||||
if (typeof value === 'number') {
|
||||
if (typeof value === "number") {
|
||||
return value;
|
||||
}
|
||||
const parsed = Number.parseFloat(value);
|
||||
|
@ -46,7 +40,7 @@ const captchaStyles = computed(() => {
|
|||
});
|
||||
|
||||
function handleClick(e: MouseEvent) {
|
||||
emit('click', e);
|
||||
emit("click", e);
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
|
@ -54,7 +48,7 @@ function handleClick(e: MouseEvent) {
|
|||
<CardHeader class="p-0">
|
||||
<CardTitle id="captcha-title" class="flex items-center justify-between">
|
||||
<template v-if="$slots.title">
|
||||
<slot name="title">{{ $t('ui.captcha.title') }}</slot>
|
||||
<slot name="title">{{ $t("ui.captcha.title") }}</slot>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>{{ title }}</span>
|
||||
|
@ -65,14 +59,7 @@ function handleClick(e: MouseEvent) {
|
|||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent class="relative mt-2 flex w-full overflow-hidden rounded p-0">
|
||||
<img
|
||||
v-show="captchaImage"
|
||||
:alt="$t('ui.captcha.alt')"
|
||||
:src="captchaImage"
|
||||
:style="captchaStyles"
|
||||
class="relative z-10"
|
||||
@click="handleClick"
|
||||
/>
|
||||
<img v-show="captchaImage" :alt="$t('ui.captcha.alt')" :src="captchaImage" :style="captchaStyles" class="relative z-10" @click="handleClick" />
|
||||
<div class="absolute inset-0">
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
|
|
@ -1,29 +1,25 @@
|
|||
<script setup lang="ts">
|
||||
import type {
|
||||
CaptchaVerifyPassingData,
|
||||
SliderCaptchaProps,
|
||||
SliderRotateVerifyPassingData,
|
||||
} from '../types';
|
||||
import type { CaptchaVerifyPassingData, SliderCaptchaProps, SliderRotateVerifyPassingData } from "../types";
|
||||
|
||||
import { reactive, unref, useTemplateRef, watch, watchEffect } from 'vue';
|
||||
import { reactive, unref, useTemplateRef, watch, watchEffect } from "vue";
|
||||
|
||||
import { $t } from '/@/locales';
|
||||
import { $t } from "/@/locales";
|
||||
|
||||
import { cn } from '/@/vben/shared/utils';
|
||||
import { cn } from "/@/vben/shared/utils";
|
||||
|
||||
import { useTimeoutFn } from '@vueuse/core';
|
||||
import { useTimeoutFn } from "@vueuse/core";
|
||||
|
||||
import SliderCaptchaAction from './slider-captcha-action.vue';
|
||||
import SliderCaptchaBar from './slider-captcha-bar.vue';
|
||||
import SliderCaptchaContent from './slider-captcha-content.vue';
|
||||
import SliderCaptchaAction from "./slider-captcha-action.vue";
|
||||
import SliderCaptchaBar from "./slider-captcha-bar.vue";
|
||||
import SliderCaptchaContent from "./slider-captcha-content.vue";
|
||||
|
||||
const props = withDefaults(defineProps<SliderCaptchaProps>(), {
|
||||
actionStyle: () => ({}),
|
||||
barStyle: () => ({}),
|
||||
contentStyle: () => ({}),
|
||||
isSlot: false,
|
||||
successText: '',
|
||||
text: '',
|
||||
successText: "",
|
||||
text: "",
|
||||
wrapperStyle: () => ({}),
|
||||
});
|
||||
|
||||
|
@ -49,21 +45,21 @@ defineExpose({
|
|||
resume,
|
||||
});
|
||||
|
||||
const wrapperRef = useTemplateRef<HTMLDivElement>('wrapperRef');
|
||||
const barRef = useTemplateRef<typeof SliderCaptchaBar>('barRef');
|
||||
const contentRef = useTemplateRef<typeof SliderCaptchaContent>('contentRef');
|
||||
const actionRef = useTemplateRef<typeof SliderCaptchaAction>('actionRef');
|
||||
const wrapperRef = useTemplateRef<HTMLDivElement>("wrapperRef");
|
||||
const barRef = useTemplateRef<typeof SliderCaptchaBar>("barRef");
|
||||
const contentRef = useTemplateRef<typeof SliderCaptchaContent>("contentRef");
|
||||
const actionRef = useTemplateRef<typeof SliderCaptchaAction>("actionRef");
|
||||
|
||||
watch(
|
||||
() => state.isPassing,
|
||||
(isPassing) => {
|
||||
isPassing => {
|
||||
if (isPassing) {
|
||||
const { endTime, startTime } = state;
|
||||
const time = (endTime - startTime) / 1000;
|
||||
emit('success', { isPassing, time: time.toFixed(1) });
|
||||
emit("success", { isPassing, time: time.toFixed(1) });
|
||||
modelValue.value = isPassing;
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
watchEffect(() => {
|
||||
|
@ -71,9 +67,9 @@ watchEffect(() => {
|
|||
});
|
||||
|
||||
function getEventPageX(e: MouseEvent | TouchEvent): number {
|
||||
if ('pageX' in e) {
|
||||
if ("pageX" in e) {
|
||||
return e.pageX;
|
||||
} else if ('touches' in e && e.touches[0]) {
|
||||
} else if ("touches" in e && e.touches[0]) {
|
||||
return e.touches[0].pageX;
|
||||
}
|
||||
return 0;
|
||||
|
@ -84,14 +80,9 @@ function handleDragStart(e: MouseEvent | TouchEvent) {
|
|||
return;
|
||||
}
|
||||
if (!actionRef.value) return;
|
||||
emit('start', e);
|
||||
emit("start", e);
|
||||
|
||||
state.moveDistance =
|
||||
getEventPageX(e) -
|
||||
Number.parseInt(
|
||||
actionRef.value.getStyle().left.replace('px', '') || '0',
|
||||
10,
|
||||
);
|
||||
state.moveDistance = getEventPageX(e) - Number.parseInt(actionRef.value.getStyle().left.replace("px", "") || "0", 10);
|
||||
state.startTime = Date.now();
|
||||
state.isMoving = true;
|
||||
}
|
||||
|
@ -112,7 +103,7 @@ function handleDragMoving(e: MouseEvent | TouchEvent) {
|
|||
const { actionWidth, offset, wrapperWidth } = getOffset(actionEl.getEl());
|
||||
const moveX = getEventPageX(e) - moveDistance;
|
||||
|
||||
emit('move', {
|
||||
emit("move", {
|
||||
event: e,
|
||||
moveDistance,
|
||||
moveX,
|
||||
|
@ -133,7 +124,7 @@ function handleDragMoving(e: MouseEvent | TouchEvent) {
|
|||
function handleDragOver(e: MouseEvent | TouchEvent) {
|
||||
const { isMoving, isPassing, moveDistance } = state;
|
||||
if (isMoving && !isPassing) {
|
||||
emit('end', e);
|
||||
emit("end", e);
|
||||
const actionEl = actionRef.value;
|
||||
const barEl = unref(barRef);
|
||||
if (!actionEl || !barEl) return;
|
||||
|
@ -185,12 +176,12 @@ function resume() {
|
|||
const contentEl = unref(contentRef);
|
||||
if (!actionEl || !barEl || !contentEl) return;
|
||||
|
||||
contentEl.getEl().style.width = '100%';
|
||||
contentEl.getEl().style.width = "100%";
|
||||
state.toLeft = true;
|
||||
useTimeoutFn(() => {
|
||||
state.toLeft = false;
|
||||
actionEl.setLeft('0');
|
||||
barEl.setWidth('0');
|
||||
actionEl.setLeft("0");
|
||||
barEl.setWidth("0");
|
||||
}, 300);
|
||||
}
|
||||
</script>
|
||||
|
@ -198,12 +189,7 @@ function resume() {
|
|||
<template>
|
||||
<div
|
||||
ref="wrapperRef"
|
||||
:class="
|
||||
cn(
|
||||
'border-border bg-background-deep relative flex h-10 w-full items-center overflow-hidden rounded-md border text-center',
|
||||
props.class,
|
||||
)
|
||||
"
|
||||
:class="cn('border-border bg-background-deep relative flex h-10 w-full items-center overflow-hidden rounded-md border text-center', props.class)"
|
||||
:style="wrapperStyle"
|
||||
@mouseleave="handleDragOver"
|
||||
@mousemove="handleDragMoving"
|
||||
|
@ -211,31 +197,14 @@ function resume() {
|
|||
@touchend="handleDragOver"
|
||||
@touchmove="handleDragMoving"
|
||||
>
|
||||
<SliderCaptchaBar
|
||||
ref="barRef"
|
||||
:bar-style="barStyle"
|
||||
:to-left="state.toLeft"
|
||||
/>
|
||||
<SliderCaptchaContent
|
||||
ref="contentRef"
|
||||
:content-style="contentStyle"
|
||||
:is-passing="state.isPassing"
|
||||
:success-text="successText || $t('ui.captcha.sliderSuccessText')"
|
||||
:text="text || $t('ui.captcha.sliderDefaultText')"
|
||||
>
|
||||
<SliderCaptchaBar ref="barRef" :bar-style="barStyle" :to-left="state.toLeft" />
|
||||
<SliderCaptchaContent ref="contentRef" :content-style="contentStyle" :is-passing="state.isPassing" :success-text="successText || $t('ui.captcha.sliderSuccessText')" :text="text || $t('ui.captcha.sliderDefaultText')">
|
||||
<template v-if="$slots.text" #text>
|
||||
<slot :is-passing="state.isPassing" name="text"></slot>
|
||||
</template>
|
||||
</SliderCaptchaContent>
|
||||
|
||||
<SliderCaptchaAction
|
||||
ref="actionRef"
|
||||
:action-style="actionStyle"
|
||||
:is-passing="state.isPassing"
|
||||
:to-left="state.toLeft"
|
||||
@mousedown="handleDragStart"
|
||||
@touchstart="handleDragStart"
|
||||
>
|
||||
<SliderCaptchaAction ref="actionRef" :action-style="actionStyle" :is-passing="state.isPassing" :to-left="state.toLeft" @mousedown="handleDragStart" @touchstart="handleDragStart">
|
||||
<template v-if="$slots.actionIcon" #icon>
|
||||
<slot :is-passing="state.isPassing" name="actionIcon"></slot>
|
||||
</template>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import type { CSSProperties } from 'vue';
|
||||
import type { CSSProperties } from "vue";
|
||||
|
||||
import { computed, ref, useTemplateRef } from 'vue';
|
||||
import { computed, ref, useTemplateRef } from "vue";
|
||||
|
||||
import { Check, ChevronsRight } from '/@/vben/icons';
|
||||
import { Check, ChevronsRight } from "/@/vben/icons";
|
||||
|
||||
import { Slot } from '/@/vben/shadcn-ui';
|
||||
import { Slot } from "/@/vben/shadcn-ui";
|
||||
|
||||
const props = defineProps<{
|
||||
actionStyle: CSSProperties;
|
||||
|
@ -13,9 +13,9 @@ const props = defineProps<{
|
|||
toLeft: boolean;
|
||||
}>();
|
||||
|
||||
const actionRef = useTemplateRef<HTMLDivElement>('actionRef');
|
||||
const actionRef = useTemplateRef<HTMLDivElement>("actionRef");
|
||||
|
||||
const left = ref('0');
|
||||
const left = ref("0");
|
||||
|
||||
const style = computed(() => {
|
||||
const { actionStyle } = props;
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
<script setup lang="ts">
|
||||
import type { CSSProperties } from 'vue';
|
||||
import type { CSSProperties } from "vue";
|
||||
|
||||
import { computed, ref, useTemplateRef } from 'vue';
|
||||
import { computed, ref, useTemplateRef } from "vue";
|
||||
|
||||
const props = defineProps<{
|
||||
barStyle: CSSProperties;
|
||||
toLeft: boolean;
|
||||
}>();
|
||||
|
||||
const barRef = useTemplateRef<HTMLDivElement>('barRef');
|
||||
const barRef = useTemplateRef<HTMLDivElement>("barRef");
|
||||
|
||||
const width = ref('0');
|
||||
const width = ref("0");
|
||||
|
||||
const style = computed(() => {
|
||||
const { barStyle } = props;
|
||||
|
@ -31,10 +31,5 @@ defineExpose({
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
ref="barRef"
|
||||
:class="toLeft && 'transition-width !w-0 duration-300'"
|
||||
:style="style"
|
||||
class="bg-success absolute h-full"
|
||||
></div>
|
||||
<div ref="barRef" :class="toLeft && 'transition-width !w-0 duration-300'" :style="style" class="bg-success absolute h-full"></div>
|
||||
</template>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import type { CSSProperties } from 'vue';
|
||||
import type { CSSProperties } from "vue";
|
||||
|
||||
import { computed, useTemplateRef } from 'vue';
|
||||
import { computed, useTemplateRef } from "vue";
|
||||
|
||||
import { VbenSpineText } from '/@/vben/shadcn-ui';
|
||||
import { VbenSpineText } from "/@/vben/shadcn-ui";
|
||||
|
||||
const props = defineProps<{
|
||||
contentStyle: CSSProperties;
|
||||
|
@ -12,7 +12,7 @@ const props = defineProps<{
|
|||
text: string;
|
||||
}>();
|
||||
|
||||
const contentRef = useTemplateRef<HTMLDivElement>('contentRef');
|
||||
const contentRef = useTemplateRef<HTMLDivElement>("contentRef");
|
||||
|
||||
const style = computed(() => {
|
||||
const { contentStyle } = props;
|
||||
|
|
|
@ -1,33 +1,28 @@
|
|||
<script setup lang="ts">
|
||||
import type {
|
||||
CaptchaVerifyPassingData,
|
||||
SliderCaptchaActionType,
|
||||
SliderRotateCaptchaProps,
|
||||
SliderRotateVerifyPassingData,
|
||||
} from '../types';
|
||||
import type { CaptchaVerifyPassingData, SliderCaptchaActionType, SliderRotateCaptchaProps, SliderRotateVerifyPassingData } from "../types";
|
||||
|
||||
import { computed, reactive, unref, useTemplateRef, watch } from 'vue';
|
||||
import { computed, reactive, unref, useTemplateRef, watch } from "vue";
|
||||
|
||||
import { $t } from '/@/locales';
|
||||
import { $t } from "/@/locales";
|
||||
|
||||
import { useTimeoutFn } from '@vueuse/core';
|
||||
import { useTimeoutFn } from "@vueuse/core";
|
||||
|
||||
import SliderCaptcha from '../slider-captcha/index.vue';
|
||||
import SliderCaptcha from "../slider-captcha/index.vue";
|
||||
|
||||
const props = withDefaults(defineProps<SliderRotateCaptchaProps>(), {
|
||||
defaultTip: '',
|
||||
defaultTip: "",
|
||||
diffDegree: 20,
|
||||
imageSize: 260,
|
||||
maxDegree: 300,
|
||||
minDegree: 120,
|
||||
src: '',
|
||||
src: "",
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
success: [CaptchaVerifyPassingData];
|
||||
}>();
|
||||
|
||||
const slideBarRef = useTemplateRef<SliderCaptchaActionType>('slideBarRef');
|
||||
const slideBarRef = useTemplateRef<SliderCaptchaActionType>("slideBarRef");
|
||||
|
||||
const state = reactive({
|
||||
currentRotate: 0,
|
||||
|
@ -45,14 +40,14 @@ const modalValue = defineModel<boolean>({ default: false });
|
|||
|
||||
watch(
|
||||
() => state.isPassing,
|
||||
(isPassing) => {
|
||||
isPassing => {
|
||||
if (isPassing) {
|
||||
const { endTime, startTime } = state;
|
||||
const time = (endTime - startTime) / 1000;
|
||||
emit('success', { isPassing, time: time.toFixed(1) });
|
||||
emit("success", { isPassing, time: time.toFixed(1) });
|
||||
}
|
||||
modalValue.value = isPassing;
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const getImgWrapStyleRef = computed(() => {
|
||||
|
@ -67,7 +62,7 @@ const getImgWrapStyleRef = computed(() => {
|
|||
const getFactorRef = computed(() => {
|
||||
const { maxDegree, minDegree } = props;
|
||||
if (minDegree > maxDegree) {
|
||||
console.warn('minDegree should not be greater than maxDegree');
|
||||
console.warn("minDegree should not be greater than maxDegree");
|
||||
}
|
||||
|
||||
if (minDegree === maxDegree) {
|
||||
|
@ -88,18 +83,14 @@ function handleDragBarMove(data: SliderRotateVerifyPassingData) {
|
|||
if (denominator === 0) {
|
||||
return;
|
||||
}
|
||||
const currentRotate = Math.ceil(
|
||||
(moveX / denominator) * 1.5 * maxDegree! * unref(getFactorRef),
|
||||
);
|
||||
const currentRotate = Math.ceil((moveX / denominator) * 1.5 * maxDegree! * unref(getFactorRef));
|
||||
state.currentRotate = currentRotate;
|
||||
setImgRotate(state.randomRotate - currentRotate);
|
||||
}
|
||||
|
||||
function handleImgOnLoad() {
|
||||
const { maxDegree, minDegree } = props;
|
||||
const ranRotate = Math.floor(
|
||||
minDegree! + Math.random() * (maxDegree! - minDegree!),
|
||||
); // 生成随机角度
|
||||
const ranRotate = Math.floor(minDegree! + Math.random() * (maxDegree! - minDegree!)); // 生成随机角度
|
||||
state.randomRotate = ranRotate;
|
||||
setImgRotate(ranRotate);
|
||||
}
|
||||
|
@ -147,15 +138,11 @@ function resume() {
|
|||
}
|
||||
|
||||
const imgCls = computed(() => {
|
||||
return state.toOrigin ? ['transition-transform duration-300'] : [];
|
||||
return state.toOrigin ? ["transition-transform duration-300"] : [];
|
||||
});
|
||||
|
||||
const verifyTip = computed(() => {
|
||||
return state.isPassing
|
||||
? $t('ui.captcha.sliderRotateSuccessTip', [
|
||||
((state.endTime - state.startTime) / 1000).toFixed(1),
|
||||
])
|
||||
: $t('ui.captcha.sliderRotateFailTip');
|
||||
return state.isPassing ? $t("ui.captcha.sliderRotateSuccessTip", [((state.endTime - state.startTime) / 1000).toFixed(1)]) : $t("ui.captcha.sliderRotateFailTip");
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
|
@ -165,22 +152,9 @@ defineExpose({
|
|||
|
||||
<template>
|
||||
<div class="relative flex flex-col items-center">
|
||||
<div
|
||||
:style="getImgWrapStyleRef"
|
||||
class="border-border relative cursor-pointer overflow-hidden rounded-full border shadow-md"
|
||||
>
|
||||
<img
|
||||
:class="imgCls"
|
||||
:src="src"
|
||||
:style="state.imgStyle"
|
||||
alt="verify"
|
||||
class="w-full rounded-full"
|
||||
@click="resume"
|
||||
@load="handleImgOnLoad"
|
||||
/>
|
||||
<div
|
||||
class="absolute bottom-3 left-0 z-10 block h-7 w-full text-center text-xs leading-[30px] text-white"
|
||||
>
|
||||
<div :style="getImgWrapStyleRef" class="border-border relative cursor-pointer overflow-hidden rounded-full border shadow-md">
|
||||
<img :class="imgCls" :src="src" :style="state.imgStyle" alt="verify" class="w-full rounded-full" @click="resume" @load="handleImgOnLoad" />
|
||||
<div class="absolute bottom-3 left-0 z-10 block h-7 w-full text-center text-xs leading-[30px] text-white">
|
||||
<div
|
||||
v-if="state.showTip"
|
||||
:class="{
|
||||
|
@ -191,20 +165,12 @@ defineExpose({
|
|||
{{ verifyTip }}
|
||||
</div>
|
||||
<div v-if="!state.dragging" class="bg-black/30">
|
||||
{{ defaultTip || $t('ui.captcha.sliderRotateDefaultTip') }}
|
||||
{{ defaultTip || $t("ui.captcha.sliderRotateDefaultTip") }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SliderCaptcha
|
||||
ref="slideBarRef"
|
||||
v-model="modalValue"
|
||||
class="mt-5"
|
||||
is-slot
|
||||
@end="handleDragEnd"
|
||||
@move="handleDragBarMove"
|
||||
@start="handleStart"
|
||||
>
|
||||
<SliderCaptcha ref="slideBarRef" v-model="modalValue" class="mt-5" is-slot @end="handleDragEnd" @move="handleDragBarMove" @start="handleStart">
|
||||
<template v-for="(_, key) in $slots" :key="key" #[key]="slotProps">
|
||||
<slot :name="key" v-bind="slotProps"></slot>
|
||||
</template>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { CSSProperties } from 'vue';
|
||||
import type { CSSProperties } from "vue";
|
||||
|
||||
import type { ClassType } from '/@/vben/types';
|
||||
import type { ClassType } from "/@/vben/types";
|
||||
|
||||
export interface CaptchaData {
|
||||
/**
|
||||
|
@ -54,8 +54,7 @@ export interface PointSelectionCaptchaCardProps {
|
|||
width?: number | string;
|
||||
}
|
||||
|
||||
export interface PointSelectionCaptchaProps
|
||||
extends PointSelectionCaptchaCardProps {
|
||||
export interface PointSelectionCaptchaProps extends PointSelectionCaptchaCardProps {
|
||||
/**
|
||||
* 是否展示确定按钮
|
||||
* @default false
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
<script lang="ts" setup>
|
||||
import type { ColPageProps } from './types';
|
||||
import type { ColPageProps } from "./types";
|
||||
|
||||
import { computed, ref, useSlots } from 'vue';
|
||||
import { computed, ref, useSlots } from "vue";
|
||||
|
||||
import {
|
||||
ResizableHandle,
|
||||
ResizablePanel,
|
||||
ResizablePanelGroup,
|
||||
} from '/@/vben/shadcn-ui';
|
||||
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "/@/vben/shadcn-ui";
|
||||
|
||||
import Page from '../page/page.vue';
|
||||
import Page from "../page/page.vue";
|
||||
|
||||
defineOptions({
|
||||
name: 'ColPage',
|
||||
name: "ColPage",
|
||||
inheritAttrs: false,
|
||||
});
|
||||
|
||||
|
@ -33,7 +29,7 @@ const delegatedSlots = computed(() => {
|
|||
const resultSlots: string[] = [];
|
||||
|
||||
for (const key of Object.keys(slots)) {
|
||||
if (!['default', 'left'].includes(key)) {
|
||||
if (!["default", "left"].includes(key)) {
|
||||
resultSlots.push(key);
|
||||
}
|
||||
}
|
||||
|
@ -58,23 +54,12 @@ defineExpose({
|
|||
<template>
|
||||
<Page v-bind="delegatedProps">
|
||||
<!-- 继承默认的slot -->
|
||||
<template
|
||||
v-for="slotName in delegatedSlots"
|
||||
:key="slotName"
|
||||
#[slotName]="slotProps"
|
||||
>
|
||||
<template v-for="slotName in delegatedSlots" :key="slotName" #[slotName]="slotProps">
|
||||
<slot :name="slotName" v-bind="slotProps"></slot>
|
||||
</template>
|
||||
|
||||
<ResizablePanelGroup class="w-full" direction="horizontal">
|
||||
<ResizablePanel
|
||||
ref="leftPanelRef"
|
||||
:collapsed-size="leftCollapsedWidth"
|
||||
:collapsible="leftCollapsible"
|
||||
:default-size="leftWidth"
|
||||
:max-size="leftMaxWidth"
|
||||
:min-size="leftMinWidth"
|
||||
>
|
||||
<ResizablePanel ref="leftPanelRef" :collapsed-size="leftCollapsedWidth" :collapsible="leftCollapsible" :default-size="leftWidth" :max-size="leftMaxWidth" :min-size="leftMinWidth">
|
||||
<template #default="slotProps">
|
||||
<slot
|
||||
name="left"
|
||||
|
@ -86,18 +71,8 @@ defineExpose({
|
|||
></slot>
|
||||
</template>
|
||||
</ResizablePanel>
|
||||
<ResizableHandle
|
||||
v-if="resizable"
|
||||
:style="{ backgroundColor: splitLine ? undefined : 'transparent' }"
|
||||
:with-handle="splitHandle"
|
||||
/>
|
||||
<ResizablePanel
|
||||
:collapsed-size="rightCollapsedWidth"
|
||||
:collapsible="rightCollapsible"
|
||||
:default-size="rightWidth"
|
||||
:max-size="rightMaxWidth"
|
||||
:min-size="rightMinWidth"
|
||||
>
|
||||
<ResizableHandle v-if="resizable" :style="{ backgroundColor: splitLine ? undefined : 'transparent' }" :with-handle="splitHandle" />
|
||||
<ResizablePanel :collapsed-size="rightCollapsedWidth" :collapsible="rightCollapsible" :default-size="rightWidth" :max-size="rightMaxWidth" :min-size="rightMinWidth">
|
||||
<template #default>
|
||||
<slot></slot>
|
||||
</template>
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
export { default as ColPage } from './col-page.vue';
|
||||
export * from './types';
|
||||
export { default as ColPage } from "./col-page.vue";
|
||||
export * from "./types";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { PageProps } from '../page/types';
|
||||
import type { PageProps } from "../page/types";
|
||||
|
||||
export interface ColPageProps extends PageProps {
|
||||
/**
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
<script lang="ts" setup>
|
||||
import type { CountToProps } from './types';
|
||||
import type { CountToProps } from "./types";
|
||||
|
||||
import { computed, onMounted, ref, watch } from 'vue';
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
|
||||
import { isString } from '/@/vben/shared/utils';
|
||||
import { isString } from "/@/vben/shared/utils";
|
||||
|
||||
import { TransitionPresets, useTransition } from '@vueuse/core';
|
||||
import { TransitionPresets, useTransition } from "@vueuse/core";
|
||||
|
||||
const props = withDefaults(defineProps<CountToProps>(), {
|
||||
startVal: 0,
|
||||
duration: 2000,
|
||||
separator: ',',
|
||||
decimal: '.',
|
||||
separator: ",",
|
||||
decimal: ".",
|
||||
decimals: 0,
|
||||
delay: 0,
|
||||
transition: () => TransitionPresets.easeOutExpo,
|
||||
});
|
||||
|
||||
const emit = defineEmits(['started', 'finished']);
|
||||
const emit = defineEmits(["started", "finished"]);
|
||||
|
||||
const lastValue = ref(props.startVal);
|
||||
|
||||
|
@ -27,9 +27,9 @@ onMounted(() => {
|
|||
|
||||
watch(
|
||||
() => props.endVal,
|
||||
(val) => {
|
||||
val => {
|
||||
lastValue.value = val;
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const currentValue = useTransition(lastValue, {
|
||||
|
@ -37,62 +37,43 @@ const currentValue = useTransition(lastValue, {
|
|||
duration: computed(() => props.duration),
|
||||
disabled: computed(() => props.disabled),
|
||||
transition: computed(() => {
|
||||
return isString(props.transition)
|
||||
? TransitionPresets[props.transition]
|
||||
: props.transition;
|
||||
return isString(props.transition) ? TransitionPresets[props.transition] : props.transition;
|
||||
}),
|
||||
onStarted() {
|
||||
emit('started');
|
||||
emit("started");
|
||||
},
|
||||
onFinished() {
|
||||
emit('finished');
|
||||
emit("finished");
|
||||
},
|
||||
});
|
||||
|
||||
const numMain = computed(() => {
|
||||
const result = currentValue.value
|
||||
.toFixed(props.decimals)
|
||||
.split('.')[0]
|
||||
.split(".")[0]
|
||||
?.replaceAll(/\B(?=(\d{3})+(?!\d))/g, props.separator);
|
||||
return result;
|
||||
});
|
||||
|
||||
const numDec = computed(() => {
|
||||
return (
|
||||
props.decimal + currentValue.value.toFixed(props.decimals).split('.')[1]
|
||||
);
|
||||
return props.decimal + currentValue.value.toFixed(props.decimals).split(".")[1];
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="count-to" v-bind="$attrs">
|
||||
<slot name="prefix">
|
||||
<div
|
||||
class="count-to-prefix"
|
||||
:style="prefixStyle"
|
||||
:class="prefixClass"
|
||||
v-if="prefix"
|
||||
>
|
||||
<div v-if="prefix" class="count-to-prefix" :style="prefixStyle" :class="prefixClass">
|
||||
{{ prefix }}
|
||||
</div>
|
||||
</slot>
|
||||
<div class="count-to-main" :class="mainClass" :style="mainStyle">
|
||||
<span>{{ numMain }}</span>
|
||||
<span
|
||||
class="count-to-main-decimal"
|
||||
v-if="decimals > 0"
|
||||
:class="decimalClass"
|
||||
:style="decimalStyle"
|
||||
>
|
||||
<span v-if="decimals > 0" class="count-to-main-decimal" :class="decimalClass" :style="decimalStyle">
|
||||
{{ numDec }}
|
||||
</span>
|
||||
</div>
|
||||
<slot name="suffix">
|
||||
<div
|
||||
class="count-to-suffix"
|
||||
:style="suffixStyle"
|
||||
:class="suffixClass"
|
||||
v-if="suffix"
|
||||
>
|
||||
<div v-if="suffix" class="count-to-suffix" :style="suffixStyle" :class="suffixClass">
|
||||
{{ suffix }}
|
||||
</div>
|
||||
</slot>
|
||||
|
@ -112,7 +93,7 @@ const numDec = computed(() => {
|
|||
}
|
||||
|
||||
&-main {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
|
||||
// font-size: 1.5rem;
|
||||
|
||||
&-decimal {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue