This commit is contained in:
icssoa 2023-10-30 00:56:05 +08:00
parent 2ef563c069
commit 42b406e028
11 changed files with 337 additions and 112 deletions

View File

@ -65,7 +65,9 @@ async function getData(temps?: Eps.Entity[]) {
// 创建 json 文件 // 创建 json 文件
function createJson() { function createJson() {
const d = list.map((e) => { const d = list
.filter((e) => !e.isLocal) // 过滤本地的 service 数据
.map((e) => {
return { return {
prefix: e.prefix, prefix: e.prefix,
name: e.name || "", name: e.name || "",

View File

@ -28,5 +28,6 @@ export namespace Eps {
module: string; module: string;
name: string; name: string;
prefix: string; prefix: string;
[key: string]: any;
} }
} }

View File

@ -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);
} }

View File

@ -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/, "")
}, },

View File

@ -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() {
// 设置 request 方法
function set(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) {
set(d[i]);
}
}
}
// 遍历每一个方法
set(eps.service);
// 合并[eps]
merge(service, eps.service);
// 合并[local]
merge(
service,
path2Obj(
modules.reduce((a, b) => { modules.reduce((a, b) => {
return a.concat(...((b.services as any[]) || [])); return a.concat(...((b.services as any[]) || []));
}, []) }, [])
)
); );
// 合并数据 // 提示
merge(service, s); if (isDev) {
console.log("[eps] update", service);
}
}
// 开发环境下,生成本地 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({

View File

@ -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";

View File

@ -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";

View File

@ -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;

View File

@ -104,7 +104,8 @@ function open() {
labelPosition: "top" labelPosition: "top"
}, },
dialog: { dialog: {
height: "500px" height: "500px",
width: "1000px"
}, },
items: [ items: [
{ {

View 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>

View File

@ -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: "工作",