mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-06 00:18:51 +08:00
refactor: use setup refactor
This commit is contained in:
parent
8f6986608d
commit
d4302627e8
41
src/App.vue
41
src/App.vue
@ -1,28 +1,25 @@
|
|||||||
<template>
|
<script setup lang="ts">
|
||||||
<el-config-provider :locale="currentLocale">
|
import { getCurrentInstance } from "vue";
|
||||||
<router-view />
|
|
||||||
</el-config-provider>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { ElConfigProvider } from "element-plus";
|
import { ElConfigProvider } from "element-plus";
|
||||||
import zhCn from "element-plus/lib/locale/lang/zh-cn";
|
import zhCn from "element-plus/lib/locale/lang/zh-cn";
|
||||||
import en from "element-plus/lib/locale/lang/en";
|
import en from "element-plus/lib/locale/lang/en";
|
||||||
export default {
|
|
||||||
name: "app",
|
let locale: string =
|
||||||
components: {
|
getCurrentInstance().appContext.config.globalProperties.$storage?.locale
|
||||||
[ElConfigProvider.name]: ElConfigProvider
|
?.locale;
|
||||||
},
|
|
||||||
computed: {
|
let currentLocale = () => {
|
||||||
// eslint-disable-next-line vue/return-in-computed-property
|
switch (locale) {
|
||||||
currentLocale() {
|
case "zh":
|
||||||
switch (this.$storage.locale?.locale) {
|
return zhCn;
|
||||||
case "zh":
|
case "en":
|
||||||
return zhCn;
|
return en;
|
||||||
case "en":
|
|
||||||
return en;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-config-provider :locale="currentLocale()">
|
||||||
|
<router-view />
|
||||||
|
</el-config-provider>
|
||||||
|
</template>
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useFullscreen } from "@vueuse/core";
|
||||||
|
|
||||||
|
const { isFullscreen, toggle } = useFullscreen();
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="screen-full" @click="toggle">
|
<div class="screen-full" @click="toggle">
|
||||||
<i
|
<i
|
||||||
@ -15,23 +21,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import { useFullscreen } from "@vueuse/core";
|
|
||||||
import { defineComponent } from "vue";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "screenfull",
|
|
||||||
setup() {
|
|
||||||
const { isFullscreen, toggle } = useFullscreen();
|
|
||||||
|
|
||||||
return {
|
|
||||||
isFullscreen,
|
|
||||||
toggle
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.screen-full {
|
.screen-full {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
|
@ -1,47 +1,40 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: "reEditor"
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, onBeforeUnmount, ref, unref } from "vue";
|
||||||
|
import WangEditor from "wangeditor";
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
const editor = ref<ComponentRef>(null);
|
||||||
|
const html = ref<HTMLElement>(null);
|
||||||
|
let instance: WangEditor;
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
instance = new WangEditor(unref(editor));
|
||||||
|
Object.assign(instance.config, {
|
||||||
|
onchange() {
|
||||||
|
html.value = instance.txt.html();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
instance.create();
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
instance.destroy();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div ref="editor"></div>
|
<div ref="editor"></div>
|
||||||
<div :innerHTML="content.html"></div>
|
<div :innerHTML="html"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import { onMounted, onBeforeUnmount, ref, reactive } from "vue";
|
|
||||||
import WangEditor from "wangeditor";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "reEditor",
|
|
||||||
setup() {
|
|
||||||
const editor = ref();
|
|
||||||
const content = reactive({
|
|
||||||
html: "",
|
|
||||||
text: ""
|
|
||||||
});
|
|
||||||
|
|
||||||
let instance;
|
|
||||||
onMounted(() => {
|
|
||||||
instance = new WangEditor(editor.value);
|
|
||||||
Object.assign(instance.config, {
|
|
||||||
onchange() {
|
|
||||||
content.html = instance.txt.html();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
instance.create();
|
|
||||||
});
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
instance.destroy();
|
|
||||||
instance = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
editor,
|
|
||||||
content
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
:deep(.w-e-text-container) {
|
:deep(.w-e-text-container) {
|
||||||
z-index: 99 !important;
|
z-index: 99 !important;
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import imgs from "/@/assets/401.gif";
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
const img = ref(`${imgs}?${new Date()}`);
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="errPage-container">
|
<div class="errPage-container">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<h1 class="text-jumbo text-ginormous">CURD Admin</h1>
|
<h1 class="text-jumbo text-ginormous">Pure Admin</h1>
|
||||||
<h2>你没有权限去该页面</h2>
|
<h2>你没有权限去该页面</h2>
|
||||||
<h6>如有不满请联系你领导</h6>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<img
|
<img
|
||||||
@ -18,20 +24,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import imgs from "/@/assets/401.gif";
|
|
||||||
import { ref } from "vue";
|
|
||||||
export default {
|
|
||||||
name: "401",
|
|
||||||
setup() {
|
|
||||||
const img = ref(`${imgs}?${new Date()}`);
|
|
||||||
return {
|
|
||||||
img
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.errPage-container {
|
.errPage-container {
|
||||||
width: 800px;
|
width: 800px;
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from "vue";
|
||||||
|
import four from "/@/assets/404.png";
|
||||||
|
import four_cloud from "/@/assets/404_cloud.png";
|
||||||
|
|
||||||
|
const message = computed(() => {
|
||||||
|
return "The webmaster said that you can not enter this page...";
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="wscn-http404-container">
|
<div class="wscn-http404-container">
|
||||||
<div class="wscn-http404">
|
<div class="wscn-http404">
|
||||||
@ -8,7 +18,7 @@
|
|||||||
<img class="pic-404__child right" :src="four_cloud" alt="404" />
|
<img class="pic-404__child right" :src="four_cloud" alt="404" />
|
||||||
</div>
|
</div>
|
||||||
<div class="bullshit">
|
<div class="bullshit">
|
||||||
<div class="bullshit__oops">CURD Admin</div>
|
<div class="bullshit__oops">Pure Admin</div>
|
||||||
<div class="bullshit__headline">{{ message }}</div>
|
<div class="bullshit__headline">{{ message }}</div>
|
||||||
<div class="bullshit__info">
|
<div class="bullshit__info">
|
||||||
Please check that the URL you entered is correct, or click the button
|
Please check that the URL you entered is correct, or click the button
|
||||||
@ -20,26 +30,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import { computed } from "vue";
|
|
||||||
import four from "/@/assets/404.png";
|
|
||||||
import four_cloud from "/@/assets/404_cloud.png";
|
|
||||||
export default {
|
|
||||||
name: "404",
|
|
||||||
setup() {
|
|
||||||
const message = computed(() => {
|
|
||||||
return "The webmaster said that you can not enter this page...";
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
message,
|
|
||||||
four,
|
|
||||||
four_cloud
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.wscn-http404-container {
|
.wscn-http404-container {
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
|
@ -1,3 +1,62 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, unref, onMounted } from "vue";
|
||||||
|
import LogicFlow from "@logicflow/core";
|
||||||
|
import { Snapshot, BpmnElement, Menu } from "@logicflow/extension";
|
||||||
|
import "@logicflow/core/dist/style/index.css";
|
||||||
|
import "@logicflow/extension/lib/style/index.css";
|
||||||
|
import { Control, NodePanel, DataDialog } from "/@/components/ReFlowChart";
|
||||||
|
import { toLogicflowData } from "/@/components/ReFlowChart/src/adpterForTurbo";
|
||||||
|
import { BpmnNode } from "/@/components/ReFlowChart/src/config";
|
||||||
|
import demoData from "./dataTurbo.json";
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
let lf = ref<ElRef>(null);
|
||||||
|
let graphData = ref(null);
|
||||||
|
let dataVisible = ref<boolean>(false);
|
||||||
|
let config = ref({
|
||||||
|
grid: true,
|
||||||
|
background: {
|
||||||
|
color: "#f7f9ff"
|
||||||
|
},
|
||||||
|
keyboard: {
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let nodeList = BpmnNode;
|
||||||
|
|
||||||
|
function initLf() {
|
||||||
|
// 画布配置
|
||||||
|
LogicFlow.use(Snapshot);
|
||||||
|
// 使用bpmn插件,引入bpmn元素,这些元素可以在turbo中转换后使用
|
||||||
|
LogicFlow.use(BpmnElement);
|
||||||
|
// 启动右键菜单
|
||||||
|
LogicFlow.use(Menu);
|
||||||
|
const domLf = new LogicFlow({
|
||||||
|
...unref(config),
|
||||||
|
container: document.querySelector("#LF-Turbo")
|
||||||
|
});
|
||||||
|
lf.value = domLf;
|
||||||
|
// 设置边类型bpmn:sequenceFlow为默认类型
|
||||||
|
unref(lf).setDefaultEdgeType("bpmn:sequenceFlow");
|
||||||
|
onRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRender() {
|
||||||
|
// Turbo数据转换为LogicFlow内部识别的数据结构
|
||||||
|
const lFData = toLogicflowData(demoData);
|
||||||
|
lf.value.render(lFData);
|
||||||
|
}
|
||||||
|
|
||||||
|
function catData() {
|
||||||
|
graphData.value = unref(lf).getGraphData();
|
||||||
|
dataVisible.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
initLf();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="logic-flow-view">
|
<div class="logic-flow-view">
|
||||||
<!-- 辅助工具栏 -->
|
<!-- 辅助工具栏 -->
|
||||||
@ -19,80 +78,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { ref, unref, onMounted } from "vue";
|
|
||||||
import LogicFlow from "@logicflow/core";
|
|
||||||
import { Snapshot, BpmnElement, Menu } from "@logicflow/extension";
|
|
||||||
import "@logicflow/core/dist/style/index.css";
|
|
||||||
import "@logicflow/extension/lib/style/index.css";
|
|
||||||
import { Control, NodePanel, DataDialog } from "/@/components/ReFlowChart";
|
|
||||||
|
|
||||||
import { toLogicflowData } from "/@/components/ReFlowChart/src/adpterForTurbo";
|
|
||||||
import { BpmnNode } from "/@/components/ReFlowChart/src/config";
|
|
||||||
import demoData from "./dataTurbo.json";
|
|
||||||
export default {
|
|
||||||
name: "reFlowChart",
|
|
||||||
components: { NodePanel, Control, DataDialog },
|
|
||||||
setup() {
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
let lf = ref<ElRef>(null);
|
|
||||||
let graphData = ref(null);
|
|
||||||
let dataVisible = ref(false);
|
|
||||||
let config = ref({
|
|
||||||
grid: true,
|
|
||||||
background: {
|
|
||||||
color: "#f7f9ff"
|
|
||||||
},
|
|
||||||
keyboard: {
|
|
||||||
enabled: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let nodeList = BpmnNode;
|
|
||||||
|
|
||||||
function initLf() {
|
|
||||||
// 画布配置
|
|
||||||
LogicFlow.use(Snapshot);
|
|
||||||
// 使用bpmn插件,引入bpmn元素,这些元素可以在turbo中转换后使用
|
|
||||||
LogicFlow.use(BpmnElement);
|
|
||||||
// 启动右键菜单
|
|
||||||
LogicFlow.use(Menu);
|
|
||||||
const domLf = new LogicFlow({
|
|
||||||
...unref(config),
|
|
||||||
container: document.querySelector("#LF-Turbo")
|
|
||||||
});
|
|
||||||
lf.value = domLf;
|
|
||||||
// 设置边类型bpmn:sequenceFlow为默认类型
|
|
||||||
unref(lf).setDefaultEdgeType("bpmn:sequenceFlow");
|
|
||||||
onRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onRender() {
|
|
||||||
// Turbo数据转换为LogicFlow内部识别的数据结构
|
|
||||||
const lFData = toLogicflowData(demoData);
|
|
||||||
lf.value.render(lFData);
|
|
||||||
}
|
|
||||||
|
|
||||||
function catData() {
|
|
||||||
graphData.value = unref(lf).getGraphData();
|
|
||||||
dataVisible.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
initLf();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
lf,
|
|
||||||
graphData,
|
|
||||||
dataVisible,
|
|
||||||
config,
|
|
||||||
nodeList,
|
|
||||||
catData
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#LF-Turbo {
|
#LF-Turbo {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
|
@ -1,3 +1,57 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, onBeforeMount } from "vue";
|
||||||
|
import info, { ContextProps } from "../components/ReInfo/index.vue";
|
||||||
|
import { getVerify, getLogin } from "/@/api/user";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { storageSession } from "/@/utils/storage";
|
||||||
|
import { warnMessage, successMessage } from "/@/utils/message";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
// 刷新验证码
|
||||||
|
const refreshGetVerify = async () => {
|
||||||
|
let { svg } = await getVerify();
|
||||||
|
contextInfo.svg = svg;
|
||||||
|
};
|
||||||
|
|
||||||
|
const contextInfo: ContextProps = reactive({
|
||||||
|
userName: "",
|
||||||
|
passWord: "",
|
||||||
|
verify: null,
|
||||||
|
svg: null
|
||||||
|
});
|
||||||
|
|
||||||
|
const toPage = (info: Object): void => {
|
||||||
|
storageSession.setItem("info", info);
|
||||||
|
router.push("/");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 登录
|
||||||
|
const onLogin = async () => {
|
||||||
|
let { userName, passWord, verify } = contextInfo;
|
||||||
|
let { code, info, accessToken } = await getLogin({
|
||||||
|
username: userName,
|
||||||
|
password: passWord,
|
||||||
|
verify: verify
|
||||||
|
});
|
||||||
|
code === 0
|
||||||
|
? successMessage(info) &&
|
||||||
|
toPage({
|
||||||
|
username: userName,
|
||||||
|
accessToken
|
||||||
|
})
|
||||||
|
: warnMessage(info);
|
||||||
|
};
|
||||||
|
|
||||||
|
const refreshVerify = (): void => {
|
||||||
|
refreshGetVerify();
|
||||||
|
};
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
// refreshGetVerify();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="login">
|
<div class="login">
|
||||||
<info
|
<info
|
||||||
@ -7,72 +61,3 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { reactive, onBeforeMount } from "vue";
|
|
||||||
import info, { ContextProps } from "../components/ReInfo/index.vue";
|
|
||||||
import { getVerify, getLogin } from "/@/api/user";
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import { storageSession } from "/@/utils/storage";
|
|
||||||
import { warnMessage, successMessage } from "/@/utils/message";
|
|
||||||
export default {
|
|
||||||
name: "login",
|
|
||||||
components: {
|
|
||||||
info
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
// 刷新验证码
|
|
||||||
const refreshGetVerify = async () => {
|
|
||||||
let { svg } = await getVerify();
|
|
||||||
contextInfo.svg = svg;
|
|
||||||
};
|
|
||||||
|
|
||||||
const contextInfo: ContextProps = reactive({
|
|
||||||
userName: "",
|
|
||||||
passWord: "",
|
|
||||||
verify: null,
|
|
||||||
svg: null
|
|
||||||
});
|
|
||||||
|
|
||||||
const toPage = (info: Object): void => {
|
|
||||||
storageSession.setItem("info", info);
|
|
||||||
router.push("/");
|
|
||||||
};
|
|
||||||
|
|
||||||
// 登录
|
|
||||||
const onLogin = async () => {
|
|
||||||
let { userName, passWord, verify } = contextInfo;
|
|
||||||
let { code, info, accessToken } = await getLogin({
|
|
||||||
username: userName,
|
|
||||||
password: passWord,
|
|
||||||
verify: verify
|
|
||||||
});
|
|
||||||
code === 0
|
|
||||||
? successMessage(info) &&
|
|
||||||
toPage({
|
|
||||||
username: userName,
|
|
||||||
accessToken
|
|
||||||
})
|
|
||||||
: warnMessage(info);
|
|
||||||
};
|
|
||||||
|
|
||||||
const refreshVerify = (): void => {
|
|
||||||
refreshGetVerify();
|
|
||||||
};
|
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
// refreshGetVerify();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
contextInfo,
|
|
||||||
onLogin,
|
|
||||||
router,
|
|
||||||
toPage,
|
|
||||||
refreshVerify
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
@ -1,3 +1,18 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { storageSession } from "/@/utils/storage";
|
||||||
|
|
||||||
|
const auth = ref(storageSession.getItem("info").username || "admin");
|
||||||
|
|
||||||
|
function changRole(value) {
|
||||||
|
storageSession.setItem("info", {
|
||||||
|
username: value,
|
||||||
|
accessToken: `eyJhbGciOiJIUzUxMiJ9.${value}`
|
||||||
|
});
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-radio-group v-model="auth" @change="changRole">
|
<el-radio-group v-model="auth" @change="changRole">
|
||||||
@ -8,30 +23,3 @@
|
|||||||
<p v-auth="'v-test'">只有test可看</p>
|
<p v-auth="'v-test'">只有test可看</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { ref } from "vue";
|
|
||||||
import { storageSession } from "/@/utils/storage";
|
|
||||||
export default {
|
|
||||||
name: "permissionButton",
|
|
||||||
setup() {
|
|
||||||
const auth = ref(storageSession.getItem("info").username || "admin");
|
|
||||||
|
|
||||||
function changRole(value) {
|
|
||||||
storageSession.setItem("info", {
|
|
||||||
username: value,
|
|
||||||
accessToken: `eyJhbGciOiJIUzUxMiJ9.${value}`
|
|
||||||
});
|
|
||||||
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
auth,
|
|
||||||
changRole
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
|
@ -1,3 +1,26 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, unref } from "vue";
|
||||||
|
import { storageSession } from "/@/utils/storage";
|
||||||
|
|
||||||
|
let purview: string = ref(storageSession.getItem("info").username);
|
||||||
|
|
||||||
|
function changRole() {
|
||||||
|
if (unref(purview) === "admin") {
|
||||||
|
storageSession.setItem("info", {
|
||||||
|
username: "test",
|
||||||
|
accessToken: "eyJhbGciOiJIUzUxMiJ9.test"
|
||||||
|
});
|
||||||
|
window.location.reload();
|
||||||
|
} else {
|
||||||
|
storageSession.setItem("info", {
|
||||||
|
username: "admin",
|
||||||
|
accessToken: "eyJhbGciOiJIUzUxMiJ9.admin"
|
||||||
|
});
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<h4>
|
<h4>
|
||||||
@ -10,35 +33,3 @@
|
|||||||
<el-button type="primary" @click="changRole">切换角色</el-button>
|
<el-button type="primary" @click="changRole">切换角色</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { ref, unref } from "vue";
|
|
||||||
import { storageSession } from "/@/utils/storage";
|
|
||||||
export default {
|
|
||||||
name: "permissionPage",
|
|
||||||
setup() {
|
|
||||||
let purview: string = ref(storageSession.getItem("info").username);
|
|
||||||
|
|
||||||
function changRole() {
|
|
||||||
if (unref(purview) === "admin") {
|
|
||||||
storageSession.setItem("info", {
|
|
||||||
username: "test",
|
|
||||||
accessToken: "eyJhbGciOiJIUzUxMiJ9.test"
|
|
||||||
});
|
|
||||||
window.location.reload();
|
|
||||||
} else {
|
|
||||||
storageSession.setItem("info", {
|
|
||||||
username: "admin",
|
|
||||||
accessToken: "eyJhbGciOiJIUzUxMiJ9.admin"
|
|
||||||
});
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
purview,
|
|
||||||
changRole
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
@ -1,26 +1,20 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { unref } from "vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
|
const { currentRoute, replace } = useRouter();
|
||||||
|
|
||||||
|
const { params, query } = unref(currentRoute);
|
||||||
|
const { path } = params;
|
||||||
|
|
||||||
|
const _path = Array.isArray(path) ? path.join("/") : path;
|
||||||
|
|
||||||
|
replace({
|
||||||
|
path: "/" + _path,
|
||||||
|
query
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div></div>
|
<div></div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent, unref } from "vue";
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "redirect",
|
|
||||||
setup() {
|
|
||||||
const { currentRoute, replace } = useRouter();
|
|
||||||
|
|
||||||
const { params, query } = unref(currentRoute);
|
|
||||||
const { path } = params;
|
|
||||||
|
|
||||||
const _path = Array.isArray(path) ? path.join("/") : path;
|
|
||||||
|
|
||||||
replace({
|
|
||||||
path: "/" + _path,
|
|
||||||
query
|
|
||||||
});
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
@ -1,3 +1,47 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, onBeforeMount } from "vue";
|
||||||
|
import info, { ContextProps } from "../components/ReInfo/index.vue";
|
||||||
|
import { getRegist, getVerify } from "/@/api/user";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { warnMessage, successMessage } from "/@/utils/message";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
// 刷新验证码
|
||||||
|
const refreshGetVerify = async () => {
|
||||||
|
let { svg } = await getVerify();
|
||||||
|
contextInfo.svg = svg;
|
||||||
|
};
|
||||||
|
|
||||||
|
const contextInfo: ContextProps = reactive({
|
||||||
|
userName: "",
|
||||||
|
passWord: "",
|
||||||
|
verify: null,
|
||||||
|
svg: null
|
||||||
|
});
|
||||||
|
|
||||||
|
// 注册
|
||||||
|
const onRegist = async () => {
|
||||||
|
let { userName, passWord, verify } = contextInfo;
|
||||||
|
let { code, info } = await getRegist({
|
||||||
|
username: userName,
|
||||||
|
password: passWord,
|
||||||
|
verify: verify
|
||||||
|
});
|
||||||
|
code === 0
|
||||||
|
? successMessage(info) && router.push("/login")
|
||||||
|
: warnMessage(info);
|
||||||
|
};
|
||||||
|
|
||||||
|
const refreshVerify = (): void => {
|
||||||
|
refreshGetVerify();
|
||||||
|
};
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
// refreshGetVerify();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="register">
|
<div class="register">
|
||||||
<info
|
<info
|
||||||
@ -7,61 +51,3 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { reactive, onBeforeMount } from "vue";
|
|
||||||
import info, { ContextProps } from "../components/ReInfo/index.vue";
|
|
||||||
import { getRegist, getVerify } from "/@/api/user";
|
|
||||||
import { useRouter } from "vue-router";
|
|
||||||
import { warnMessage, successMessage } from "/@/utils/message";
|
|
||||||
export default {
|
|
||||||
name: "register",
|
|
||||||
components: {
|
|
||||||
info
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
// 刷新验证码
|
|
||||||
const refreshGetVerify = async () => {
|
|
||||||
let { svg } = await getVerify();
|
|
||||||
contextInfo.svg = svg;
|
|
||||||
};
|
|
||||||
|
|
||||||
const contextInfo: ContextProps = reactive({
|
|
||||||
userName: "",
|
|
||||||
passWord: "",
|
|
||||||
verify: null,
|
|
||||||
svg: null
|
|
||||||
});
|
|
||||||
|
|
||||||
// 注册
|
|
||||||
const onRegist = async () => {
|
|
||||||
let { userName, passWord, verify } = contextInfo;
|
|
||||||
let { code, info } = await getRegist({
|
|
||||||
username: userName,
|
|
||||||
password: passWord,
|
|
||||||
verify: verify
|
|
||||||
});
|
|
||||||
code === 0
|
|
||||||
? successMessage(info) && router.push("/login")
|
|
||||||
: warnMessage(info);
|
|
||||||
};
|
|
||||||
|
|
||||||
const refreshVerify = (): void => {
|
|
||||||
refreshGetVerify();
|
|
||||||
};
|
|
||||||
|
|
||||||
onBeforeMount(() => {
|
|
||||||
// refreshGetVerify();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
contextInfo,
|
|
||||||
onRegist,
|
|
||||||
router,
|
|
||||||
refreshVerify
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
@ -1,3 +1,170 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import Flop from "/@/components/ReFlop";
|
||||||
|
import { ref, computed, onMounted, nextTick } from "vue";
|
||||||
|
import { deviceDetection } from "/@/utils/deviceDetection";
|
||||||
|
import { useEventListener, tryOnUnmounted, useTimeoutFn } from "@vueuse/core";
|
||||||
|
import { echartsJson } from "/@/api/mock";
|
||||||
|
import echarts from "/@/plugins/echarts";
|
||||||
|
import { ECharts } from "echarts";
|
||||||
|
|
||||||
|
//折线图实例
|
||||||
|
let brokenLine: ECharts;
|
||||||
|
let mobile = ref<boolean>(deviceDetection());
|
||||||
|
let date: Date = new Date();
|
||||||
|
let loading = ref<boolean>(true);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = !loading.value;
|
||||||
|
nextTick(() => {
|
||||||
|
initbrokenLine();
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
let greetings = computed(() => {
|
||||||
|
if (date.getHours() >= 0 && date.getHours() < 12) {
|
||||||
|
return "上午阳光明媚,祝你薪水翻倍🌞!";
|
||||||
|
} else if (date.getHours() >= 12 && date.getHours() < 18) {
|
||||||
|
return "下午小风娇好,愿你青春不老😃!";
|
||||||
|
} else {
|
||||||
|
return "折一根天使羽毛,愿拂去您的疲惫烦恼忧伤🌛!";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function initbrokenLine() {
|
||||||
|
const lineRefDom = document.getElementById("brokenLine");
|
||||||
|
if (!lineRefDom) return;
|
||||||
|
// @ts-ignore
|
||||||
|
brokenLine = echarts.init(lineRefDom);
|
||||||
|
brokenLine.clear(); //清除旧画布 重新渲染
|
||||||
|
|
||||||
|
echartsJson().then(({ info }) => {
|
||||||
|
brokenLine.setOption({
|
||||||
|
title: {
|
||||||
|
text: "上海 空气质量指数",
|
||||||
|
left: "1%"
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: "axis"
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: "5%",
|
||||||
|
right: "15%",
|
||||||
|
bottom: "10%"
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
data: info.map(function (item) {
|
||||||
|
return item[0];
|
||||||
|
})
|
||||||
|
},
|
||||||
|
yAxis: {},
|
||||||
|
toolbox: {
|
||||||
|
right: 10,
|
||||||
|
feature: {
|
||||||
|
saveAsImage: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dataZoom: [
|
||||||
|
{
|
||||||
|
startValue: "2014-06-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "inside"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
visualMap: {
|
||||||
|
top: 50,
|
||||||
|
right: 10,
|
||||||
|
pieces: [
|
||||||
|
{
|
||||||
|
gt: 0,
|
||||||
|
lte: 50,
|
||||||
|
color: "#93CE07"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gt: 50,
|
||||||
|
lte: 100,
|
||||||
|
color: "#FBDB0F"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gt: 100,
|
||||||
|
lte: 150,
|
||||||
|
color: "#FC7D02"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gt: 150,
|
||||||
|
lte: 200,
|
||||||
|
color: "#FD0100"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gt: 200,
|
||||||
|
lte: 300,
|
||||||
|
color: "#AA069F"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gt: 300,
|
||||||
|
color: "#AC3B2A"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
outOfRange: {
|
||||||
|
color: "#999"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: {
|
||||||
|
name: "上海 空气质量指数",
|
||||||
|
type: "line",
|
||||||
|
data: info.map(function (item) {
|
||||||
|
return item[1];
|
||||||
|
}),
|
||||||
|
markLine: {
|
||||||
|
silent: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: "#333"
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
yAxis: 50
|
||||||
|
},
|
||||||
|
{
|
||||||
|
yAxis: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
yAxis: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
yAxis: 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
yAxis: 300
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const openDepot = (): void => {
|
||||||
|
window.open("https://github.com/xiaoxian521/vue-pure-admin");
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
useEventListener("resize", () => {
|
||||||
|
if (!brokenLine) return;
|
||||||
|
useTimeoutFn(() => {
|
||||||
|
brokenLine.resize();
|
||||||
|
}, 180);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
tryOnUnmounted(() => {
|
||||||
|
if (!brokenLine) return;
|
||||||
|
brokenLine.dispose();
|
||||||
|
brokenLine = null;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="welcome">
|
<div class="welcome">
|
||||||
<el-affix>
|
<el-affix>
|
||||||
@ -26,185 +193,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import Flop from "/@/components/ReFlop";
|
|
||||||
import { ref, computed, onMounted, nextTick } from "vue";
|
|
||||||
import { deviceDetection } from "/@/utils/deviceDetection";
|
|
||||||
import { useEventListener, tryOnUnmounted, useTimeoutFn } from "@vueuse/core";
|
|
||||||
import { echartsJson } from "/@/api/mock";
|
|
||||||
import echarts from "/@/plugins/echarts";
|
|
||||||
|
|
||||||
let brokenLine: any = null; //折线图实例
|
|
||||||
export default {
|
|
||||||
name: "welcome",
|
|
||||||
components: {
|
|
||||||
Flop
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
let mobile = ref(deviceDetection());
|
|
||||||
let date: Date = new Date();
|
|
||||||
let loading = ref(true);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
loading.value = !loading.value;
|
|
||||||
nextTick(() => {
|
|
||||||
initbrokenLine();
|
|
||||||
});
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
let greetings = computed(() => {
|
|
||||||
if (date.getHours() >= 0 && date.getHours() < 12) {
|
|
||||||
return "上午阳光明媚,祝你薪水翻倍🌞!";
|
|
||||||
} else if (date.getHours() >= 12 && date.getHours() < 18) {
|
|
||||||
return "下午小风娇好,愿你青春不老😃!";
|
|
||||||
} else {
|
|
||||||
return "折一根天使羽毛,愿拂去您的疲惫烦恼忧伤🌛!";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function initbrokenLine() {
|
|
||||||
const lineRefDom = document.getElementById("brokenLine");
|
|
||||||
if (!lineRefDom) return;
|
|
||||||
brokenLine = echarts.init(lineRefDom);
|
|
||||||
brokenLine.clear(); //清除旧画布 重新渲染
|
|
||||||
|
|
||||||
echartsJson().then(({ info }) => {
|
|
||||||
brokenLine.setOption({
|
|
||||||
title: {
|
|
||||||
text: "上海 空气质量指数",
|
|
||||||
left: "1%"
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: "axis"
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
left: "5%",
|
|
||||||
right: "15%",
|
|
||||||
bottom: "10%"
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
data: info.map(function (item) {
|
|
||||||
return item[0];
|
|
||||||
})
|
|
||||||
},
|
|
||||||
yAxis: {},
|
|
||||||
toolbox: {
|
|
||||||
right: 10,
|
|
||||||
feature: {
|
|
||||||
saveAsImage: {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dataZoom: [
|
|
||||||
{
|
|
||||||
startValue: "2014-06-01"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "inside"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
visualMap: {
|
|
||||||
top: 50,
|
|
||||||
right: 10,
|
|
||||||
pieces: [
|
|
||||||
{
|
|
||||||
gt: 0,
|
|
||||||
lte: 50,
|
|
||||||
color: "#93CE07"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gt: 50,
|
|
||||||
lte: 100,
|
|
||||||
color: "#FBDB0F"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gt: 100,
|
|
||||||
lte: 150,
|
|
||||||
color: "#FC7D02"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gt: 150,
|
|
||||||
lte: 200,
|
|
||||||
color: "#FD0100"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gt: 200,
|
|
||||||
lte: 300,
|
|
||||||
color: "#AA069F"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gt: 300,
|
|
||||||
color: "#AC3B2A"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
outOfRange: {
|
|
||||||
color: "#999"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: {
|
|
||||||
name: "上海 空气质量指数",
|
|
||||||
type: "line",
|
|
||||||
data: info.map(function (item) {
|
|
||||||
return item[1];
|
|
||||||
}),
|
|
||||||
markLine: {
|
|
||||||
silent: true,
|
|
||||||
lineStyle: {
|
|
||||||
color: "#333"
|
|
||||||
},
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
yAxis: 50
|
|
||||||
},
|
|
||||||
{
|
|
||||||
yAxis: 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
yAxis: 150
|
|
||||||
},
|
|
||||||
{
|
|
||||||
yAxis: 200
|
|
||||||
},
|
|
||||||
{
|
|
||||||
yAxis: 300
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const openDepot = (): void => {
|
|
||||||
window.open("https://github.com/xiaoxian521/vue-pure-admin");
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
nextTick(() => {
|
|
||||||
useEventListener("resize", () => {
|
|
||||||
if (!brokenLine) return;
|
|
||||||
useTimeoutFn(() => {
|
|
||||||
brokenLine.resize();
|
|
||||||
}, 180);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
tryOnUnmounted(() => {
|
|
||||||
if (!brokenLine) return;
|
|
||||||
brokenLine.dispose();
|
|
||||||
brokenLine = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
greetings,
|
|
||||||
mobile,
|
|
||||||
loading,
|
|
||||||
openDepot
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.welcome {
|
.welcome {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
"importHelpers": true,
|
"importHelpers": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
|
"strictFunctionTypes": false,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
@ -16,27 +17,14 @@
|
|||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"allowJs": false,
|
"allowJs": false,
|
||||||
"resolveJsonModule": true, // 包含导入的模块。json的扩展
|
"resolveJsonModule": true, // 包含导入的模块。json的扩展
|
||||||
"lib": [
|
"lib": ["dom", "esnext"],
|
||||||
"dom",
|
|
||||||
"esnext"
|
|
||||||
],
|
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"/@/*": [
|
"/@/*": ["src/*"],
|
||||||
"src/*"
|
"/#/*": ["types/*"]
|
||||||
],
|
|
||||||
"/#/*": [
|
|
||||||
"types/*"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"types": [
|
"types": ["node", "vite/client"],
|
||||||
"node",
|
"typeRoots": ["./node_modules/@types/", "./types"]
|
||||||
"vite/client"
|
|
||||||
],
|
|
||||||
"typeRoots": [
|
|
||||||
"./node_modules/@types/",
|
|
||||||
"./types"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*.ts",
|
"src/**/*.ts",
|
||||||
@ -46,9 +34,5 @@
|
|||||||
"mock/*.ts",
|
"mock/*.ts",
|
||||||
"vite.config.ts"
|
"vite.config.ts"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": ["node_modules", "dist", "**/*.js"]
|
||||||
"node_modules",
|
}
|
||||||
"dist",
|
|
||||||
"**/*.js"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user