mirror of
https://github.com/cool-team-official/cool-admin-vue.git
synced 2024-11-01 14:10:27 +08:00
优化
This commit is contained in:
parent
2ef563c069
commit
42b406e028
@ -65,19 +65,21 @@ async function getData(temps?: Eps.Entity[]) {
|
|||||||
|
|
||||||
// 创建 json 文件
|
// 创建 json 文件
|
||||||
function createJson() {
|
function createJson() {
|
||||||
const d = list.map((e) => {
|
const d = list
|
||||||
return {
|
.filter((e) => !e.isLocal) // 过滤本地的 service 数据
|
||||||
prefix: e.prefix,
|
.map((e) => {
|
||||||
name: e.name || "",
|
return {
|
||||||
api: e.api.map((e) => {
|
prefix: e.prefix,
|
||||||
return {
|
name: e.name || "",
|
||||||
name: e.name,
|
api: e.api.map((e) => {
|
||||||
method: e.method,
|
return {
|
||||||
path: e.path
|
name: e.name,
|
||||||
};
|
method: e.method,
|
||||||
})
|
path: e.path
|
||||||
};
|
};
|
||||||
});
|
})
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
createWriteStream(join(DistPath, "eps.json"), {
|
createWriteStream(join(DistPath, "eps.json"), {
|
||||||
flags: "w"
|
flags: "w"
|
||||||
|
1
build/cool/types/index.d.ts
vendored
1
build/cool/types/index.d.ts
vendored
@ -28,5 +28,6 @@ export namespace Eps {
|
|||||||
module: string;
|
module: string;
|
||||||
name: string;
|
name: string;
|
||||||
prefix: string;
|
prefix: string;
|
||||||
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
@ -22,7 +22,7 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
|
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB",
|
||||||
"Microsoft YaHei", Arial, sans-serif;
|
"Microsoft YaHei", "微软雅黑", Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preload__wrap {
|
.preload__wrap {
|
||||||
@ -93,8 +93,7 @@
|
|||||||
border: 7px solid currentColor;
|
border: 7px solid currentColor;
|
||||||
border-bottom-color: #2f3447 !important;
|
border-bottom-color: #2f3447 !important;
|
||||||
position: relative;
|
position: relative;
|
||||||
animation:
|
animation: r 1s infinite cubic-bezier(0.17, 0.67, 0.83, 0.67),
|
||||||
r 1s infinite cubic-bezier(0.17, 0.67, 0.83, 0.67),
|
|
||||||
bc 2s infinite ease-in;
|
bc 2s infinite ease-in;
|
||||||
transform: rotate(0deg);
|
transform: rotate(0deg);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
export const proxy = {
|
export const proxy = {
|
||||||
"/dev/": {
|
"/dev/": {
|
||||||
target: "http://127.0.0.1:8001",
|
// target: "http://127.0.0.1:8001",
|
||||||
|
target: "https://test-admin.cool-js.cloud",
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (path: string) => path.replace(/^\/dev/, "")
|
rewrite: (path: string) => path.replace(/^\/dev/, "")
|
||||||
},
|
},
|
||||||
|
@ -1,30 +1,85 @@
|
|||||||
import { merge } from "lodash-es";
|
import { merge } from "lodash-es";
|
||||||
import { service } from "../service";
|
import { BaseService, service } from "../service";
|
||||||
import { Module } from "../types";
|
import { Module } from "../types";
|
||||||
import { path2Obj } from "../utils";
|
import { path2Obj } from "../utils";
|
||||||
import { config, isDev } from "/@/config";
|
import { config, isDev } from "/@/config";
|
||||||
|
import { eps } from "virtual:eps";
|
||||||
|
|
||||||
export function createEps(modules: Module[]) {
|
export function createEps(modules: Module[]) {
|
||||||
// 本地模块的数据
|
// 更新数据
|
||||||
const s = path2Obj(
|
function update() {
|
||||||
modules.reduce((a, b) => {
|
// 设置 request 方法
|
||||||
return a.concat(...((b.services as any[]) || []));
|
function set(d: any) {
|
||||||
}, [])
|
if (d.namespace) {
|
||||||
);
|
const a = new BaseService(d.namespace);
|
||||||
|
|
||||||
// 合并数据
|
for (const i in d) {
|
||||||
merge(service, s);
|
const { path, method = "get" } = d[i];
|
||||||
|
|
||||||
// 开发环境下,生成本地 service 的类型文件
|
if (path) {
|
||||||
|
a.request = a.request;
|
||||||
|
|
||||||
|
a[i] = function (data?: any) {
|
||||||
|
return this.request({
|
||||||
|
url: path,
|
||||||
|
method,
|
||||||
|
[method.toLocaleLowerCase() == "post" ? "data" : "params"]: data
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const i in a) {
|
||||||
|
d[i] = a[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const i in d) {
|
||||||
|
set(d[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 遍历每一个方法
|
||||||
|
set(eps.service);
|
||||||
|
|
||||||
|
// 合并[eps]
|
||||||
|
merge(service, eps.service);
|
||||||
|
|
||||||
|
// 合并[local]
|
||||||
|
merge(
|
||||||
|
service,
|
||||||
|
path2Obj(
|
||||||
|
modules.reduce((a, b) => {
|
||||||
|
return a.concat(...((b.services as any[]) || []));
|
||||||
|
}, [])
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 提示
|
||||||
|
if (isDev) {
|
||||||
|
console.log("[eps] update", service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update();
|
||||||
|
|
||||||
|
// 监听 vite 触发事件
|
||||||
|
if (import.meta.hot) {
|
||||||
|
import.meta.hot.on("eps-update", () => {
|
||||||
|
update();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开发环境下,生成本地 service 的类型描述文件
|
||||||
if (isDev && config.test.eps) {
|
if (isDev && config.test.eps) {
|
||||||
const list: any[] = [];
|
const list: any[] = [];
|
||||||
|
|
||||||
// 模拟 eps 数据
|
// 模拟 eps 数据
|
||||||
function deep(s: any) {
|
modules.forEach((m) => {
|
||||||
if (s.namespace) {
|
m.services?.forEach((s) => {
|
||||||
const api = Array.from(
|
const api = Array.from(
|
||||||
new Set([
|
new Set([
|
||||||
...Object.getOwnPropertyNames(s.constructor.prototype),
|
...Object.getOwnPropertyNames(s.value.constructor.prototype),
|
||||||
"page",
|
"page",
|
||||||
"list",
|
"list",
|
||||||
"info",
|
"info",
|
||||||
@ -42,18 +97,13 @@ export function createEps(modules: Module[]) {
|
|||||||
|
|
||||||
list.push({
|
list.push({
|
||||||
api,
|
api,
|
||||||
module: s.namespace.split("/")[0],
|
module: m.name,
|
||||||
name: s.constructor.name + "Entity",
|
name: s.value.constructor.name + "Entity",
|
||||||
prefix: `/admin/${s.namespace}`
|
prefix: `/admin/${s.path}`,
|
||||||
|
isLocal: true
|
||||||
});
|
});
|
||||||
} else {
|
});
|
||||||
for (const i in s) {
|
});
|
||||||
deep(s[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deep(s);
|
|
||||||
|
|
||||||
// 生成文件
|
// 生成文件
|
||||||
service.request({
|
service.request({
|
||||||
|
@ -1,64 +1,9 @@
|
|||||||
import { BaseService } from "./base";
|
import { BaseService } from "./base";
|
||||||
import { hmr } from "../hook";
|
|
||||||
import { eps } from "virtual:eps";
|
|
||||||
import { merge } from "lodash-es";
|
|
||||||
|
|
||||||
// service 数据集合
|
// service 数据集合
|
||||||
export const service: Eps.Service = hmr.getData("service", {
|
export const service: Eps.Service = {
|
||||||
|
// @ts-ignore
|
||||||
request: new BaseService().request
|
request: new BaseService().request
|
||||||
});
|
};
|
||||||
|
|
||||||
// 同步 service 数据
|
|
||||||
function update() {
|
|
||||||
function deep(d: any) {
|
|
||||||
if (d.namespace) {
|
|
||||||
const a = new BaseService(d.namespace);
|
|
||||||
|
|
||||||
for (const i in d) {
|
|
||||||
const { path, method = "get" } = d[i];
|
|
||||||
|
|
||||||
if (path) {
|
|
||||||
a.request = a.request;
|
|
||||||
|
|
||||||
a[i] = function (data?: any) {
|
|
||||||
return this.request({
|
|
||||||
url: path,
|
|
||||||
method,
|
|
||||||
[method.toLocaleLowerCase() == "post" ? "data" : "params"]: data
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const i in a) {
|
|
||||||
d[i] = a[i];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (const i in d) {
|
|
||||||
deep(d[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 遍历
|
|
||||||
deep(eps.service);
|
|
||||||
|
|
||||||
// 合并
|
|
||||||
merge(service, eps.service);
|
|
||||||
|
|
||||||
// 缓存
|
|
||||||
hmr.setData("service", service);
|
|
||||||
|
|
||||||
// tips
|
|
||||||
console.log("[eps] update");
|
|
||||||
}
|
|
||||||
|
|
||||||
update();
|
|
||||||
|
|
||||||
if (import.meta.hot) {
|
|
||||||
import.meta.hot.on("eps-update", () => {
|
|
||||||
update();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export * from "./base";
|
export * from "./base";
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useCrud } from "@cool-vue/crud";
|
import { useCrud } from "@cool-vue/crud";
|
||||||
import { isObject, isString } from "lodash-es";
|
import { isString } from "lodash-es";
|
||||||
import { computed, defineComponent, isRef, PropType, Ref, ref, watch } from "vue";
|
import { computed, defineComponent, isRef, PropType, Ref, ref, watch } from "vue";
|
||||||
import { parsePx } from "/@/cool/utils";
|
import { parsePx } from "/@/cool/utils";
|
||||||
|
|
||||||
|
@ -1,10 +1,3 @@
|
|||||||
* {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
|
|
||||||
"微软雅黑", Arial, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
*::-webkit-scrollbar {
|
*::-webkit-scrollbar {
|
||||||
width: 10px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
|
@ -104,7 +104,8 @@ function open() {
|
|||||||
labelPosition: "top"
|
labelPosition: "top"
|
||||||
},
|
},
|
||||||
dialog: {
|
dialog: {
|
||||||
height: "500px"
|
height: "500px",
|
||||||
|
width: "1000px"
|
||||||
},
|
},
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
|
216
src/modules/demo/components/select-user.vue
Normal file
216
src/modules/demo/components/select-user.vue
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
<template>
|
||||||
|
<div class="select-user__inner">
|
||||||
|
<div class="btns">
|
||||||
|
<el-button type="success" @click="open">添加</el-button>
|
||||||
|
<el-button type="danger" :disabled="list.length == 0" @click="remove">移除</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<cl-table :data="list" :ref="setRefs('table')" :auto-height="false" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<cl-dialog v-model="visible" width="1200px" title="选择用户">
|
||||||
|
<cl-crud ref="Crud">
|
||||||
|
<cl-row>
|
||||||
|
<!-- 刷新按钮 -->
|
||||||
|
<cl-refresh-btn />
|
||||||
|
|
||||||
|
<cl-filter label="状态">
|
||||||
|
<cl-select :options="options.status" prop="status" :width="120" />
|
||||||
|
</cl-filter>
|
||||||
|
|
||||||
|
<cl-flex1 />
|
||||||
|
<!-- 关键字搜索 -->
|
||||||
|
<cl-search-key placeholder="搜索昵称" />
|
||||||
|
</cl-row>
|
||||||
|
|
||||||
|
<cl-row>
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<cl-table ref="Table" :auto-height="false" />
|
||||||
|
</cl-row>
|
||||||
|
|
||||||
|
<cl-row>
|
||||||
|
<span>已选 {{ Table?.selection.length }} 人</span>
|
||||||
|
<cl-flex1 />
|
||||||
|
<!-- 分页控件 -->
|
||||||
|
<cl-pagination />
|
||||||
|
</cl-row>
|
||||||
|
</cl-crud>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="close">取消</el-button>
|
||||||
|
<el-button type="success" @click="select">选择</el-button>
|
||||||
|
</template>
|
||||||
|
</cl-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup name="select-user">
|
||||||
|
import { useCrud, useForm, useTable } from "@cool-vue/crud";
|
||||||
|
import { useCool } from "/@/cool";
|
||||||
|
import { nextTick, reactive, ref, watch } from "vue";
|
||||||
|
import { cloneDeep } from "lodash";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
isDisabled: Boolean,
|
||||||
|
prop: String,
|
||||||
|
scope: null,
|
||||||
|
disabled: Boolean
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["update:modelValue"]);
|
||||||
|
|
||||||
|
const { service, refs, setRefs } = useCool();
|
||||||
|
|
||||||
|
// 上级表单
|
||||||
|
const Form = useForm();
|
||||||
|
|
||||||
|
// 选项
|
||||||
|
const options = reactive({
|
||||||
|
status: [
|
||||||
|
{
|
||||||
|
label: "启用",
|
||||||
|
value: 1,
|
||||||
|
type: "success"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "禁用",
|
||||||
|
value: 0,
|
||||||
|
type: "danger"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// cl-table
|
||||||
|
const Table = useTable({
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
type: "selection",
|
||||||
|
width: 60,
|
||||||
|
reserveSelection: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "headImg",
|
||||||
|
label: "头像",
|
||||||
|
component: {
|
||||||
|
name: "cl-avatar"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "username",
|
||||||
|
label: "手机号",
|
||||||
|
minWidth: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "name",
|
||||||
|
label: "姓名",
|
||||||
|
minWidth: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "departmentName",
|
||||||
|
label: "部门名称",
|
||||||
|
minWidth: 150
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "状态",
|
||||||
|
prop: "status",
|
||||||
|
minWidth: 100,
|
||||||
|
dict: options.status
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "创建时间",
|
||||||
|
prop: "createTime",
|
||||||
|
sortable: "desc",
|
||||||
|
minWidth: 160
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// cl-crud
|
||||||
|
const Crud = useCrud({
|
||||||
|
service: service.base.sys.user,
|
||||||
|
async onRefresh(params, { next }) {
|
||||||
|
await next(params);
|
||||||
|
|
||||||
|
// 数据反选
|
||||||
|
list.value.forEach((e) => {
|
||||||
|
const d = Table.value?.data.find((a) => a.id == e.id);
|
||||||
|
|
||||||
|
if (d) {
|
||||||
|
Table.value?.toggleRowSelection(d, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 刷新
|
||||||
|
async function refresh(params?: any) {
|
||||||
|
return Crud.value?.refresh(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 弹窗是否可见
|
||||||
|
const visible = ref(false);
|
||||||
|
|
||||||
|
// 已选列表
|
||||||
|
const list = ref<Eps.BaseSysUserEntity[]>([]);
|
||||||
|
|
||||||
|
// 打开选择弹窗
|
||||||
|
function open() {
|
||||||
|
visible.value = true;
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
refresh({
|
||||||
|
size: 10
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭选择弹窗
|
||||||
|
function close() {
|
||||||
|
visible.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择
|
||||||
|
function select() {
|
||||||
|
list.value = cloneDeep(Table.value?.selection || []);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除
|
||||||
|
function remove() {
|
||||||
|
const ids = (refs.table.selection as any[]).map((e) => e.id);
|
||||||
|
|
||||||
|
list.value = list.value.filter((e) => {
|
||||||
|
// 清空选择状态
|
||||||
|
refs.table.toggleRowSelection(e, false);
|
||||||
|
|
||||||
|
// 移除已选的
|
||||||
|
return !ids.find((id) => id == e.id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听已选列表,返回 ids
|
||||||
|
watch(
|
||||||
|
list,
|
||||||
|
(arr) => {
|
||||||
|
emit(
|
||||||
|
"update:modelValue",
|
||||||
|
arr.map((e) => e.id)
|
||||||
|
);
|
||||||
|
Form.value?.validateField(props.prop);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.select-user__inner {
|
||||||
|
.btns {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -45,7 +45,7 @@
|
|||||||
},
|
},
|
||||||
{ label: '手机号', value: 'phone' }
|
{ label: '手机号', value: 'phone' }
|
||||||
]"
|
]"
|
||||||
:width="200"
|
:width="250"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 高级搜索按钮 -->
|
<!-- 高级搜索按钮 -->
|
||||||
@ -88,7 +88,11 @@
|
|||||||
</cl-row>
|
</cl-row>
|
||||||
|
|
||||||
<!-- 新增、编辑 -->
|
<!-- 新增、编辑 -->
|
||||||
<cl-upsert ref="Upsert" />
|
<cl-upsert ref="Upsert">
|
||||||
|
<template #slot-userIds="{ scope }">
|
||||||
|
<select-user v-model="scope.userIds" />
|
||||||
|
</template>
|
||||||
|
</cl-upsert>
|
||||||
|
|
||||||
<!-- 高级搜索 -->
|
<!-- 高级搜索 -->
|
||||||
<cl-adv-search ref="AdvSearch" />
|
<cl-adv-search ref="AdvSearch" />
|
||||||
@ -102,6 +106,7 @@ import { reactive } from "vue";
|
|||||||
import { ElMessage, ElMessageBox } from "element-plus";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
import { useCool } from "/@/cool";
|
import { useCool } from "/@/cool";
|
||||||
import FormBtn from "../components/form-btn.vue";
|
import FormBtn from "../components/form-btn.vue";
|
||||||
|
import SelectUser from "../components/select-user.vue";
|
||||||
|
|
||||||
// 基础
|
// 基础
|
||||||
const { service, refs, setRefs } = useCool();
|
const { service, refs, setRefs } = useCool();
|
||||||
@ -156,6 +161,11 @@ function refresh(params?: any) {
|
|||||||
|
|
||||||
// 新增、编辑
|
// 新增、编辑
|
||||||
const Upsert = useUpsert({
|
const Upsert = useUpsert({
|
||||||
|
dialog: {
|
||||||
|
height: "600px", // 固定高
|
||||||
|
width: "1000px" // 固定宽
|
||||||
|
},
|
||||||
|
|
||||||
items: [
|
items: [
|
||||||
// 分组
|
// 分组
|
||||||
{
|
{
|
||||||
@ -232,7 +242,6 @@ const Upsert = useUpsert({
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
label: "省市区",
|
label: "省市区",
|
||||||
prop: "pca",
|
prop: "pca",
|
||||||
@ -241,6 +250,14 @@ const Upsert = useUpsert({
|
|||||||
name: "cl-distpicker"
|
name: "cl-distpicker"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: "选择用户",
|
||||||
|
prop: "userIds",
|
||||||
|
group: "base",
|
||||||
|
component: {
|
||||||
|
name: "slot-userIds"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
label: "工作",
|
label: "工作",
|
||||||
|
Loading…
Reference in New Issue
Block a user