build 调整

This commit is contained in:
icssoa 2021-04-01 18:36:57 +08:00
parent a6b3e9118e
commit 13b2788a84
33 changed files with 5143 additions and 414 deletions

View File

@ -1,3 +1 @@
vue.config.js
/src/crud
/src/core
vue.config.js

4571
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
{
"name": "front-next",
"version": "0.0.1",
"version": "0.1.0",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"build": "vue-tsc --noEmit --skipLibCheck && vite build",
"serve": "vite preview",
"lint:prettier": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
"lint:eslint": "eslint \"{src,mock}/**/*.{vue,ts,tsx}\" --fix"
@ -34,6 +34,8 @@
"vuex": "^4.0.0-0"
},
"devDependencies": {
"@types/lodash": "^4.14.168",
"@types/node": "^14.14.37",
"@typescript-eslint/eslint-plugin": "^4.20.0",
"@typescript-eslint/parser": "^4.20.0",
"@vitejs/plugin-vue": "^1.1.5",

View File

@ -10,7 +10,7 @@ export default defineComponent({
setup(_: any, { emit }) {
const $service = inject<any>("service");
const { refs, setRefs } = useRefs();
const { refs, setRefs }: any = useRefs();
// 树形列表
const list = ref<any[]>([]);

View File

@ -23,7 +23,7 @@
</ul>
</div>
<div class="cl-dept-tree__container" @contextmenu.prevent="openCM">
<div class="cl-dept-tree__container" @contextmenu.stop.prevent="openCM">
<el-tree
v-loading="loading"
node-key="id"
@ -294,7 +294,7 @@ export default defineComponent({
}
//
function openCM(e: any, d: any, n: any) {
function openCM(e: any, d?: any, n?: any) {
if (!d) {
d = list.value[0] || {};
}

View File

@ -31,7 +31,7 @@ export default defineComponent({
emits: ["update:modelValue", "load"],
setup(props, { emit }) {
const { refs, setRefs } = useRefs();
const { refs, setRefs }: any = useRefs();
let quill: any = null;

View File

@ -12,11 +12,15 @@
class="app-process__item"
:class="{ active: item.active }"
:data-index="index"
@click="onTap(item)"
@click="onTap(item, Number(index))"
@contextmenu.stop.prevent="openCM($event, item)"
>
<span>{{ item.label }}</span>
<i v-if="index > 0" class="el-icon-close" @mousedown.stop="onDel(index)"></i>
<i
v-if="index > 0"
class="el-icon-close"
@mousedown.stop="onDel(Number(index))"
></i>
</div>
</div>
@ -41,7 +45,7 @@ export default {
const router = useRouter();
const route = useRoute();
const store = useStore();
const { refs, setRefs } = useRefs();
const { refs, setRefs }: any = useRefs();
//
const menu = reactive<any>({

View File

@ -113,7 +113,7 @@ const mutations = {
// 设置视图路由
SET_VIEW_ROUTES(state: any, list: MenuItem[]) {
router.$plugin.addViews(list);
router.$plugin?.addViews(list);
state.routes = list;
storage.set("viewRoutes", list);

View File

@ -49,7 +49,7 @@ export default defineComponent({
setup() {
const $service = inject<any>("service");
const { refs, setRefs } = useRefs();
const { refs, setRefs }: any = useRefs();
//
const day = ref<number>(1);
@ -148,6 +148,7 @@ export default defineComponent({
});
return {
$service,
refs,
day,
table,

View File

@ -477,7 +477,7 @@ export default defineComponent({
}
//
async function toMove(e: any) {
async function toMove(e?: any) {
let ids = [];
if (!e) {
@ -490,6 +490,7 @@ export default defineComponent({
}
return {
$service,
refs,
isExpand,
selects,

View File

@ -3,49 +3,21 @@
<!-- 工具栏 -->
<div class="cl-chat-input__opbar">
<ul>
<!-- 表情 -->
<li>
<!-- 表情 -->
<emoji @select="onEmojiSelect" />
</li>
<!-- 图片上传 -->
<li>
<cl-upload
accept="image/*"
list-type
:before-upload="
(file) => {
onBeforeUpload(file, 'image');
}
"
:on-progress="onUploadProgress"
:on-success="
(res, file) => {
onUploadSuccess(res, file, 'image');
}
"
>
<!-- 图片上传 -->
<upload name="image" accept="image/*" @before-upload="append" @success="send">
<img src="../static/images/image.png" alt="" />
</cl-upload>
</upload>
</li>
<!-- 视频上传 -->
<li>
<cl-upload
accept="video/*"
list-type
:before-upload="
(file) => {
onBeforeUpload(file, 'video');
}
"
:on-progress="onUploadProgress"
:on-success="
(res, file) => {
onUploadSuccess(res, file, 'video');
}
"
>
<!-- 视频上传 -->
<upload name="video" accept="video/*" @before-upload="append" @success="send">
<img src="../static/images/video.png" alt="" />
</cl-upload>
</upload>
</li>
</ul>
</div>
@ -72,10 +44,12 @@
import { defineComponent, inject, nextTick, reactive, ref } from "vue";
import { useStore } from "vuex";
import Emoji from "./emoji.vue";
import Upload from "./upload.vue";
export default defineComponent({
components: {
Emoji
Emoji,
Upload
},
setup() {
@ -121,86 +95,6 @@ export default defineComponent({
}
}
//
function onBeforeUpload(file: any, key: string) {
//
function next(options = {}) {
const data = {
content: {
[`${key}Url`]: ""
},
type: 0,
uid: file.uid,
loading: true,
progress: "0%",
contentType: chat.modes.indexOf(key),
...options
};
append(data);
}
//
if (key == "image") {
const fileReader = new FileReader();
fileReader.onload = (e: any) => {
const imageUrl = e.target.result;
const image = new Image();
image.onload = () => {
let height = 0;
let width = 0;
if (image.width > 200) {
width = 200;
height = (image.height * 200) / image.width;
}
next({
content: {
imageUrl
},
style: {
height: height + "px",
width: width + "px"
}
});
};
image.src = imageUrl;
};
fileReader.readAsDataURL(file);
} else {
next();
}
}
//
function onUploadProgress(e: any, file: any) {
store.commit("UPDATE_MESSAGE", {
file,
data: {
progress: e.percent + "%"
}
});
}
//
function onUploadSuccess(res: any, file: any, key: string) {
store.commit("UPDATE_MESSAGE", {
file,
data: {
loading: false,
content: {
[`${key}Url`]: res.data
}
},
callback: send
});
}
//
function onTextSend() {
if (text.value) {
@ -269,9 +163,7 @@ export default defineComponent({
text,
emoji,
send,
onBeforeUpload,
onUploadProgress,
onUploadSuccess,
append,
onTextSend,
onImageSelect,
onEmojiSelect,

View File

@ -29,7 +29,7 @@
'is-active': session ? item.id == session.id : false
}"
@click="toDetail(item)"
@contextmenu.stop.prevent="openCM($event, item.id, index)"
@contextmenu.stop.prevent="openCM($event, item.id, Number(index))"
>
<!-- 头像 -->
<div class="avatar">

View File

@ -0,0 +1,119 @@
<template>
<cl-upload
:accept="accept"
list-type
:before-upload="onBeforeUpload"
:on-progress="onUploadProgress"
:on-success="onUploadSuccess"
>
<slot></slot>
</cl-upload>
</template>
<script lang="ts">
import { ElFile } from "element-plus/lib/el-upload/src/upload.type";
import { defineComponent, inject } from "vue";
import { useStore } from "vuex";
export default defineComponent({
props: {
name: String,
accept: String
},
emits: ["before-upload", "success"],
setup(props, { emit }) {
const store = useStore();
const chat = inject<any>("chat");
//
function onBeforeUpload(file: ElFile) {
//
function next(options = {}) {
const data = {
content: {
[`${props.name}Url`]: ""
},
type: 0,
uid: file.uid,
loading: true,
progress: "0%",
contentType: chat.modes.indexOf(props.name),
...options
};
emit("before-upload", data);
}
//
if (props.name == "image") {
const fileReader = new FileReader();
fileReader.onload = (e: any) => {
const imageUrl = e.target.result;
const image = new Image();
image.onload = () => {
let height = 0;
let width = 0;
if (image.width > 200) {
width = 200;
height = (image.height * 200) / image.width;
}
next({
content: {
imageUrl
},
style: {
height: height + "px",
width: width + "px"
}
});
};
image.src = imageUrl;
};
fileReader.readAsDataURL(file);
} else {
next();
}
}
//
function onUploadProgress(e: any, file: ElFile) {
store.commit("UPDATE_MESSAGE", {
file,
data: {
progress: e.percent + "%"
}
});
}
//
function onUploadSuccess(res: any, file: ElFile) {
store.commit("UPDATE_MESSAGE", {
file,
data: {
loading: false,
content: {
[`${props.name}Url`]: res.data
}
},
callback: (data: any) => {
emit("success", data);
}
});
}
return {
onBeforeUpload,
onUploadProgress,
onUploadSuccess
};
}
});
</script>

View File

@ -42,7 +42,7 @@
item-key="id"
:data-type="item.params.type"
:data-status="item.params.status"
@end="(e) => onDragEnd(e, item)"
@end="onDragEnd"
>
<template #item="{ element }">
<li
@ -125,7 +125,7 @@
class="more"
type="text"
size="mini"
@click="moreTask(index, item)"
@click="moreTask(index)"
>查看更多</el-button
>
</div>
@ -182,7 +182,9 @@
@click="expandLog(item)"
>
<div class="h">
<span class="name">{{ index + 1 }} · {{ item.taskName }}</span>
<span class="name"
>{{ Number(index) + 1 }} · {{ item.taskName }}</span
>
</div>
<div class="remark" :class="{ _ellipsis: !item._expand }">

View File

@ -145,7 +145,19 @@ export default {
}
],
isDev,
form: {}
form: {
name: "",
conf: {
showAMenu: false,
showRouteNav: true,
showProcess: true,
customMenu: false
},
theme: {
color: "",
url: ""
}
}
};
},

View File

@ -202,7 +202,7 @@ export default {
loading: false,
preview: {
visible: false,
url: null
url: ""
}
};
},

View File

@ -28,76 +28,81 @@
</ul>
</div>
<cl-form ref="form" />
<cl-form :ref="setRefs('form')" />
</div>
</template>
<script>
import { mapGetters } from "vuex";
<script lang="ts">
import { ElMessage, ElMessageBox } from "element-plus";
import { computed, defineComponent, inject, ref, watch } from "vue";
import { useStore } from "vuex";
import { isEmpty } from "/@/core/utils";
import { ContextMenu } from "/@/crud";
import { useRefs } from "/@/crud/hooks/core";
export default {
export default defineComponent({
name: "cl-upload-space-category",
inject: ["space"],
props: {
modelValue: [Number]
modelValue: [Number, String]
},
emits: ["update:modelValue", "change"],
data() {
return {
list: [],
current: undefined,
keyword: ""
};
},
setup(_, { emit }) {
const store = useStore();
const { refs, setRefs }: any = useRefs();
const $service: any = inject("service");
const space = inject<any>("space");
computed: {
...mapGetters(["browser"]),
//
const list = ref<any[]>([]);
flist() {
return this.list.filter((e) => e.name.includes(this.keyword));
}
},
//
const current = ref<number | string>("");
watch: {
current: {
handler(id) {
this.$emit("update:modelValue", id);
this.$emit("change", id);
//
const keyword = ref<string>("");
//
const flist = computed(() => {
return list.value.filter((e: any) => e.name.includes(keyword.value));
});
//
const browser = computed(() => store.getters.browser);
//
watch(
() => current.value,
(id: number | string) => {
console.log(id);
emit("update:modelValue", id);
emit("change", id);
}
}
},
);
created() {
this.refresh();
},
methods: {
//
refresh() {
return this.$service.space.type.list().then((res) => {
function refresh() {
return $service.space.type.list().then((res: any) => {
res.unshift({
name: "全部文件",
id: null
});
this.list = res;
list.value = res;
if (!isEmpty(res)) {
if (!this.current) {
this.current = res[0].id;
if (!current.value) {
current.value = res[0].id;
}
}
});
},
}
//
edit(item = {}) {
this.$refs.form.open({
function edit(item: any = {}) {
refs.value.form.open({
title: "添加分类",
width: "400px",
items: [
@ -118,87 +123,91 @@ export default {
}
],
on: {
submit: (data, { done, close }) => {
submit: (data: any, { done, close }: any) => {
let next = null;
if (!item.id) {
next = this.$service.space.type.add(data);
next = $service.space.type.add(data);
} else {
next = this.$service.space.type.update({
next = $service.space.type.update({
...data,
id: item.id
});
}
next.then(() => {
this.refresh();
refresh();
close();
}).catch((err) => {
this.$message.error(err);
}).catch((err: string) => {
ElMessage.error(err);
done();
});
}
}
});
},
}
//
select(id) {
this.current = id;
function select(id: number) {
current.value = id;
//
if (this.browser.isMini) {
this.space.category.visible = false;
if (browser.value.isMini) {
space.category.visible = false;
}
},
}
//
openContextMenu(e, { id, name }) {
function openContextMenu(e: any, { id, name }: any) {
if (!id) {
return false;
}
this.$crud.openContextMenu(e, {
ContextMenu.open(e, {
list: [
{
label: "刷新",
"suffix-icon": "el-icon-edit",
callback: (_, done) => {
this.refresh();
callback: (_: any, done: Function) => {
refresh();
done();
}
},
{
label: "编辑",
"suffix-icon": "el-icon-edit",
callback: (_, done) => {
this.edit({ id, name });
callback: (_: any, done: Function) => {
edit({ id, name });
done();
}
},
{
label: "删除",
"suffix-icon": "el-icon-delete",
callback: (_, done) => {
this.$confirm(`此操作将删除【${name}】下的文件, 是否继续?`, "提示", {
type: "warning"
})
callback: (_: any, done: Function) => {
ElMessageBox.confirm(
`此操作将删除【${name}】下的文件, 是否继续?`,
"提示",
{
type: "warning"
}
)
.then(() => {
this.$service.space.type
$service.space.type
.delete({
ids: [id]
})
.then(() => {
this.$message.success("删除成功");
ElMessage.success("删除成功");
if (id == this.current) {
this.current = null;
if (id == current.value) {
current.value = 0;
}
this.refresh();
refresh();
})
.catch((err) => {
this.$message.error(err);
.catch((err: string) => {
ElMessage.error(err);
});
})
.catch(() => null);
@ -209,8 +218,25 @@ export default {
]
});
}
refresh();
return {
refs,
setRefs,
browser,
space,
list,
flist,
current,
keyword,
refresh,
edit,
select,
openContextMenu
};
}
};
});
</script>
<style lang="scss" scoped>

View File

@ -6,32 +6,32 @@
@contextmenu.stop.prevent="openContextMenu"
>
<!-- 错误 -->
<template v-if="value.error">
<div class="cl-upload-space-item__error">上传失败{{ value.error }}</div>
<template v-if="info.error">
<div class="cl-upload-space-item__error">上传失败{{ info.error }}</div>
</template>
<!-- 成功 -->
<template v-else>
<!-- 图片 -->
<template v-if="type === 'image'">
<el-image fit="cover" :src="value.url" lazy />
<el-image fit="cover" :src="info.url" lazy />
</template>
<!-- 视频 -->
<template v-else-if="type === 'video'">
<video
controls
:src="value.url"
:src="info.url"
:style="{
'max-height': '100%',
'max-width': '100%'
maxHeight: '100%',
maxWidth: '100%'
}"
></video>
</template>
<!-- 其他 -->
<template v-else>
<span>{{ value.url }}</span>
<span>{{ info.url }}</span>
</template>
</template>
@ -45,65 +45,86 @@
</div>
</template>
<script>
export default {
<script lang="ts">
import { computed, defineComponent, inject } from "vue";
import { ContextMenu } from "/@/crud";
export default defineComponent({
name: "cl-upload-space-item",
inject: ["space"],
props: {
value: Object
modelValue: {
type: Object,
default: () => {
return {};
}
}
},
emits: ["select", "remove"],
computed: {
index() {
return this.space.selection.findIndex((e) => e.id === this.value.id);
},
setup(props, { emit }) {
const space = inject<any>("space");
isSelected() {
return this.index >= 0;
},
//
const info = computed(() => props.modelValue);
type() {
return (this.value.type || "").split("/")[0];
//
const index = computed(() =>
space.selection.value.findIndex((e: any) => e.id === info.value.id)
);
//
const isSelected = computed(() => index.value >= 0);
//
const type = computed(() => (info.value.type || "").split("/")[0]);
//
function select() {
emit("select", info.value);
}
},
methods: {
select() {
this.$emit("select", this.value);
},
//
function remove() {
emit("remove", info.value);
}
remove() {
this.$emit("remove", this.value);
},
openContextMenu(e) {
this.$crud.openContextMenu(e, {
//
function openContextMenu(e: any) {
ContextMenu.open(e, {
list: [
{
label: this.isSelected ? "取消选中" : "选中",
"suffix-icon": this.isSelected ? "el-icon-close" : "el-icon-check",
callback: (_, done) => {
this.select();
label: isSelected.value ? "取消选中" : "选中",
"suffix-icon": isSelected.value ? "el-icon-close" : "el-icon-check",
callback: (_: any, done: Function) => {
select();
done();
}
},
{
label: "删除",
"suffix-icon": "el-icon-delete",
callback: (_, done) => {
this.remove();
callback: (_: any, done: Function) => {
remove();
done();
}
}
]
});
}
return {
info,
index,
type,
isSelected,
select,
remove,
openContextMenu
};
}
};
});
</script>
<style lang="scss" scoped>

View File

@ -116,11 +116,7 @@
:page-size="pagination.size"
:current-page="pagination.page"
:total="pagination.total"
@current-change="
(page) => {
refresh({ page });
}
"
@current-change="onCurrentChange"
/>
</div>
</div>
@ -141,13 +137,16 @@
</div>
</template>
<script>
<script lang="ts">
import { computed, defineComponent, inject, provide, reactive, ref, watch } from "vue";
import { useStore } from "vuex";
import { ElMessage, ElMessageBox } from "element-plus";
import { ElFile } from "element-plus/lib/el-upload/src/upload.type";
import { isEmpty } from "/@/core/utils";
import Category from "./category.vue";
import FileItem from "./file-item.vue";
import { mapGetters } from "vuex";
export default {
export default defineComponent({
name: "cl-upload-space",
components: {
@ -155,13 +154,9 @@ export default {
FileItem
},
provide() {
return {
space: this
};
},
props: {
//
modelValue: String,
//
action: String,
//
@ -195,199 +190,243 @@ export default {
emits: ["update:modelValue", "confirm"],
data() {
return {
visible: false,
loading: false,
category: {
id: null,
visible: true
setup(props, { emit }) {
const store = useStore();
const $service = inject<any>("service");
//
const visible = ref<boolean>(false);
//
const loading = ref<boolean>(false);
//
const selection = ref<any[]>([]);
//
const list = ref<any[]>([]);
//
const category = reactive<any>({
id: "",
visible: true
});
//
const pagination = reactive<any>({
page: 1,
size: 12,
total: 0
});
//
const browser = computed(() => store.getters.browser);
//
watch(
() => browser.value.isMini,
(val) => {
category.visible = val ? false : true;
},
selection: [],
list: [],
pagination: {
page: 1,
size: 12,
total: 0
{
immediate: true
}
};
},
);
computed: {
...mapGetters(["browser"]),
//
const limitTip = computed(() => selection.value.length + "/" + props.limit);
limitTip() {
return this.selection.length + "/" + this.limit;
},
//
const isSelected = computed(() => !isEmpty(selection.value));
isSelected() {
return !isEmpty(this.selection);
// Provide
provide("space", {
category,
selection
});
//
function open() {
visible.value = true;
}
},
watch: {
"browser.isMini": {
immediate: true,
handler(val) {
this.category.visible = val ? false : true;
}
//
function clear() {
selection.value = [];
}
},
methods: {
open() {
this.visible = true;
},
close() {
this.visible = false;
this.clear();
},
clear() {
this.selection = [];
},
//
function close() {
visible.value = false;
clear();
}
//
onSuccess(res, file) {
const item = this.list.find((e) => file.uid == e.uid);
function onSuccess(res: any, file: ElFile) {
const item = list.value.find((e: any) => file.uid == e.uid);
if (item) {
item.url = res.data;
this.$service.space.info
$service.space.info
.add({
url: res.data,
type: item.type,
classifyId: item.classifyId
})
.then((res) => {
.then((res: any) => {
item.loading = false;
item.id = res.id;
})
.catch((err) => {
this.$message.error(err);
.catch((err: string) => {
ElMessage.error(err);
});
}
},
}
//
onError(err, file) {
const item = this.list.find((e) => file.uid == e.uid);
function onError(err: string, file: ElFile) {
const item = list.value.find((e) => file.uid == e.uid);
if (item) {
item.loading = false;
this.$set(item, "error", err);
item.error = err;
}
},
}
//
beforeUpload({ tempFilePath, type, uid }) {
this.list.unshift({
function beforeUpload({ tempFilePath, type, uid }: any) {
list.value.unshift({
url: tempFilePath,
type,
uid,
classifyId: this.category.id,
classifyId: category.id,
loading: true,
progress: "0%"
});
},
}
//
onProgress({ percent }, file) {
const item = this.list.find(({ uid }) => uid == file.uid);
function onProgress({ percent }: any, file: ElFile) {
const item = list.value.find(({ uid }: any) => uid == file.uid);
if (item) {
item.progress = percent + "%";
}
},
}
//
refresh(params) {
function refresh(params: any = {}) {
//
this.clear();
clear();
this.loading = true;
loading.value = true;
this.$service.space.info
$service.space.info
.page({
...this.pagination,
...pagination,
...params,
classifyId: this.category.id,
type: this.accept
classifyId: category.id,
type: props.accept
})
.then((res) => {
this.pagination = res.pagination;
.then((res: any) => {
Object.assign(pagination, res.pagination);
this.list = res.list.map((e) => {
e.loading = false;
return e;
list.value = res.list.map((e: any) => {
return {
...e,
loading: false
};
});
})
.done(() => {
this.loading = false;
loading.value = false;
});
},
}
//
confirm() {
const urls = this.selection.map((e) => e.url).join(",");
function confirm() {
const urls = selection.value.map((e: any) => e.url).join(",");
this.$emit("update:modelValue", urls);
this.$emit("confirm", this.detailData ? this.selection : urls);
emit("update:modelValue", urls);
emit("confirm", props.detailData ? selection.value : urls);
this.close();
},
close();
}
//
select(item) {
const index = this.selection.findIndex((e) => e.id === item.id);
function select(item: any) {
const index = selection.value.findIndex((e: any) => e.id === item.id);
if (index >= 0) {
this.selection.splice(index, 1);
selection.value.splice(index, 1);
} else {
if (this.selection.length < this.limit) {
this.selection.push(item);
if (selection.value.length < props.limit) {
selection.value.push(item);
}
}
},
}
//
remove(...selection) {
if (isEmpty(selection)) {
selection = this.selection;
}
function remove(item: any) {
// id
const ids = selection.map((e) => e.id);
const ids: number[] = item ? [item.id] : selection.value.map((e: any) => e.id);
this.$confirm("此操作将删除文件, 是否继续?", "提示", {
ElMessageBox.confirm("此操作将删除文件, 是否继续?", "提示", {
type: "warning"
})
.then(() => {
this.$message.success("删除成功");
ElMessage.success("删除成功");
//
ids.forEach((id) => {
[this.list, this.selection].forEach((list) => {
const index = list.findIndex((e) => e.id === id);
[list.value, selection.value].forEach((list) => {
const index = list.findIndex((e: any) => e.id === id);
list.splice(index, 1);
});
});
//
this.$service.space.info
$service.space.info
.delete({
ids
})
.catch((err) => {
this.$message.error(err);
.catch((err: string) => {
ElMessage.error(err);
});
})
.catch(() => null);
}
//
function onCurrentChange(page: number) {
refresh({ page });
}
return {
visible,
loading,
selection,
list,
category,
pagination,
browser,
limitTip,
isSelected,
open,
close,
refresh,
remove,
confirm,
select,
onSuccess,
onError,
beforeUpload,
onProgress,
onCurrentChange
};
}
};
});
</script>
<style lang="scss">

View File

@ -1,13 +1,13 @@
import { onBeforeUpdate, ref } from "vue";
export function useRefs() {
const refs = ref<HTMLElement[]>([]);
const refs: any = ref<any[]>([]);
onBeforeUpdate(() => {
refs.value = [];
});
const setRefs = (index: number) => (el: HTMLElement) => {
const setRefs = (index: string) => (el: any) => {
refs.value[index] = el;
};

View File

@ -10,6 +10,6 @@ async function bootstrap(app: any) {
SET_SERVICE(app);
SET_MODULE(app);
router.$plugin.addViews(store.getters.routes);
router.$plugin?.addViews(store.getters.routes);
}
export { Service, Permission, BaseService, bootstrap, useRefs };

View File

@ -18,22 +18,14 @@ export default function (app: any) {
if (!error) {
local.push({
name,
value: files[i].default,
value: files[i].default
});
}
}
// 安装模块
function install(mod: any) {
const {
store: _store,
components,
service,
directives,
pages,
views,
name,
} = mod;
const { store: _store, components, service, directives, pages, views, name } = mod;
try {
// 注册vuex模块
@ -82,7 +74,7 @@ export default function (app: any) {
}
if (e.path) {
router.$plugin.addViews([e]);
router.$plugin?.addViews([e]);
} else {
console.error(`[${name}-views]:缺少 path 参数`);
}
@ -104,7 +96,7 @@ export default function (app: any) {
// Parse
if (isString(e)) {
mod = {
name: e,
name: e
};
} else if (isObject(e)) {
mod = e;
@ -112,7 +104,7 @@ export default function (app: any) {
mod = {
name: e[0],
value: e[1],
options: e[2],
options: e[2]
};
} else {
console.error(e, "格式错误");
@ -144,7 +136,7 @@ export default function (app: any) {
mod = {
name: mod.name,
options: mod.options || {},
...mod.value,
...mod.value
};
modules.push(mod);

12
src/core/types/index.d.ts vendored Normal file
View File

@ -0,0 +1,12 @@
import { Store } from "vuex";
import { Router } from "vue-router";
export declare class CoolStore<S> extends Store<S> {
$service?: any;
}
export declare interface CoolRouter extends Router {
$plugin?: {
addViews(list: any[], options?: any): void;
};
}

View File

@ -208,7 +208,7 @@ export function getBrowser() {
}
export function href(path: string, newWindow?: boolean) {
const { search, origin, pathname } = window.location;
const { origin, pathname } = window.location;
if (pathname == path) {
return false;
@ -219,7 +219,7 @@ export function href(path: string, newWindow?: boolean) {
if (routerMode == "history") {
url = origin + import.meta.env.BASE_URL + path.substr(1);
} else {
url = origin + search + "#" + path;
url = origin + import.meta.env.BASE_URL + "#" + path;
}
if (newWindow) {
@ -237,9 +237,9 @@ export function deepTree(list: Array<any>) {
const newList: Array<any> = [];
const map: any = {};
list.forEach(e => (map[e.id] = e));
list.forEach((e) => (map[e.id] = e));
list.forEach(e => {
list.forEach((e) => {
const parent = map[e.parentId];
if (parent) {
@ -250,7 +250,7 @@ export function deepTree(list: Array<any>) {
});
const fn = (list: Array<any>) => {
list.map(e => {
list.map((e) => {
if (e.children instanceof Array) {
e.children = orderBy(e.children, "orderNum");
@ -269,7 +269,7 @@ export function revDeepTree(list: Array<any> = []) {
let id = 0;
const deep = (list: Array<any>, parentId: any) => {
list.forEach(e => {
list.forEach((e) => {
if (!e.id) {
e.id = id++;
}

View File

@ -12,7 +12,7 @@ const clearReturn = /(\r)|(\n)/g;
function findSvgFile(dir: string): string[] {
const svgRes = [];
const dirents = readdirSync(dir, {
withFileTypes: true,
withFileTypes: true
});
for (const dirent of dirents) {
if (dirent.isDirectory()) {
@ -21,10 +21,10 @@ function findSvgFile(dir: string): string[] {
const svg = readFileSync(dir + dirent.name)
.toString()
.replace(clearReturn, "")
.replace(svgTitle, (_, $2) => {
.replace(svgTitle, (_: any, $2: any) => {
let width = 0;
let height = 0;
let content = $2.replace(clearHeightWidth, (s1, s2, s3) => {
let content = $2.replace(clearHeightWidth, (_: any, s2: any, s3: any) => {
if (s2 === "width") {
width = s3;
} else if (s2 === "height") {
@ -47,7 +47,7 @@ function findSvgFile(dir: string): string[] {
return svgRes;
}
export const svgBuilder = (path: string, perfix = "icon"): Plugin => {
export const svgBuilder = (path: string, perfix = "icon"): Plugin | null => {
if (path !== "") {
idPerfix = perfix;
const res = findSvgFile(path);
@ -63,7 +63,9 @@ export const svgBuilder = (path: string, perfix = "icon"): Plugin => {
</svg>
`
);
},
}
};
} else {
return null;
}
};

View File

@ -1,3 +1,4 @@
// @ts-nocheck
Promise.prototype.done = function (cb: Function) {
const P: any = this.constructor;

View File

@ -5,7 +5,7 @@ import { deepMerge, isBoolean, isEmpty, isFunction, isObject, isString } from ".
import Parse from "../../utils/parse";
import { renderNode } from "../../utils/vnode";
import { useAction } from "./helper";
import { Browser } from "@/crud/types";
import { Browser } from "../../types";
export default defineComponent({
name: "cl-form",

View File

@ -34,7 +34,7 @@
<el-dropdown trigger="click" :hide-on-click="false" @command="onCommand">
<span v-if="userInfo" class="el-dropdown-link">
<span class="name">{{ userInfo.nickName }}</span>
<img class="avatar" :src="userInfo.headImg" alt />
<img class="avatar" :src="userInfo.headImg" />
</span>
<template #dropdown>

View File

@ -1,4 +1,5 @@
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
import { CoolRouter } from "/@/core/types";
// 忽略规则
const ignore: any = {
@ -28,7 +29,7 @@ const routes: Array<RouteRecordRaw> = [
const router = createRouter({
history: createWebHistory(),
routes
});
}) as CoolRouter;
export default router;
export { ignore };

View File

@ -1,7 +1,8 @@
import { createStore } from "vuex";
import { CoolStore } from "/@/core/types";
const store = createStore({
strict: true
});
}) as CoolStore<any>;
export default store;

View File

@ -7,6 +7,7 @@
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"experimentalDecorators": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"types": ["vite/client", "vite-svg-loader"],
@ -15,5 +16,6 @@
"/#/*": ["./types/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"exclude": ["node_modules", "dist"]
}

View File

@ -1,5 +1,5 @@
Arguments:
D:\node\node.exe C:\Users\Administrator\AppData\Roaming\npm\node_modules\yarn\bin\yarn.js add eslint-config-prettier -D
D:\node\node.exe C:\Users\Administrator\AppData\Roaming\npm\node_modules\yarn\bin\yarn.js remove @types/node
PATH:
C:\Program Files (x86)\Common Files\Intel\Shared Libraries\redist\intel64\compiler;C:\windows\system32;C:\windows;C:\windows\System32\Wbem;C:\windows\System32\WindowsPowerShell\v1.0\;C:\windows\System32\OpenSSH\;D:\Tortoise\bin;C:\Program Files\Git\cmd;C:\Program Files\python;C:\Program Files\python\Scripts;;D:\BtSoft\panel\script;D:\node\;C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps;;D:\cool\Microsoft VS Code\bin;C:\Users\Administrator\AppData\Roaming\npm
@ -14,29 +14,18 @@ Platform:
win32 x64
Trace:
Error: https://registry.yarnpkg.com/eslint-config-prettier%20-D: Not found
at Request.params.callback [as _callback] (C:\Users\Administrator\AppData\Roaming\npm\node_modules\yarn\lib\cli.js:66988:18)
at Request.self.callback (C:\Users\Administrator\AppData\Roaming\npm\node_modules\yarn\lib\cli.js:140662:22)
at Request.emit (events.js:315:20)
at Request.<anonymous> (C:\Users\Administrator\AppData\Roaming\npm\node_modules\yarn\lib\cli.js:141634:10)
at Request.emit (events.js:315:20)
at IncomingMessage.<anonymous> (C:\Users\Administrator\AppData\Roaming\npm\node_modules\yarn\lib\cli.js:141556:12)
at Object.onceWrapper (events.js:421:28)
at IncomingMessage.emit (events.js:327:22)
at endReadableNT (internal/streams/readable.js:1327:12)
at processTicksAndRejections (internal/process/task_queues.js:80:21)
Error: EPERM: operation not permitted, copyfile 'C:\Users\Administrator\AppData\Local\Yarn\Cache\v6\npm-yallist-2.1.2-1c11f9218f076089a47dd512f93c6699a6a81d52-integrity\node_modules\yallist\README.md' -> 'D:\cool\srcs\admin\front-next\node_modules\editorconfig\node_modules\yallist\README.md'
npm manifest:
{
"name": "front-next",
"version": "0.0.1",
"version": "0.1.0",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"build": "vue-tsc --noEmit --skipLibCheck && vite build",
"serve": "vite preview",
"lint": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
"lint:eslint": "eslint \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
"lint:ls": "ls-lint"
"lint:prettier": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
"lint:eslint": "eslint \"{src,mock}/**/*.{vue,ts,tsx}\" --fix"
},
"dependencies": {
"array.prototype.flat": "^1.2.4",
@ -70,6 +59,8 @@ npm manifest:
"@vitejs/plugin-vue-jsx": "^1.1.2",
"@vue/compiler-sfc": "^3.0.5",
"eslint": "^7.23.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-vue": "^7.8.0",
"prettier": "^2.2.1",
"sass": "^1.32.8",
@ -387,6 +378,11 @@ Lockfile:
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==
"@types/node@^14.14.37":
version "14.14.37"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.37.tgz#a3dd8da4eb84a996c36e331df98d82abd76b516e"
integrity sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw==
"@typescript-eslint/eslint-plugin@^4.20.0":
version "4.20.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.20.0.tgz#9d8794bd99aad9153092ad13c96164e3082e9a92"
@ -1338,6 +1334,18 @@ Lockfile:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
eslint-config-prettier@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.1.0.tgz#4ef1eaf97afe5176e6a75ddfb57c335121abc5a6"
integrity sha512-oKMhGv3ihGbCIimCAjqkdzx2Q+jthoqnXSP+d86M9tptwugycmTFdVR4IpLgq2c4SHifbwO90z2fQ8/Aio73yw==
eslint-plugin-prettier@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz#7079cfa2497078905011e6f82e8dd8453d1371b7"
integrity sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==
dependencies:
prettier-linter-helpers "^1.0.0"
eslint-plugin-vue@^7.8.0:
version "7.8.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-7.8.0.tgz#cb0e85d65b65fa8d15e783fbb03c049d2c4cfdae"
@ -1535,6 +1543,11 @@ Lockfile:
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154"
integrity sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==
fast-diff@^1.1.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
fast-glob@^3.1.1:
version "3.2.5"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661"
@ -2719,6 +2732,13 @@ Lockfile:
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
prettier-linter-helpers@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
dependencies:
fast-diff "^1.1.2"
prettier@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5"

View File

@ -299,6 +299,16 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad"
integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==
"@types/lodash@^4.14.168":
version "4.14.168"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.168.tgz#fe24632e79b7ade3f132891afff86caa5e5ce008"
integrity sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==
"@types/node@^14.14.37":
version "14.14.37"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.37.tgz#a3dd8da4eb84a996c36e331df98d82abd76b516e"
integrity sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw==
"@typescript-eslint/eslint-plugin@^4.20.0":
version "4.20.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.20.0.tgz#9d8794bd99aad9153092ad13c96164e3082e9a92"