mirror of
https://github.com/cool-team-official/cool-admin-vue.git
synced 2024-11-01 06:02:38 +08:00
优化代码
This commit is contained in:
parent
39b2afd17c
commit
6b4a9c3459
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "front-next",
|
"name": "front-next",
|
||||||
"version": "5.10.0",
|
"version": "5.11.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --host",
|
"dev": "vite --host",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
@ -11,7 +11,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/lang-javascript": "^6.0.1",
|
"@codemirror/lang-javascript": "^6.0.1",
|
||||||
"@codemirror/theme-one-dark": "^6.0.0",
|
"@codemirror/theme-one-dark": "^6.0.0",
|
||||||
"@cool-vue/crud": "^5.6.1",
|
"@cool-vue/admin": "^5.0.1",
|
||||||
|
"@cool-vue/crud": "^5.6.4",
|
||||||
"@element-plus/icons-vue": "^2.0.6",
|
"@element-plus/icons-vue": "^2.0.6",
|
||||||
"@vueuse/core": "^9.1.0",
|
"@vueuse/core": "^9.1.0",
|
||||||
"@wangeditor/editor": "^5.1.14",
|
"@wangeditor/editor": "^5.1.14",
|
||||||
|
@ -183,27 +183,28 @@ export async function createEps() {
|
|||||||
createDts(list);
|
createDts(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 开发环境下使用接口 /eps 的数据,生产环境使用 eps.json
|
// 使用 eps.json
|
||||||
|
try {
|
||||||
|
const eps = JSON.parse(__EPS__ || "[]").map(([prefix, api]: any[]) => {
|
||||||
|
return {
|
||||||
|
prefix,
|
||||||
|
api: api.map(([method, path, name]: string[]) => {
|
||||||
|
return {
|
||||||
|
method,
|
||||||
|
path,
|
||||||
|
name
|
||||||
|
};
|
||||||
|
})
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
set(eps);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("[Eps] 解析失败!", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开发环境下使用接口 /eps 刷新数据
|
||||||
if (isDev) {
|
if (isDev) {
|
||||||
await getEps();
|
await getEps();
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
const eps = JSON.parse(__EPS__ || "[]").map(([prefix, api]: any[]) => {
|
|
||||||
return {
|
|
||||||
prefix,
|
|
||||||
api: api.map(([method, path, name]: string[]) => {
|
|
||||||
return {
|
|
||||||
method,
|
|
||||||
path,
|
|
||||||
name
|
|
||||||
};
|
|
||||||
})
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
set(eps);
|
|
||||||
} catch (err) {
|
|
||||||
console.error("[Eps] 解析失败!", err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,110 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="cl-avatar" :class="[size, shape]" :style="[style]">
|
|
||||||
<el-image :src="src || modelValue" alt="头像">
|
|
||||||
<template #error>
|
|
||||||
<div class="image-slot">
|
|
||||||
<el-icon :size="20" :color="color"><user /></el-icon>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-image>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { computed, defineComponent, PropType } from "vue";
|
|
||||||
import { isNumber } from "lodash-es";
|
|
||||||
import { User } from "@element-plus/icons-vue";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "cl-avatar",
|
|
||||||
|
|
||||||
components: {
|
|
||||||
User
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
modelValue: String,
|
|
||||||
src: String,
|
|
||||||
size: {
|
|
||||||
type: [String, Number],
|
|
||||||
default: 36
|
|
||||||
},
|
|
||||||
shape: {
|
|
||||||
type: String as PropType<"square" | "circle">,
|
|
||||||
default: "square"
|
|
||||||
},
|
|
||||||
backgroundColor: {
|
|
||||||
type: String,
|
|
||||||
default: "#f7f7f7"
|
|
||||||
},
|
|
||||||
color: {
|
|
||||||
type: String,
|
|
||||||
default: "#ccc"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setup(props) {
|
|
||||||
const size = isNumber(props.size) ? props.size + "px" : props.size;
|
|
||||||
|
|
||||||
const style = computed(() => {
|
|
||||||
return {
|
|
||||||
height: size,
|
|
||||||
width: size,
|
|
||||||
backgroundColor: props.backgroundColor
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
style
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.cl-avatar {
|
|
||||||
overflow: hidden;
|
|
||||||
margin: 0 auto;
|
|
||||||
|
|
||||||
&.large {
|
|
||||||
height: 50px;
|
|
||||||
width: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.medium {
|
|
||||||
height: 40px;
|
|
||||||
width: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.small {
|
|
||||||
height: 30px;
|
|
||||||
width: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.circle {
|
|
||||||
border-radius: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.square {
|
|
||||||
border-radius: 10%;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-image {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.image-slot {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,95 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="cl-codemirror">
|
|
||||||
<codemirror
|
|
||||||
v-model="content"
|
|
||||||
:placeholder="placeholder"
|
|
||||||
:style="{ height, fontSize }"
|
|
||||||
autofocus
|
|
||||||
indent-with-tab
|
|
||||||
:tab-size="4"
|
|
||||||
:extensions="extensions"
|
|
||||||
@change="onChange"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" name="cl-codemirror" setup>
|
|
||||||
import { Codemirror } from "vue-codemirror";
|
|
||||||
import { javascript } from "@codemirror/lang-javascript";
|
|
||||||
import { oneDark } from "@codemirror/theme-one-dark";
|
|
||||||
import { ref, watch, computed } from "vue";
|
|
||||||
import { useDark } from "@vueuse/core";
|
|
||||||
import { isNumber } from "lodash-es";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
modelValue: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
placeholder: {
|
|
||||||
type: String,
|
|
||||||
default: "请输入"
|
|
||||||
},
|
|
||||||
height: {
|
|
||||||
type: [String, Number],
|
|
||||||
default: 400
|
|
||||||
},
|
|
||||||
fontSize: {
|
|
||||||
type: String,
|
|
||||||
default: "14px"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits(["update:modelValue", "change"]);
|
|
||||||
|
|
||||||
// 是否暗黑模式
|
|
||||||
const isDark = ref(useDark());
|
|
||||||
|
|
||||||
// 高度
|
|
||||||
const height = computed(() => (isNumber(props.height) ? `${props.height}px` : props.height));
|
|
||||||
|
|
||||||
// 插件
|
|
||||||
const extensions: any[] = [javascript()];
|
|
||||||
|
|
||||||
if (isDark.value) {
|
|
||||||
extensions.push(oneDark);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 内容
|
|
||||||
const content = ref("");
|
|
||||||
|
|
||||||
// 值改变
|
|
||||||
function onChange(value: string) {
|
|
||||||
emit("update:modelValue", value);
|
|
||||||
emit("change", value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听值
|
|
||||||
watch(
|
|
||||||
() => props.modelValue,
|
|
||||||
(val) => {
|
|
||||||
content.value = val;
|
|
||||||
},
|
|
||||||
{
|
|
||||||
immediate: true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.cl-codemirror {
|
|
||||||
border: 1px solid var(--el-border-color);
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
:deep(.cm-editor) {
|
|
||||||
.cm-foldGutter {
|
|
||||||
width: 12px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.cm-focused {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,136 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="cl-column-custom__wrap">
|
|
||||||
<el-button @click="open">自定义列</el-button>
|
|
||||||
|
|
||||||
<cl-dialog v-model="visible" title="自定义列">
|
|
||||||
<div class="cl-column-custom__dialog">
|
|
||||||
<div class="left">
|
|
||||||
<el-checkbox-group v-model="selection">
|
|
||||||
<el-checkbox
|
|
||||||
v-for="(item, index) in list"
|
|
||||||
:key="index"
|
|
||||||
:label="item.value"
|
|
||||||
>{{ item.label }}</el-checkbox
|
|
||||||
>
|
|
||||||
</el-checkbox-group>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="right"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<template #footer>
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
<el-button type="success" @click="save">保存</el-button>
|
|
||||||
</template>
|
|
||||||
</cl-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { computed, defineComponent, onMounted, ref } from "vue";
|
|
||||||
import { useCrud } from "@cool-vue/crud";
|
|
||||||
import store from "store";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "cl-column-custom",
|
|
||||||
|
|
||||||
props: {
|
|
||||||
name: String,
|
|
||||||
columns: {
|
|
||||||
type: Array,
|
|
||||||
default: () => []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setup(props) {
|
|
||||||
// cl-crud
|
|
||||||
const Crud = useCrud();
|
|
||||||
|
|
||||||
// 是否可见
|
|
||||||
const visible = ref(false);
|
|
||||||
|
|
||||||
// 选中
|
|
||||||
const selection = ref([]);
|
|
||||||
|
|
||||||
// 名称
|
|
||||||
const name = `column-custom__${props.name || location.pathname}`;
|
|
||||||
|
|
||||||
// 列数据
|
|
||||||
const list = computed(() => {
|
|
||||||
return props.columns
|
|
||||||
.filter((e: any) => !e.type)
|
|
||||||
.map((e: any) => {
|
|
||||||
return {
|
|
||||||
label: e.label,
|
|
||||||
value: e.prop
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 获取 prop
|
|
||||||
function getNames() {
|
|
||||||
const arr = store.get(name);
|
|
||||||
return arr ? arr : list.value.map((e) => e.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 改变列
|
|
||||||
function change() {
|
|
||||||
const names = getNames();
|
|
||||||
|
|
||||||
if (store.get(name)) {
|
|
||||||
Crud.value?.Table.reBuild(() => {
|
|
||||||
props.columns.map((e: any) => {
|
|
||||||
if (!e.type) {
|
|
||||||
e.hidden = !names.includes(e.prop);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存
|
|
||||||
function save() {
|
|
||||||
store.set(name, selection.value);
|
|
||||||
change();
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 打开
|
|
||||||
function open() {
|
|
||||||
selection.value = getNames();
|
|
||||||
visible.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关闭
|
|
||||||
function close() {
|
|
||||||
visible.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
change();
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
visible,
|
|
||||||
list,
|
|
||||||
selection,
|
|
||||||
open,
|
|
||||||
close,
|
|
||||||
save
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.cl-column-custom {
|
|
||||||
&__dialog {
|
|
||||||
.left {
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
border-left: 1px solid #eee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,30 +0,0 @@
|
|||||||
<template>
|
|
||||||
<span class="cl-date-text">{{ value }}</span>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent, computed } from "vue";
|
|
||||||
import dayjs from "dayjs";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "cl-date-text",
|
|
||||||
|
|
||||||
props: {
|
|
||||||
modelValue: [String, Number],
|
|
||||||
format: {
|
|
||||||
type: String,
|
|
||||||
default: "YYYY-MM-DD HH:mm:ss"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setup(props) {
|
|
||||||
const value = computed(() => {
|
|
||||||
return props.modelValue ? dayjs(props.modelValue).format(props.format) : "";
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
value
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
@ -1,256 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="cl-editor-quill">
|
|
||||||
<div ref="Editor" class="editor" :style="style"></div>
|
|
||||||
<cl-upload-space ref="Upload" :show-btn="false" @confirm="onSpaceConfirm" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { computed, defineComponent, onMounted, ref, watch } from "vue";
|
|
||||||
import Quill from "quill";
|
|
||||||
import "quill/dist/quill.snow.css";
|
|
||||||
import { isNumber } from "lodash-es";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "cl-editor-quill",
|
|
||||||
|
|
||||||
props: {
|
|
||||||
modelValue: null,
|
|
||||||
options: Object,
|
|
||||||
height: [String, Number],
|
|
||||||
width: [String, Number]
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ["update:modelValue", "load"],
|
|
||||||
|
|
||||||
setup(props, { emit }) {
|
|
||||||
let quill: any = null;
|
|
||||||
|
|
||||||
const Editor = ref();
|
|
||||||
const Upload = ref();
|
|
||||||
|
|
||||||
// 文本内容
|
|
||||||
const content = ref("");
|
|
||||||
|
|
||||||
// 光标位置
|
|
||||||
const cursorIndex = ref(0);
|
|
||||||
|
|
||||||
// 上传处理
|
|
||||||
function uploadFileHandler() {
|
|
||||||
const selection = quill.getSelection();
|
|
||||||
|
|
||||||
if (selection) {
|
|
||||||
cursorIndex.value = selection.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
Upload.value.open();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 文件确认
|
|
||||||
function onSpaceConfirm(files: any[]) {
|
|
||||||
if (files.length > 0) {
|
|
||||||
// 批量插入图片
|
|
||||||
files.forEach((file, i) => {
|
|
||||||
if (file.type == "image") {
|
|
||||||
quill.insertEmbed(
|
|
||||||
cursorIndex.value + i,
|
|
||||||
file.type,
|
|
||||||
file.url,
|
|
||||||
Quill.sources.USER
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 移动光标到图片后一位
|
|
||||||
quill.setSelection(cursorIndex.value + files.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置内容
|
|
||||||
function setContent(val: string) {
|
|
||||||
quill.root.innerHTML = val || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// 编辑框样式
|
|
||||||
const style = computed<any>(() => {
|
|
||||||
const height = isNumber(props.height) ? props.height + "px" : props.height;
|
|
||||||
const width = isNumber(props.width) ? props.width + "px" : props.width;
|
|
||||||
|
|
||||||
return {
|
|
||||||
height,
|
|
||||||
width
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// 监听绑定值
|
|
||||||
watch(
|
|
||||||
() => props.modelValue,
|
|
||||||
(val: string) => {
|
|
||||||
if (val) {
|
|
||||||
if (val !== content.value) {
|
|
||||||
setContent(val);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setContent("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
onMounted(function () {
|
|
||||||
// 实例化
|
|
||||||
quill = new Quill(Editor.value, {
|
|
||||||
theme: "snow",
|
|
||||||
placeholder: "输入内容",
|
|
||||||
modules: {
|
|
||||||
toolbar: [
|
|
||||||
["bold", "italic", "underline", "strike"],
|
|
||||||
["blockquote", "code-block"],
|
|
||||||
[{ header: 1 }, { header: 2 }],
|
|
||||||
[{ list: "ordered" }, { list: "bullet" }],
|
|
||||||
[{ script: "sub" }, { script: "super" }],
|
|
||||||
[{ indent: "-1" }, { indent: "+1" }],
|
|
||||||
[{ direction: "rtl" }],
|
|
||||||
[{ size: ["small", false, "large", "huge"] }],
|
|
||||||
[{ header: [1, 2, 3, 4, 5, 6, false] }],
|
|
||||||
[{ color: [] }, { background: [] }],
|
|
||||||
[{ font: [] }],
|
|
||||||
[{ align: [] }],
|
|
||||||
["clean"],
|
|
||||||
["link", "image"]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
...props.options
|
|
||||||
});
|
|
||||||
|
|
||||||
// 添加图片工具
|
|
||||||
quill.getModule("toolbar").addHandler("image", uploadFileHandler);
|
|
||||||
|
|
||||||
// 监听输入
|
|
||||||
quill.on("text-change", () => {
|
|
||||||
content.value = quill.root.innerHTML;
|
|
||||||
emit("update:modelValue", content.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 设置内容
|
|
||||||
setContent(props.modelValue);
|
|
||||||
|
|
||||||
// 加载回调
|
|
||||||
emit("load", quill);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
Editor,
|
|
||||||
Upload,
|
|
||||||
content,
|
|
||||||
quill,
|
|
||||||
cursorIndex,
|
|
||||||
style,
|
|
||||||
setContent,
|
|
||||||
onSpaceConfirm
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.cl-editor-quill {
|
|
||||||
background-color: #fff;
|
|
||||||
|
|
||||||
.ql-snow {
|
|
||||||
line-height: 22px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-upload,
|
|
||||||
#quill-upload-btn {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow {
|
|
||||||
border: 1px solid #dcdfe6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-tooltip[data-mode="link"]::before {
|
|
||||||
content: "请输入链接地址:";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
|
|
||||||
border-right: 0px;
|
|
||||||
content: "保存";
|
|
||||||
padding-right: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-tooltip[data-mode="video"]::before {
|
|
||||||
content: "请输入视频地址:";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
|
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
|
|
||||||
content: "14px";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
|
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
|
|
||||||
content: "10px";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
|
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
|
|
||||||
content: "18px";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
|
|
||||||
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
|
|
||||||
content: "32px";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
|
|
||||||
content: "文本";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
|
|
||||||
content: "标题1";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
|
|
||||||
content: "标题2";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
|
|
||||||
content: "标题3";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
|
|
||||||
content: "标题4";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
|
|
||||||
content: "标题5";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
|
|
||||||
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
|
|
||||||
content: "标题6";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
|
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
|
|
||||||
content: "标准字体";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
|
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
|
|
||||||
content: "衬线字体";
|
|
||||||
}
|
|
||||||
|
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
|
|
||||||
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
|
|
||||||
content: "等宽字体";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,146 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="cl-editor-wang">
|
|
||||||
<!-- 工具栏 -->
|
|
||||||
<toolbar :editor="editorRef" :mode="mode" />
|
|
||||||
|
|
||||||
<!-- 编辑框 -->
|
|
||||||
<editor
|
|
||||||
v-model="value"
|
|
||||||
:defaultConfig="editorConfig"
|
|
||||||
:mode="mode"
|
|
||||||
:style="{
|
|
||||||
height
|
|
||||||
}"
|
|
||||||
@onCreated="onCreated"
|
|
||||||
@onFocus="onFocus"
|
|
||||||
@onBlur="onBlur"
|
|
||||||
@onChange="onChange"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 图片 -->
|
|
||||||
<cl-upload-space
|
|
||||||
ref="ImageSpace"
|
|
||||||
accept="image/*"
|
|
||||||
:show-btn="false"
|
|
||||||
@confirm="onSpaceConfirm"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 视频 -->
|
|
||||||
<cl-upload-space
|
|
||||||
ref="VideoSpace"
|
|
||||||
accept="video/*"
|
|
||||||
:show-btn="false"
|
|
||||||
@confirm="onSpaceConfirm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" name="cl-editor-wang" setup>
|
|
||||||
import "@wangeditor/editor/dist/css/style.css";
|
|
||||||
import { onBeforeUnmount, ref, shallowRef, watch, PropType, reactive, computed } from "vue";
|
|
||||||
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
|
|
||||||
import { IEditorConfig } from "@wangeditor/editor";
|
|
||||||
import { isNumber } from "lodash-es";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
modelValue: String,
|
|
||||||
mode: {
|
|
||||||
type: String as PropType<"default" | "simple">,
|
|
||||||
default: "default"
|
|
||||||
},
|
|
||||||
height: {
|
|
||||||
type: [String, Number],
|
|
||||||
default: 400
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const emit = defineEmits(["update:modelValue", "change", "focus", "blur"]);
|
|
||||||
|
|
||||||
const ImageSpace = ref();
|
|
||||||
const VideoSpace = ref();
|
|
||||||
const editorRef = shallowRef();
|
|
||||||
|
|
||||||
// 内容
|
|
||||||
const value = ref();
|
|
||||||
|
|
||||||
// 编辑器高度
|
|
||||||
const height = computed(() => (isNumber(props.height) ? `${props.height}px` : props.height));
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.modelValue,
|
|
||||||
(val) => {
|
|
||||||
value.value = val;
|
|
||||||
},
|
|
||||||
{
|
|
||||||
immediate: true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
function onCreated(editor: any) {
|
|
||||||
editorRef.value = editor;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onFocus(editor: any) {
|
|
||||||
emit("focus", editor);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onBlur(editor: any) {
|
|
||||||
emit("blur", editor);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onChange() {
|
|
||||||
emit("update:modelValue", value.value);
|
|
||||||
emit("change", value.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
const temp = reactive<any>({
|
|
||||||
insertFn: null
|
|
||||||
});
|
|
||||||
|
|
||||||
// 配置
|
|
||||||
const editorConfig: Partial<IEditorConfig> = {
|
|
||||||
placeholder: "请输入",
|
|
||||||
MENU_CONF: {
|
|
||||||
uploadImage: {
|
|
||||||
customBrowseAndUpload(insertFn: any) {
|
|
||||||
temp.insertFn = insertFn;
|
|
||||||
ImageSpace.value.open();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
uploadVideo: {
|
|
||||||
customBrowseAndUpload(insertFn: any) {
|
|
||||||
temp.insertFn = insertFn;
|
|
||||||
VideoSpace.value.open();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 文件确认
|
|
||||||
function onSpaceConfirm(files: any[]) {
|
|
||||||
if (files.length > 0) {
|
|
||||||
files.forEach((file) => {
|
|
||||||
temp.insertFn(file.url);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
const editor = editorRef.value;
|
|
||||||
if (editor == null) return;
|
|
||||||
editor.destroy();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.cl-editor-wang {
|
|
||||||
border: 1px solid var(--el-border-color);
|
|
||||||
border-radius: var(--el-border-radius-base);
|
|
||||||
box-sizing: border-box;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
:deep(.w-e-toolbar) {
|
|
||||||
border-bottom: 1px solid var(--el-border-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,41 +0,0 @@
|
|||||||
<template>
|
|
||||||
<svg :class="svgClass" :style="style" aria-hidden="true">
|
|
||||||
<use :xlink:href="iconName" />
|
|
||||||
</svg>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" name="cl-svg" setup>
|
|
||||||
import { computed, ref } from "vue";
|
|
||||||
import { isNumber } from "lodash-es";
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
name: {
|
|
||||||
type: String
|
|
||||||
},
|
|
||||||
className: {
|
|
||||||
type: String
|
|
||||||
},
|
|
||||||
size: {
|
|
||||||
type: [String, Number]
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const style = ref({
|
|
||||||
fontSize: isNumber(props.size) ? props.size + "px" : props.size
|
|
||||||
});
|
|
||||||
|
|
||||||
const iconName = computed(() => `#icon-${props.name}`);
|
|
||||||
const svgClass = computed(() => {
|
|
||||||
return ["cl-svg", `cl-svg__${props.name}`, String(props.className || "")];
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.cl-svg {
|
|
||||||
width: 1em;
|
|
||||||
height: 1em;
|
|
||||||
vertical-align: -0.15em;
|
|
||||||
fill: currentColor;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,109 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div
|
|
||||||
class="cl-image"
|
|
||||||
:style="{
|
|
||||||
justifyContent: justify,
|
|
||||||
height: sty.h
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<el-image
|
|
||||||
:src="urls[0]"
|
|
||||||
:fit="fit"
|
|
||||||
:lazy="lazy"
|
|
||||||
:preview-src-list="urls"
|
|
||||||
:style="{
|
|
||||||
height: sty.h,
|
|
||||||
width: sty.w
|
|
||||||
}"
|
|
||||||
preview-teleported
|
|
||||||
>
|
|
||||||
<template #error>
|
|
||||||
<div class="image-slot">
|
|
||||||
<el-icon :size="20"><picture-filled /></el-icon>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-image>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { computed, defineComponent } from "vue";
|
|
||||||
import { isArray, isNumber, isString } from "lodash-es";
|
|
||||||
import { PictureFilled } from "@element-plus/icons-vue";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "cl-image",
|
|
||||||
|
|
||||||
components: {
|
|
||||||
PictureFilled
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
modelValue: [String, Array],
|
|
||||||
src: [String, Array],
|
|
||||||
size: {
|
|
||||||
type: [Number, Array],
|
|
||||||
default: 100
|
|
||||||
},
|
|
||||||
lazy: Boolean,
|
|
||||||
fit: {
|
|
||||||
type: String,
|
|
||||||
default: "cover"
|
|
||||||
},
|
|
||||||
justify: {
|
|
||||||
type: String,
|
|
||||||
default: "center"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setup(props) {
|
|
||||||
const urls = computed(() => {
|
|
||||||
const urls: any = props.modelValue || props.src;
|
|
||||||
|
|
||||||
if (isArray(urls)) {
|
|
||||||
return urls;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isString(urls)) {
|
|
||||||
return (urls || "").split(",").filter(Boolean);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
});
|
|
||||||
|
|
||||||
const sty = computed(() => {
|
|
||||||
const [h, w]: any = isNumber(props.size) ? [props.size, props.size] : props.size;
|
|
||||||
|
|
||||||
return {
|
|
||||||
h: isNumber(h) ? h + "px" : h,
|
|
||||||
w: isNumber(w) ? w + "px" : w
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
urls,
|
|
||||||
sty
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.cl-image {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.el-image {
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
.image-slot {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
height: 100%;
|
|
||||||
background-color: #f7f7f7;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,79 +0,0 @@
|
|||||||
<template>
|
|
||||||
<a v-for="item in urls" :key="item" class="cl-link" :href="item" :target="target">
|
|
||||||
<el-icon><icon-link /></el-icon>{{ filename(item) }}
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { defineComponent, computed } from "vue";
|
|
||||||
import { isArray, isString, last } from "lodash-es";
|
|
||||||
import { Link } from "@element-plus/icons-vue";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "cl-link",
|
|
||||||
|
|
||||||
components: {
|
|
||||||
"icon-link": Link
|
|
||||||
},
|
|
||||||
|
|
||||||
props: {
|
|
||||||
modelValue: [String, Array],
|
|
||||||
href: [String, Array],
|
|
||||||
text: {
|
|
||||||
type: String,
|
|
||||||
default: "查看"
|
|
||||||
},
|
|
||||||
target: {
|
|
||||||
type: String,
|
|
||||||
default: "_blank"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setup(props) {
|
|
||||||
const urls = computed(() => {
|
|
||||||
const urls: any = props.modelValue || props.href;
|
|
||||||
|
|
||||||
if (isArray(urls)) {
|
|
||||||
return urls;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isString(urls)) {
|
|
||||||
return (urls || "").split(",").filter(Boolean);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
});
|
|
||||||
|
|
||||||
function filename(url: string) {
|
|
||||||
return last(url.split("/"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
urls,
|
|
||||||
filename
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.cl-link {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
text-align: left;
|
|
||||||
background-color: var(--color-primary);
|
|
||||||
color: #fff;
|
|
||||||
padding: 0 5px;
|
|
||||||
border-radius: 5px;
|
|
||||||
font-size: 12px;
|
|
||||||
margin: 2px;
|
|
||||||
|
|
||||||
.el-icon {
|
|
||||||
margin-right: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,65 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-select v-model="value" @change="onChange" clearable>
|
|
||||||
<el-option
|
|
||||||
v-for="(item, index) in list"
|
|
||||||
:key="index"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
></el-option>
|
|
||||||
</el-select>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { useCrud } from "@cool-vue/crud";
|
|
||||||
import { computed, defineComponent, isRef, ref, watch } from "vue";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "cl-select",
|
|
||||||
|
|
||||||
props: {
|
|
||||||
modelValue: [String, Number],
|
|
||||||
options: {
|
|
||||||
type: [Array, Object],
|
|
||||||
default: () => []
|
|
||||||
},
|
|
||||||
prop: String
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ["update:modelValue", "change"],
|
|
||||||
|
|
||||||
setup(props, { emit }) {
|
|
||||||
// cl-crud
|
|
||||||
const Crud = useCrud();
|
|
||||||
const value = ref();
|
|
||||||
const list = computed<any>(() =>
|
|
||||||
isRef(props.options) ? props.options.value : props.options
|
|
||||||
);
|
|
||||||
|
|
||||||
// 值改变
|
|
||||||
function onChange(val: string) {
|
|
||||||
emit("update:modelValue", val);
|
|
||||||
emit("change", val);
|
|
||||||
|
|
||||||
if (props.prop) {
|
|
||||||
Crud.value?.refresh({ page: 1, [props.prop]: val === "" ? undefined : val });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.modelValue,
|
|
||||||
(val) => {
|
|
||||||
value.value = val;
|
|
||||||
},
|
|
||||||
{
|
|
||||||
immediate: true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
list,
|
|
||||||
value,
|
|
||||||
onChange
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
@ -1,86 +0,0 @@
|
|||||||
import { useCrud } from "@cool-vue/crud";
|
|
||||||
import { ElMessage } from "element-plus";
|
|
||||||
import { defineComponent, ref, watch } from "vue";
|
|
||||||
import { isBoolean } from "lodash-es";
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "cl-switch",
|
|
||||||
|
|
||||||
props: {
|
|
||||||
scope: null,
|
|
||||||
column: null,
|
|
||||||
modelValue: [Number, String, Boolean],
|
|
||||||
activeValue: {
|
|
||||||
type: [Number, String, Boolean],
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
inactiveValue: {
|
|
||||||
type: [Number, String, Boolean],
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ["update:modelValue", "change"],
|
|
||||||
|
|
||||||
setup(props, { emit }) {
|
|
||||||
// cl-crud
|
|
||||||
const Crud = useCrud();
|
|
||||||
|
|
||||||
// 状态
|
|
||||||
const status = ref<boolean | number | string>();
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.modelValue,
|
|
||||||
(val: any) => {
|
|
||||||
if (isBoolean(props.activeValue)) {
|
|
||||||
status.value = Boolean(val);
|
|
||||||
} else {
|
|
||||||
status.value = val;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
immediate: true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 监听改变
|
|
||||||
function onChange(val: boolean | string | number) {
|
|
||||||
if (props.column && props.scope) {
|
|
||||||
if (Crud.value?.service.update) {
|
|
||||||
Crud.value?.service
|
|
||||||
?.update({
|
|
||||||
...props.scope,
|
|
||||||
[props.column.property]: val
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success("更新成功");
|
|
||||||
emit("update:modelValue", val);
|
|
||||||
emit("change", val);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
ElMessage.error(err.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
emit("update:modelValue", val);
|
|
||||||
emit("change", val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
status,
|
|
||||||
onChange
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
render(ctx: any) {
|
|
||||||
return (
|
|
||||||
<el-switch
|
|
||||||
v-model={ctx.status}
|
|
||||||
active-value={ctx.activeValue}
|
|
||||||
inactive-value={ctx.inactiveValue}
|
|
||||||
onChange={ctx.onChange}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,150 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="cl-view-group">
|
|
||||||
<div class="cl-view-group__wrap">
|
|
||||||
<!-- 组 -->
|
|
||||||
<div class="cl-view-group__left" :class="[isExpand ? '_expand' : '_collapse']">
|
|
||||||
<slot name="left"></slot>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 内容 -->
|
|
||||||
<div class="cl-view-group__right">
|
|
||||||
<div class="cl-view-group__right-head">
|
|
||||||
<div class="icon" @click="toExpand()">
|
|
||||||
<el-icon v-if="isExpand"><arrow-left /></el-icon>
|
|
||||||
<el-icon v-else><arrow-right /></el-icon>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<span>{{ title }}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="cl-view-group__right-content">
|
|
||||||
<slot name="right"></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" name="cl-view-group" setup>
|
|
||||||
import { provide, ref, watch } from "vue";
|
|
||||||
import { ArrowLeft, ArrowRight } from "@element-plus/icons-vue";
|
|
||||||
import { useBase } from "/$/base";
|
|
||||||
|
|
||||||
defineProps({
|
|
||||||
title: String
|
|
||||||
});
|
|
||||||
|
|
||||||
const { app } = useBase();
|
|
||||||
|
|
||||||
// 是否展开
|
|
||||||
const isExpand = ref<boolean>(true);
|
|
||||||
|
|
||||||
// 收起、展开
|
|
||||||
function toExpand(value?: boolean) {
|
|
||||||
isExpand.value = value === undefined ? !isExpand.value : value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 小屏幕下
|
|
||||||
function checkExpand(value?: boolean) {
|
|
||||||
if (app.browser.isMini) {
|
|
||||||
toExpand(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听屏幕大小变化
|
|
||||||
watch(
|
|
||||||
() => app.browser.isMini,
|
|
||||||
(val: boolean) => {
|
|
||||||
isExpand.value = !val;
|
|
||||||
},
|
|
||||||
{
|
|
||||||
immediate: true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
provide("viewGroup", {
|
|
||||||
checkExpand
|
|
||||||
});
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
checkExpand
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.cl-view-group {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&__wrap {
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
position: relative;
|
|
||||||
background-color: var(--el-bg-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
&__left {
|
|
||||||
height: 100%;
|
|
||||||
width: 300px;
|
|
||||||
transition: width 0.3s;
|
|
||||||
flex-shrink: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
border-right: 1px solid var(--el-border-color);
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
&._collapse {
|
|
||||||
margin-right: 0;
|
|
||||||
width: 0 !important;
|
|
||||||
border-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__right {
|
|
||||||
width: calc(100% - 310px);
|
|
||||||
flex: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
&-head {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
height: 40px;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
span {
|
|
||||||
font-size: 14px;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
font-size: 18px;
|
|
||||||
cursor: pointer;
|
|
||||||
height: 40px;
|
|
||||||
width: 80px;
|
|
||||||
padding-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-content {
|
|
||||||
height: calc(100% - 40px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 768px) {
|
|
||||||
.cl-view-group__left {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cl-view-group__right {
|
|
||||||
width: calc(100% - 100px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,11 +1,13 @@
|
|||||||
import { ModuleConfig, config } from "/@/cool";
|
import { ModuleConfig, config } from "/@/cool";
|
||||||
import { useStore } from "./store";
|
import { useStore } from "./store";
|
||||||
|
import { App } from "vue";
|
||||||
|
import Admin from "@cool-vue/admin";
|
||||||
|
import "@cool-vue/admin/dist/index.css";
|
||||||
import "./static/css/index.scss";
|
import "./static/css/index.scss";
|
||||||
|
|
||||||
export default (): ModuleConfig => {
|
export default (): ModuleConfig => {
|
||||||
return {
|
return {
|
||||||
order: 99,
|
order: 99,
|
||||||
components: Object.values(import.meta.glob("./components/**/*")),
|
|
||||||
views: [
|
views: [
|
||||||
{
|
{
|
||||||
path: "/my/info",
|
path: "/my/info",
|
||||||
@ -56,7 +58,10 @@ export default (): ModuleConfig => {
|
|||||||
component: () => import("./pages/error-page/502.vue")
|
component: () => import("./pages/error-page/502.vue")
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
install() {
|
install(app: App) {
|
||||||
|
// 基础库
|
||||||
|
app.use(Admin);
|
||||||
|
|
||||||
// 设置标题
|
// 设置标题
|
||||||
document.title = config.app.name;
|
document.title = config.app.name;
|
||||||
},
|
},
|
||||||
|
@ -23,10 +23,10 @@ const { router, route } = useCool();
|
|||||||
const { menu } = useBase();
|
const { menu } = useBase();
|
||||||
|
|
||||||
// 选中标识
|
// 选中标识
|
||||||
const active = ref<string>("0");
|
const active = ref("");
|
||||||
|
|
||||||
// 选择导航
|
// 选择导航
|
||||||
function select(index: number) {
|
function select(index: any) {
|
||||||
menu.setMenu(index);
|
menu.setMenu(index);
|
||||||
|
|
||||||
// 获取第一个菜单地址
|
// 获取第一个菜单地址
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-views">
|
<div class="app-views">
|
||||||
<router-view v-slot="{ Component }">
|
<router-view v-slot="{ Component }">
|
||||||
<el-scrollbar>
|
<el-scrollbar :key="route.path">
|
||||||
<transition :name="app.info.router.transition">
|
<transition :name="app.info.router.transition">
|
||||||
<keep-alive :include="caches">
|
<keep-alive :include="caches">
|
||||||
<component :is="Component" />
|
<component :is="Component" />
|
||||||
@ -15,7 +15,9 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import { useBase } from "/$/base";
|
import { useBase } from "/$/base";
|
||||||
|
import { useCool } from "/@/cool";
|
||||||
|
|
||||||
|
const { route } = useCool();
|
||||||
const { process, app } = useBase();
|
const { process, app } = useBase();
|
||||||
|
|
||||||
// 缓存列表
|
// 缓存列表
|
||||||
|
@ -5,7 +5,7 @@ import { deepMerge, getBrowser, storage } from "/@/cool/utils";
|
|||||||
|
|
||||||
export const useAppStore = defineStore("app", function () {
|
export const useAppStore = defineStore("app", function () {
|
||||||
// 基本信息
|
// 基本信息
|
||||||
const info = ref<any>({
|
const info = reactive({
|
||||||
...config.app
|
...config.app
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -31,8 +31,8 @@ export const useAppStore = defineStore("app", function () {
|
|||||||
|
|
||||||
// 设置基本信息
|
// 设置基本信息
|
||||||
function set(data: any) {
|
function set(data: any) {
|
||||||
deepMerge(info.value, data);
|
deepMerge(info, data);
|
||||||
storage.set("__app__", info.value);
|
storage.set("__app__", info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置浏览器信息
|
// 设置浏览器信息
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
item.label
|
item.label
|
||||||
}}</el-button>
|
}}</el-button>
|
||||||
|
|
||||||
<component :is="item.component" v-model="scope.data" height="300px" />
|
<component :is="item.component" v-model="scope.data" />
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
height="630px"
|
height="630px"
|
||||||
width="1200px"
|
width="1200px"
|
||||||
keep-alive
|
keep-alive
|
||||||
|
:draggable="false"
|
||||||
custom-class="cl-chat__dialog"
|
custom-class="cl-chat__dialog"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
close-on-press-escape
|
close-on-press-escape
|
||||||
|
@ -63,7 +63,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<cl-upload @success="onImageSend" :show-file-list="false">
|
<cl-upload @success="onImageSend" :show-file-list="false">
|
||||||
<li>
|
<li>
|
||||||
<el-icon><Picture /></el-icon>
|
<el-icon><picture /></el-icon>
|
||||||
</li>
|
</li>
|
||||||
</cl-upload>
|
</cl-upload>
|
||||||
|
|
||||||
|
109
src/modules/demo/components/form-crud.vue
Normal file
109
src/modules/demo/components/form-crud.vue
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
<template>
|
||||||
|
<el-button @click="open">自定义表单</el-button>
|
||||||
|
|
||||||
|
<cl-form ref="Form">
|
||||||
|
<template #slot-crud>
|
||||||
|
<cl-crud ref="Crud">
|
||||||
|
<el-row>
|
||||||
|
<!-- 刷新按钮 -->
|
||||||
|
<cl-refresh-btn />
|
||||||
|
<!-- 新增按钮 -->
|
||||||
|
<cl-add-btn />
|
||||||
|
<!-- 删除按钮 -->
|
||||||
|
<cl-multi-delete-btn />
|
||||||
|
<cl-flex1 />
|
||||||
|
<!-- 关键字搜索 -->
|
||||||
|
<cl-search-key />
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row>
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<cl-table ref="Table" />
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row>
|
||||||
|
<cl-flex1 />
|
||||||
|
<!-- 分页控件 -->
|
||||||
|
<cl-pagination />
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<!-- 新增、编辑 -->
|
||||||
|
<cl-upsert ref="Upsert" />
|
||||||
|
</cl-crud>
|
||||||
|
</template>
|
||||||
|
</cl-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" name="菜单名称" setup>
|
||||||
|
import { useCrud, useForm, useTable, useUpsert } from "@cool-vue/crud";
|
||||||
|
|
||||||
|
// cl-upsert 配置
|
||||||
|
const Upsert = useUpsert({
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: "姓名",
|
||||||
|
prop: "name",
|
||||||
|
component: {
|
||||||
|
name: "el-input"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "创建时间",
|
||||||
|
prop: "createTime",
|
||||||
|
component: {
|
||||||
|
name: "el-date-picker"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// cl-table 配置
|
||||||
|
const Table = useTable({
|
||||||
|
autoHeight: false,
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
type: "selection"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "姓名",
|
||||||
|
prop: "name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "创建时间",
|
||||||
|
prop: "createTime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "op"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// cl-crud 配置
|
||||||
|
const Crud = useCrud(
|
||||||
|
{
|
||||||
|
service: "test"
|
||||||
|
},
|
||||||
|
(app) => {
|
||||||
|
app.refresh();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const Form = useForm();
|
||||||
|
|
||||||
|
function open() {
|
||||||
|
Form.value?.open({
|
||||||
|
title: "内嵌crud",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: "",
|
||||||
|
props: {
|
||||||
|
labelWidth: "0"
|
||||||
|
},
|
||||||
|
component: {
|
||||||
|
name: "slot-crud"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
@ -3,61 +3,43 @@
|
|||||||
<el-row>
|
<el-row>
|
||||||
<cl-refresh-btn />
|
<cl-refresh-btn />
|
||||||
<cl-add-btn />
|
<cl-add-btn />
|
||||||
<el-button @click="openForm">自定义表单</el-button>
|
<form-crud />
|
||||||
|
|
||||||
<cl-filter label="字典">
|
<cl-filter label="字典筛选">
|
||||||
<cl-select :options="dict.get('brand')"></cl-select>
|
<cl-select :options="dict.get('brand')" prop="brand" />
|
||||||
</cl-filter>
|
</cl-filter>
|
||||||
|
|
||||||
<cl-flex1></cl-flex1>
|
<cl-flex1 />
|
||||||
<cl-column-custom :columns="Table?.columns" />
|
<cl-column-custom :columns="Table?.columns" />
|
||||||
<cl-search-key />
|
<cl-search-key />
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row>
|
<el-row>
|
||||||
<cl-table ref="Table">
|
<cl-table ref="Table" />
|
||||||
<template #slot-btn>
|
|
||||||
<el-button>btn</el-button>
|
|
||||||
</template>
|
|
||||||
</cl-table>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row>
|
<el-row>
|
||||||
<cl-flex1></cl-flex1>
|
<cl-flex1 />
|
||||||
<cl-pagination></cl-pagination>
|
<cl-pagination />
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<cl-upsert ref="Upsert">
|
<cl-upsert ref="Upsert" />
|
||||||
<template #slot-crud>
|
|
||||||
<cl-crud ref="Crud2" padding="0">
|
|
||||||
<el-row>
|
|
||||||
<cl-refresh-btn></cl-refresh-btn>
|
|
||||||
</el-row>
|
|
||||||
<el-row>
|
|
||||||
<cl-table :auto-height="false" ref="Table2"></cl-table>
|
|
||||||
</el-row>
|
|
||||||
</cl-crud>
|
|
||||||
</template>
|
|
||||||
</cl-upsert>
|
|
||||||
</cl-crud>
|
</cl-crud>
|
||||||
|
|
||||||
<cl-dialog title="xxx" v-model="dialog.visible"> xxxx </cl-dialog>
|
|
||||||
|
|
||||||
<cl-form ref="Form"></cl-form>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="tsx" setup name="crud">
|
<script lang="tsx" setup name="crud">
|
||||||
import { useCrud, useUpsert, useTable, useForm } from "@cool-vue/crud";
|
import { useCrud, useUpsert, useTable } from "@cool-vue/crud";
|
||||||
import { reactive } from "vue";
|
|
||||||
import { useDict } from "/$/dict";
|
import { useDict } from "/$/dict";
|
||||||
|
import FormCrud from "../components/form-crud.vue";
|
||||||
|
|
||||||
const { dict } = useDict();
|
const { dict } = useDict();
|
||||||
|
|
||||||
console.log(dict.get("brand").value);
|
|
||||||
|
|
||||||
const Crud = useCrud(
|
const Crud = useCrud(
|
||||||
{
|
{
|
||||||
service: "test"
|
service: "test",
|
||||||
|
async onRefresh(params, { next }) {
|
||||||
|
console.log(await next(params));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
(app) => {
|
(app) => {
|
||||||
app.refresh();
|
app.refresh();
|
||||||
@ -74,39 +56,33 @@ const Upsert = useUpsert({
|
|||||||
name: "el-input"
|
name: "el-input"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: "tabs",
|
||||||
|
props: {
|
||||||
|
labels: [
|
||||||
|
{
|
||||||
|
label: "基础",
|
||||||
|
value: "base"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "其他",
|
||||||
|
value: "other"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: "认证类型",
|
label: "认证类型",
|
||||||
prop: "authType",
|
prop: "authType",
|
||||||
|
group: "base",
|
||||||
component: {
|
component: {
|
||||||
name: "el-select",
|
name: "el-select",
|
||||||
options: dict.get("type")
|
options: dict.get("type")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
type: "tabs",
|
|
||||||
props: {
|
|
||||||
labels: [
|
|
||||||
{
|
|
||||||
label: "A",
|
|
||||||
value: "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "B",
|
|
||||||
value: "2"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "内嵌Crud",
|
|
||||||
group: "1",
|
|
||||||
component: {
|
|
||||||
name: "slot-crud"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: "年龄",
|
label: "年龄",
|
||||||
group: "2",
|
group: "other",
|
||||||
prop: "age",
|
prop: "age",
|
||||||
component: {
|
component: {
|
||||||
name: "el-input-number"
|
name: "el-input-number"
|
||||||
@ -142,6 +118,13 @@ const Table = useTable({
|
|||||||
label: "姓名",
|
label: "姓名",
|
||||||
prop: "name"
|
prop: "name"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: "存款",
|
||||||
|
prop: "price",
|
||||||
|
formatter(row) {
|
||||||
|
return `¥${row.price}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: "状态",
|
label: "状态",
|
||||||
prop: "status",
|
prop: "status",
|
||||||
@ -152,13 +135,15 @@ const Table = useTable({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "关闭",
|
label: "关闭",
|
||||||
|
type: "danger",
|
||||||
value: 0
|
value: 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "创建时间",
|
label: "创建时间",
|
||||||
prop: "createTime"
|
prop: "createTime",
|
||||||
|
sortable: "desc"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "op",
|
type: "op",
|
||||||
@ -167,67 +152,4 @@ const Table = useTable({
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
const dialog = reactive({
|
|
||||||
visible: false
|
|
||||||
});
|
|
||||||
|
|
||||||
const Form = useForm();
|
|
||||||
|
|
||||||
// 内嵌
|
|
||||||
const Crud2 = useCrud(
|
|
||||||
{
|
|
||||||
service: "test"
|
|
||||||
},
|
|
||||||
(app) => {
|
|
||||||
app.refresh();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const Table2 = useTable({
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
label: "姓名",
|
|
||||||
prop: "name"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "创建时间",
|
|
||||||
prop: "createTime"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
function openForm() {
|
|
||||||
return (dialog.visible = true);
|
|
||||||
|
|
||||||
Form.value?.open({
|
|
||||||
title: "自定义表单",
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
label: "姓名",
|
|
||||||
prop: "name",
|
|
||||||
required: true,
|
|
||||||
component: {
|
|
||||||
name: "el-input"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
on: {
|
|
||||||
submit(data, { close }) {
|
|
||||||
console.log(data);
|
|
||||||
setTimeout(() => {
|
|
||||||
close();
|
|
||||||
}, 1500);
|
|
||||||
},
|
|
||||||
open(data) {
|
|
||||||
console.log("form open", data);
|
|
||||||
Crud2.value?.refresh();
|
|
||||||
},
|
|
||||||
close(done) {
|
|
||||||
console.log("form close");
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -74,7 +74,7 @@ const chartOption = reactive({
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__container {
|
&__container {
|
||||||
height: 415px;
|
height: 395px;
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
@ -42,40 +42,9 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<div class="hot-search__table">
|
<div class="hot-search__table">
|
||||||
<cl-crud ref="Crud">
|
<cl-crud ref="Crud" padding="0">
|
||||||
<el-row>
|
<el-row>
|
||||||
<cl-table
|
<cl-table ref="Table" :border="false" />
|
||||||
:border="false"
|
|
||||||
:auto-height="false"
|
|
||||||
:default-sort="{
|
|
||||||
prop: 'ud',
|
|
||||||
order: 'descending'
|
|
||||||
}"
|
|
||||||
:context-menu="false"
|
|
||||||
:columns="[
|
|
||||||
{
|
|
||||||
label: '排名',
|
|
||||||
type: 'index',
|
|
||||||
width: 60
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '搜索关键词',
|
|
||||||
prop: 'keyWord',
|
|
||||||
minWidth: 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '用户数',
|
|
||||||
prop: 'users',
|
|
||||||
minWidth: 100
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '周涨幅',
|
|
||||||
prop: 'ud',
|
|
||||||
sortable: 'custom',
|
|
||||||
minWidth: 100
|
|
||||||
}
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
</cl-crud>
|
</cl-crud>
|
||||||
</div>
|
</div>
|
||||||
@ -86,7 +55,7 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive } from "vue";
|
import { reactive } from "vue";
|
||||||
import * as echarts from "echarts";
|
import * as echarts from "echarts";
|
||||||
import { useCrud } from "@cool-vue/crud";
|
import { useCrud, useTable } from "@cool-vue/crud";
|
||||||
|
|
||||||
const chartOption = reactive({
|
const chartOption = reactive({
|
||||||
grid: {
|
grid: {
|
||||||
@ -224,6 +193,34 @@ const Crud = useCrud(
|
|||||||
app.refresh();
|
app.refresh();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const Table = useTable({
|
||||||
|
autoHeight: false,
|
||||||
|
contextMenu: false,
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
label: "排名",
|
||||||
|
type: "index",
|
||||||
|
width: 60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "搜索关键词",
|
||||||
|
prop: "keyWord",
|
||||||
|
minWidth: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "用户数",
|
||||||
|
prop: "users",
|
||||||
|
minWidth: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "周涨幅",
|
||||||
|
prop: "ud",
|
||||||
|
sortable: "desc",
|
||||||
|
minWidth: 100
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -50,6 +50,15 @@
|
|||||||
<el-form-item label="菜单分组显示">
|
<el-form-item label="菜单分组显示">
|
||||||
<el-switch v-model="form.theme.isGroup" @change="setGroup"></el-switch>
|
<el-switch v-model="form.theme.isGroup" @change="setGroup"></el-switch>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="转场动画">
|
||||||
|
<el-switch
|
||||||
|
v-model="form.theme.transition"
|
||||||
|
active-value="slide"
|
||||||
|
inactive-value="none"
|
||||||
|
@change="setTransition"
|
||||||
|
></el-switch>
|
||||||
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
@ -57,35 +66,30 @@
|
|||||||
|
|
||||||
<script lang="ts" setup name="cl-theme">
|
<script lang="ts" setup name="cl-theme">
|
||||||
import { reactive, ref } from "vue";
|
import { reactive, ref } from "vue";
|
||||||
import { setTheme, themes } from "../utils";
|
|
||||||
import { module } from "/@/cool";
|
|
||||||
import store from "store";
|
|
||||||
import { Check, Moon, Sunny } from "@element-plus/icons-vue";
|
import { Check, Moon, Sunny } from "@element-plus/icons-vue";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { useBase } from "/$/base";
|
import { useBase } from "/$/base";
|
||||||
import { useDark } from "@vueuse/core";
|
import { useDark } from "@vueuse/core";
|
||||||
|
import { storage } from "/@/cool";
|
||||||
|
import { Theme } from "../types";
|
||||||
|
import { setTheme, themes } from "../utils";
|
||||||
|
|
||||||
const { app, menu } = useBase();
|
const { menu } = useBase();
|
||||||
|
|
||||||
// 是否暗黑模式
|
// 是否暗黑模式
|
||||||
const isDark = ref(useDark());
|
const isDark = ref(useDark());
|
||||||
|
|
||||||
// 当前主题
|
// 当前主题
|
||||||
const theme = reactive<any>(store.get("theme") || module.get("theme"));
|
const theme = reactive<Theme>(storage.get("theme"));
|
||||||
|
|
||||||
// 菜单分组显示默认值
|
|
||||||
if (theme.isGroup === undefined) {
|
|
||||||
theme.isGroup = app.info.menu.isGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表单
|
// 表单
|
||||||
const form = reactive<any>({
|
const form = reactive<{ color: string; theme: Theme }>({
|
||||||
color: theme.color || "",
|
color: theme.color || "",
|
||||||
theme
|
theme
|
||||||
});
|
});
|
||||||
|
|
||||||
// 抽屉
|
// 抽屉
|
||||||
const visible = ref<boolean>(false);
|
const visible = ref(false);
|
||||||
|
|
||||||
// 打开
|
// 打开
|
||||||
function open() {
|
function open() {
|
||||||
@ -113,15 +117,15 @@ function setComd(item: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 设置分组
|
// 设置分组
|
||||||
function setGroup(val: boolean) {
|
function setGroup(val: any) {
|
||||||
setTheme({ isGroup: val });
|
setTheme({ isGroup: val });
|
||||||
app.set({
|
|
||||||
menu: {
|
|
||||||
isGroup: val
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.setMenu();
|
menu.setMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置转场动画
|
||||||
|
function setTransition(val: any) {
|
||||||
|
setTheme({ transition: val });
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import store from "store";
|
|
||||||
import { setTheme } from "./utils";
|
import { setTheme } from "./utils";
|
||||||
import { ModuleConfig, config } from "/@/cool";
|
import { config, ModuleConfig, storage } from "/@/cool";
|
||||||
import "element-plus/theme-chalk/dark/css-vars.css";
|
import "element-plus/theme-chalk/dark/css-vars.css";
|
||||||
import "./static/css/index.scss";
|
import "./static/css/index.scss";
|
||||||
|
|
||||||
@ -16,15 +15,17 @@ export default (): ModuleConfig => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
install(_, options) {
|
install(_, options) {
|
||||||
const theme = store.get("theme") || options;
|
const data =
|
||||||
|
storage.get("theme") ||
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
|
isGroup: config.app.menu.isGroup,
|
||||||
|
transition: config.app.router.transition
|
||||||
|
},
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
if (theme) {
|
setTheme(data);
|
||||||
if (theme.isGroup !== undefined) {
|
|
||||||
config.app.menu.isGroup = theme.isGroup;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTheme(theme);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
6
src/modules/theme/types/index.d.ts
vendored
Normal file
6
src/modules/theme/types/index.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export declare interface Theme {
|
||||||
|
color?: string;
|
||||||
|
name?: string;
|
||||||
|
isGroup?: boolean;
|
||||||
|
transition?: string;
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
import store from "store";
|
import { Theme } from "../types";
|
||||||
|
import { useBase } from "/$/base";
|
||||||
|
import { storage } from "/@/cool";
|
||||||
|
|
||||||
function mix(color1: string, color2: string, weight: number) {
|
function mix(color1: string, color2: string, weight: number) {
|
||||||
weight = Math.max(Math.min(Number(weight), 1), 0);
|
weight = Math.max(Math.min(Number(weight), 1), 0);
|
||||||
@ -40,15 +42,11 @@ export const themes = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
declare interface Options {
|
export function setTheme({ color, name, isGroup, transition }: Theme) {
|
||||||
color?: string;
|
const { app } = useBase();
|
||||||
name?: string;
|
|
||||||
isGroup?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setTheme({ color, name, isGroup }: Options) {
|
|
||||||
// 主题配置
|
// 主题配置
|
||||||
const theme = store.get("theme") || {};
|
const theme = storage.get("theme") || {};
|
||||||
|
|
||||||
// 变量前缀
|
// 变量前缀
|
||||||
const pre = "--el-color-primary";
|
const pre = "--el-color-primary";
|
||||||
@ -91,7 +89,22 @@ export function setTheme({ color, name, isGroup }: Options) {
|
|||||||
// 菜单分组显示
|
// 菜单分组显示
|
||||||
if (isGroup !== undefined) {
|
if (isGroup !== undefined) {
|
||||||
theme.isGroup = isGroup;
|
theme.isGroup = isGroup;
|
||||||
|
app.set({
|
||||||
|
menu: {
|
||||||
|
isGroup
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
store.set("theme", theme);
|
// 转场动画
|
||||||
|
if (transition !== undefined) {
|
||||||
|
theme.transition = transition;
|
||||||
|
app.set({
|
||||||
|
router: {
|
||||||
|
transition
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
storage.set("theme", theme);
|
||||||
}
|
}
|
||||||
|
82
yarn.lock
82
yarn.lock
@ -992,7 +992,7 @@
|
|||||||
"@codemirror/view" "^6.0.0"
|
"@codemirror/view" "^6.0.0"
|
||||||
"@lezer/common" "^1.0.0"
|
"@lezer/common" "^1.0.0"
|
||||||
|
|
||||||
"@codemirror/lang-javascript@^6.0.1":
|
"@codemirror/lang-javascript@^6.0.1", "@codemirror/lang-javascript@^6.1.0":
|
||||||
version "6.1.0"
|
version "6.1.0"
|
||||||
resolved "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.1.0.tgz#3b3ddfed59c5fb39b210c13f1e0e8e5a65f009f3"
|
resolved "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.1.0.tgz#3b3ddfed59c5fb39b210c13f1e0e8e5a65f009f3"
|
||||||
integrity sha512-wAWEY1Wdis2cKDy9A5q/rUmzLHFbZgoupJBcGaeMMsDPi68Rm90NsmzAEODE5kW8mYdRKFhQ157WJghOZ3yYdg==
|
integrity sha512-wAWEY1Wdis2cKDy9A5q/rUmzLHFbZgoupJBcGaeMMsDPi68Rm90NsmzAEODE5kW8mYdRKFhQ157WJghOZ3yYdg==
|
||||||
@ -1040,7 +1040,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@codemirror/state/-/state-6.1.2.tgz#182d46eabcc17c95508984d6add5a5a641dcd517"
|
resolved "https://registry.npmjs.org/@codemirror/state/-/state-6.1.2.tgz#182d46eabcc17c95508984d6add5a5a641dcd517"
|
||||||
integrity sha512-Mxff85Hp5va+zuj+H748KbubXjrinX/k28lj43H14T2D0+4kuvEFIEIO7hCEcvBT8ubZyIelt9yGOjj2MWOEQA==
|
integrity sha512-Mxff85Hp5va+zuj+H748KbubXjrinX/k28lj43H14T2D0+4kuvEFIEIO7hCEcvBT8ubZyIelt9yGOjj2MWOEQA==
|
||||||
|
|
||||||
"@codemirror/theme-one-dark@^6.0.0":
|
"@codemirror/theme-one-dark@^6.0.0", "@codemirror/theme-one-dark@^6.1.0":
|
||||||
version "6.1.0"
|
version "6.1.0"
|
||||||
resolved "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.0.tgz#6f8b3c7fc22e9fec59edd573f4ba9546db42e007"
|
resolved "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.0.tgz#6f8b3c7fc22e9fec59edd573f4ba9546db42e007"
|
||||||
integrity sha512-AiTHtFRu8+vWT9wWUWDM+cog6ZwgivJogB1Tm/g40NIpLwph7AnmxrSzWfvJN5fBVufsuwBxecQCNmdcR5D7Aw==
|
integrity sha512-AiTHtFRu8+vWT9wWUWDM+cog6ZwgivJogB1Tm/g40NIpLwph7AnmxrSzWfvJN5fBVufsuwBxecQCNmdcR5D7Aw==
|
||||||
@ -1059,10 +1059,30 @@
|
|||||||
style-mod "^4.0.0"
|
style-mod "^4.0.0"
|
||||||
w3c-keyname "^2.2.4"
|
w3c-keyname "^2.2.4"
|
||||||
|
|
||||||
"@cool-vue/crud@^5.6.1":
|
"@cool-vue/admin@^5.0.1":
|
||||||
version "5.6.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.npmjs.org/@cool-vue/crud/-/crud-5.6.1.tgz#1857bc63a78ac7a7f7226ebca073b40298ade820"
|
resolved "https://registry.npmjs.org/@cool-vue/admin/-/admin-5.0.1.tgz#2ef3803b9dcee699a57fa84e9987aad10282dd11"
|
||||||
integrity sha512-KyMaEGkxf6U14W+MU7BWf4WYjqXuHyKwDoVSxAGKUfHl1idh+TcVjiY0Q5lBhowYtUMB3NvNQxKPrpaUYOP9ww==
|
integrity sha512-laegNS96vy5dHwniaaSVe/LY9W2KWDduIj3F5wF60FbHfhuuTGHPU8QDPGb6NahMdWJZjzvk62avyjkSMvJorA==
|
||||||
|
dependencies:
|
||||||
|
"@codemirror/lang-javascript" "^6.1.0"
|
||||||
|
"@codemirror/theme-one-dark" "^6.1.0"
|
||||||
|
"@cool-vue/crud" "^5.6.3"
|
||||||
|
"@vueuse/core" "^9.3.0"
|
||||||
|
"@wangeditor/editor" "^5.1.20"
|
||||||
|
"@wangeditor/editor-for-vue" "^5.1.12"
|
||||||
|
codemirror "^6.0.1"
|
||||||
|
dayjs "^1.11.5"
|
||||||
|
element-plus "^2.2.17"
|
||||||
|
lodash-es "^4.17.21"
|
||||||
|
quill "^1.3.7"
|
||||||
|
store "^2.0.12"
|
||||||
|
vue "^3.2.39"
|
||||||
|
vue-codemirror "^6.1.1"
|
||||||
|
|
||||||
|
"@cool-vue/crud@^5.6.3", "@cool-vue/crud@^5.6.4":
|
||||||
|
version "5.6.4"
|
||||||
|
resolved "https://registry.npmjs.org/@cool-vue/crud/-/crud-5.6.4.tgz#52f2afd16c26be8348d262ffa20a345186d6768a"
|
||||||
|
integrity sha512-oJ8yWqoNB7eYGDpwE/+GPRFj6G2sYOLT92PxPEY/JzGq7c4PhxOh65rypFDNV/JVdvHFGqFjcxkxsJRfaMOFpg==
|
||||||
dependencies:
|
dependencies:
|
||||||
array.prototype.flat "^1.2.4"
|
array.prototype.flat "^1.2.4"
|
||||||
core-js "^3.21.1"
|
core-js "^3.21.1"
|
||||||
@ -1795,7 +1815,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.2.39.tgz#302df167559a1a5156da162d8cc6760cef67f8e3"
|
resolved "https://registry.npmjs.org/@vue/shared/-/shared-3.2.39.tgz#302df167559a1a5156da162d8cc6760cef67f8e3"
|
||||||
integrity sha512-D3dl2ZB9qE6mTuWPk9RlhDeP1dgNRUKC3NJxji74A4yL8M2MwlhLKUC/49WHjrNzSPug58fWx/yFbaTzGAQSBw==
|
integrity sha512-D3dl2ZB9qE6mTuWPk9RlhDeP1dgNRUKC3NJxji74A4yL8M2MwlhLKUC/49WHjrNzSPug58fWx/yFbaTzGAQSBw==
|
||||||
|
|
||||||
"@vueuse/core@^9.1.0":
|
"@vueuse/core@^9.1.0", "@vueuse/core@^9.3.0":
|
||||||
version "9.3.0"
|
version "9.3.0"
|
||||||
resolved "https://registry.npmjs.org/@vueuse/core/-/core-9.3.0.tgz#74d855bd19cb5eadd2edb30c871918fac881e8b8"
|
resolved "https://registry.npmjs.org/@vueuse/core/-/core-9.3.0.tgz#74d855bd19cb5eadd2edb30c871918fac881e8b8"
|
||||||
integrity sha512-64Rna8IQDWpdrJxgitDg7yv1yTp41ZmvV8zlLEylK4QQLWAhz1OFGZDPZ8bU4lwcGgbEJ2sGi2jrdNh4LttUSQ==
|
integrity sha512-64Rna8IQDWpdrJxgitDg7yv1yTp41ZmvV8zlLEylK4QQLWAhz1OFGZDPZ8bU4lwcGgbEJ2sGi2jrdNh4LttUSQ==
|
||||||
@ -1843,6 +1863,18 @@
|
|||||||
scroll-into-view-if-needed "^2.2.28"
|
scroll-into-view-if-needed "^2.2.28"
|
||||||
slate-history "^0.66.0"
|
slate-history "^0.66.0"
|
||||||
|
|
||||||
|
"@wangeditor/core@^1.1.16":
|
||||||
|
version "1.1.16"
|
||||||
|
resolved "https://registry.npmjs.org/@wangeditor/core/-/core-1.1.16.tgz#c44df699fb98ca2e726517dcbacf809df160420d"
|
||||||
|
integrity sha512-EhPO0DhDSDUqeRQ3yuMATCfLP9DJhWVc91pd3wG5Z9r1H3HLQG3aNLODAJA58D3J8RRIlpnE5q23d58wum7TFw==
|
||||||
|
dependencies:
|
||||||
|
"@types/event-emitter" "^0.3.3"
|
||||||
|
event-emitter "^0.3.5"
|
||||||
|
html-void-elements "^2.0.0"
|
||||||
|
i18next "^20.4.0"
|
||||||
|
scroll-into-view-if-needed "^2.2.28"
|
||||||
|
slate-history "^0.66.0"
|
||||||
|
|
||||||
"@wangeditor/editor-for-vue@^5.1.12":
|
"@wangeditor/editor-for-vue@^5.1.12":
|
||||||
version "5.1.12"
|
version "5.1.12"
|
||||||
resolved "https://registry.npmjs.org/@wangeditor/editor-for-vue/-/editor-for-vue-5.1.12.tgz#f7d5f239b39cdfc01d31151488de8443fe6edc64"
|
resolved "https://registry.npmjs.org/@wangeditor/editor-for-vue/-/editor-for-vue-5.1.12.tgz#f7d5f239b39cdfc01d31151488de8443fe6edc64"
|
||||||
@ -1875,11 +1907,43 @@
|
|||||||
slate "^0.72.0"
|
slate "^0.72.0"
|
||||||
snabbdom "^3.1.0"
|
snabbdom "^3.1.0"
|
||||||
|
|
||||||
|
"@wangeditor/editor@^5.1.20":
|
||||||
|
version "5.1.20"
|
||||||
|
resolved "https://registry.npmjs.org/@wangeditor/editor/-/editor-5.1.20.tgz#ee8bca92b61b313bdf4496e457a72b035c6dfb6a"
|
||||||
|
integrity sha512-qMUyKUNZaZN/JcWg8HFKaTlu04srSNIabiUCdNtK99sk7oIMptkdbEJ/lnxOHbsQZQyz1bmf3DsfQySruxy6Ow==
|
||||||
|
dependencies:
|
||||||
|
"@uppy/core" "^2.1.1"
|
||||||
|
"@uppy/xhr-upload" "^2.0.3"
|
||||||
|
"@wangeditor/basic-modules" "^1.1.6"
|
||||||
|
"@wangeditor/code-highlight" "^1.0.3"
|
||||||
|
"@wangeditor/core" "^1.1.16"
|
||||||
|
"@wangeditor/list-module" "^1.0.5"
|
||||||
|
"@wangeditor/table-module" "^1.1.4"
|
||||||
|
"@wangeditor/upload-image-module" "^1.0.2"
|
||||||
|
"@wangeditor/video-module" "^1.1.4"
|
||||||
|
dom7 "^3.0.0"
|
||||||
|
is-hotkey "^0.2.0"
|
||||||
|
lodash.camelcase "^4.3.0"
|
||||||
|
lodash.clonedeep "^4.5.0"
|
||||||
|
lodash.debounce "^4.0.8"
|
||||||
|
lodash.foreach "^4.5.0"
|
||||||
|
lodash.isequal "^4.5.0"
|
||||||
|
lodash.throttle "^4.1.1"
|
||||||
|
lodash.toarray "^4.4.0"
|
||||||
|
nanoid "^3.2.0"
|
||||||
|
slate "^0.72.0"
|
||||||
|
snabbdom "^3.1.0"
|
||||||
|
|
||||||
"@wangeditor/list-module@^1.0.4":
|
"@wangeditor/list-module@^1.0.4":
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.npmjs.org/@wangeditor/list-module/-/list-module-1.0.4.tgz#7cdc5f4816066893265c07bd3dd95e033a648f60"
|
resolved "https://registry.npmjs.org/@wangeditor/list-module/-/list-module-1.0.4.tgz#7cdc5f4816066893265c07bd3dd95e033a648f60"
|
||||||
integrity sha512-TiZREga19+GHzNNiRWUvOqLcVOdHZSuYW8VmXddgAHOQma+uBcfodZJK7xBLOhaGO0jiFuOGAVIXUroRvYGIDw==
|
integrity sha512-TiZREga19+GHzNNiRWUvOqLcVOdHZSuYW8VmXddgAHOQma+uBcfodZJK7xBLOhaGO0jiFuOGAVIXUroRvYGIDw==
|
||||||
|
|
||||||
|
"@wangeditor/list-module@^1.0.5":
|
||||||
|
version "1.0.5"
|
||||||
|
resolved "https://registry.npmjs.org/@wangeditor/list-module/-/list-module-1.0.5.tgz#3fc0b167acddf885536b45fa0c127f9c6adaea33"
|
||||||
|
integrity sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ==
|
||||||
|
|
||||||
"@wangeditor/table-module@^1.1.4":
|
"@wangeditor/table-module@^1.1.4":
|
||||||
version "1.1.4"
|
version "1.1.4"
|
||||||
resolved "https://registry.npmjs.org/@wangeditor/table-module/-/table-module-1.1.4.tgz#757d4a5868b2b658041cd323854a4d707c8347e9"
|
resolved "https://registry.npmjs.org/@wangeditor/table-module/-/table-module-1.1.4.tgz#757d4a5868b2b658041cd323854a4d707c8347e9"
|
||||||
@ -2491,7 +2555,7 @@ d@1, d@^1.0.1:
|
|||||||
es5-ext "^0.10.50"
|
es5-ext "^0.10.50"
|
||||||
type "^1.0.1"
|
type "^1.0.1"
|
||||||
|
|
||||||
dayjs@^1.11.3:
|
dayjs@^1.11.3, dayjs@^1.11.5:
|
||||||
version "1.11.5"
|
version "1.11.5"
|
||||||
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.5.tgz#00e8cc627f231f9499c19b38af49f56dc0ac5e93"
|
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.5.tgz#00e8cc627f231f9499c19b38af49f56dc0ac5e93"
|
||||||
integrity sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==
|
integrity sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==
|
||||||
@ -5025,7 +5089,7 @@ vite@^3.0.6:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.3.2"
|
fsevents "~2.3.2"
|
||||||
|
|
||||||
vue-codemirror@^6.0.1:
|
vue-codemirror@^6.0.1, vue-codemirror@^6.1.1:
|
||||||
version "6.1.1"
|
version "6.1.1"
|
||||||
resolved "https://registry.npmjs.org/vue-codemirror/-/vue-codemirror-6.1.1.tgz#246697ef4cfa6b2448dd592ade214bb7ff86611f"
|
resolved "https://registry.npmjs.org/vue-codemirror/-/vue-codemirror-6.1.1.tgz#246697ef4cfa6b2448dd592ade214bb7ff86611f"
|
||||||
integrity sha512-rTAYo44owd282yVxKtJtnOi7ERAcXTeviwoPXjIc6K/IQYUsoDkzPvw/JDFtSP6T7Cz/2g3EHaEyeyaQCKoDMg==
|
integrity sha512-rTAYo44owd282yVxKtJtnOi7ERAcXTeviwoPXjIc6K/IQYUsoDkzPvw/JDFtSP6T7Cz/2g3EHaEyeyaQCKoDMg==
|
||||||
|
Loading…
Reference in New Issue
Block a user