增加postgre,oracle,sqlserver适配。增加crud~demo

This commit is contained in:
vben
2025-12-03 18:44:30 +08:00
parent aa8f8952bd
commit b91a6cc46d
28 changed files with 1054 additions and 412 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ end_of_line=lf
insert_final_newline=true
indent_style=space
indent_size=2
max_line_length = 100
max_line_length = 180
trim_trailing_whitespace = true
quote_type = single
+1 -1
View File
@@ -165,7 +165,7 @@ function createRequestClient(baseURL: string) {
// 通用的错误处理, 如果没有进入上面的错误处理逻辑,就会进入这里
// 主要处理http状态码不为200(如网络异常/离线)的情况 必须放在在下面的响应拦截器之前
client.addResponseInterceptor(
errorMessageResponseInterceptor((msg: string) => message.error(msg)),
errorMessageResponseInterceptor((msg: string) => ElMessage.error(msg)),
);
client.addResponseInterceptor<HttpResponse>({
+22 -8
View File
@@ -5,6 +5,7 @@ import { reactive, ref, toRefs } from 'vue';
import { requestClient } from '#/api/request';
import { modalSave } from '#/utils/page/edit';
import { listQuery } from '#/utils/page/list';
const props = defineProps({
url: {
@@ -175,15 +176,23 @@ const allowDrag = (draggingNode: any) => {
};
// endregion
const addChildCate =async () => {
const addChildCate = async () => {
await openModal({ pid: currNode.id });
};
const editCate = async () => {
await openModal({ id: currNode.id });
};
const deleteCate = async () => {
await requestClient.delete(`${props.url}/${currNode.id}`);
treeRef.value!.remove(currNode);
ElMessageBox.confirm('确认要删除吗?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
await requestClient.delete(`${props.url}/${currNode.id}`);
treeRef.value!.remove(currNode);
})
.catch(() => ElMessage.info('已取消删除'));
};
// edit逻辑
@@ -194,12 +203,17 @@ const openModal = async (data: any) => {
if (data && data.id) {
state.form = await requestClient.get(`${props.url}/info/${data.id}`);
state.type = 'edit';
if (state.form.pid === 0 || state.form.pid === '0') {
delete state.form.pid;
}
} else {
state.type = 'add';
state.form = { avtag: true,children: [] };
state.form.pid = data.pid ?? null;
state.form = { avtag: true, children: [] };
if (data.pid) {
state.form.pid = data.pid;
}
}
rdata.cates = await requestClient.get(`${props.url}/tree?id=${data?.id}`);
rdata.cates = await (data?.id ? requestClient.get(`${props.url}/tree?id=${data?.id}`) : requestClient.get(`${props.url}/tree`));
state.show = true;
formRef?.value?.clearValidate();
};
@@ -221,7 +235,7 @@ const save = async () => {
state.show = false;
if (state.type === 'add') {
if (backNode.pid === 0 || backNode.pid === null) {
if (backNode.pid === 0 || backNode.pid === null || backNode.pid === undefined) {
state.data.push(backNode);
} else {
for (const targetNode of state.data) {
@@ -277,7 +291,7 @@ const save = async () => {
</div>
</div>
</template>
<div style="margin-bottom: 88px; font-family: 'Courier New', Helvetica, Arial, sans-serif;">
<div style="margin-bottom: 88px; font-family: 'Courier New', Helvetica, Arial, sans-serif">
<el-tree
highlight-current
@node-contextmenu="rightClick"
@@ -0,0 +1,48 @@
import type { RouteRecordRaw } from 'vue-router';
const routes: RouteRecordRaw[] = [
{
meta: {
order: 22,
title: '使用案例',
},
name: 'Demo',
path: '/demo',
children: [
{
name: 'DemoSingleMain',
path: '/demo/single/main',
component: () => import('#/views/demo/single/main/index.vue'),
meta: {
title: '单一主表案例',
},
},
{
name: 'DemoSingleCate',
path: '/demo/single/cate',
component: () => import('#/views/demo/single/cate/index.vue'),
meta: {
title: '单一树表案例',
},
},
{
name: 'DemoLink',
path: '/demo/Link',
component: () => import('#/views/demo/link/index.vue'),
meta: {
title: '关联主分子案例',
},
},
{
name: 'DemoGiteeVote',
path: '/demo/gitee/vote',
component: () => import('#/views/demo/gitee/vote/index.vue'),
meta: {
title: '开源投票',
},
},
],
},
];
export default routes;
@@ -36,7 +36,7 @@ async function loadTenant() {
}
}
onMounted(loadTenant);
// onMounted(loadTenant);
const formSchema = computed((): VbenFormSchema[] => {
return [
@@ -130,7 +130,7 @@ async function handleLogin(values: LoginCodeParams) {
<div>
<ElAlert
class="mb-4"
title="测试手机号: 15888888888 正确验证码: 1234 演示使用不会真的发送"
title="测试手机号: 13812345678 正确验证码: 1234 演示使用不会真的发送"
type="success"
:closable="false"
/>
@@ -56,6 +56,9 @@ const save = async () => {
<el-form-item label="排序号" prop="ornum" :rules="[{ required: true, message: '排序号不能为空' }]" style="width: 50%">
<el-input-number v-model="form.ornum" controls-position="right" :min="0" style="width: 100%" />
</el-form-item>
<el-form-item label="是否可用" style="width: 50%">
<el-switch v-model="form.avtag" />
</el-form-item>
<el-form-item label="分类名称" prop="name" :rules="[{ required: true, message: '分类名称不能为空' }]">
<el-input v-model="form.name" placeholder="请输入分类名称" maxlength="100" />
</el-form-item>
+60
View File
@@ -0,0 +1,60 @@
<script lang="ts" setup>
import { requestClient } from '#/api/request';
import { drawerSave, reset } from '#/utils/page/edit';
const emits = defineEmits(['close']);
const state = reactive({
url: '/demo/demo',
show: false,
form: {} as any,
});
const formRef = ref();
const { form } = toRefs(state);
const open = async (data: any) => {
state.form = data && data.id ? await requestClient.get(`${state.url}/info/${data.id}`) : { avtag: true };
await reset({ formRef: formRef.value, state });
};
defineExpose({ open });
const save = async () => {
await drawerSave({ formRef: formRef.value, state });
emits('close');
};
</script>
<template>
<el-drawer v-model="state.show" size="46%">
<template #header>
<h4>参数维护</h4>
</template>
<template #default>
<el-form ref="formRef" :model="form" label-width="140px">
<el-form-item label="部门ID" prop="deptId" :rules="[{ required: true, message: '部门ID不能为空' }]">
<el-input v-model="form.deptId" />
</el-form-item>
<el-form-item label="用户ID" prop="userId" :rules="[{ required: true, message: '用户ID不能为空' }]">
<el-input v-model="form.userId" />
</el-form-item>
<el-form-item label="排序号" prop="orderNum" :rules="[{ required: true, message: '排序号不能为空' }]">
<el-input v-model="form.orderNum" />
</el-form-item>
<el-form-item label="key键" prop="testKey" :rules="[{ required: true, message: '键不能为空' }]">
<el-input v-model="form.testKey" />
</el-form-item>
<el-form-item label="值" prop="value" :rules="[{ required: true, message: '值不能为空' }]">
<el-input v-model="form.value" />
</el-form-item>
<el-form-item label="备注" prop="notes">
<el-input v-model="form.notes" :rows="2" type="textarea" />
</el-form-item>
</el-form>
</template>
<template #footer>
<div style="flex: auto; margin: 20px">
<el-button type="primary" @click="save">保 存</el-button>
<el-button @click="state.show = false">关 闭</el-button>
</div>
</template>
</el-drawer>
</template>
@@ -0,0 +1,62 @@
<script lang="ts" setup>
import { requestClient } from '#/api/request';
import { drawerSave, reset } from '#/utils/page/edit';
const emits = defineEmits(['close']);
const state = reactive({
url: '/demo/gitee/vote',
show: false,
form: {} as any,
});
const formRef = ref();
const { form } = toRefs(state);
const open = async (data: any) => {
state.form = data && data.id ? await requestClient.get(`${state.url}/info/${data.id}`) : { avtag: true };
await reset({ formRef: formRef.value, state });
};
defineExpose({ open });
const save = async () => {
await drawerSave({ formRef: formRef.value, state });
emits('close');
};
</script>
<template>
<el-drawer v-model="state.show" size="46%">
<template #header>
<h4>案例维护</h4>
</template>
<template #default>
<el-form ref="formRef" :model="form" label-width="140px" class="zform">
<el-form-item label="案例名称" prop="name" :rules="[{ required: true, message: '案例名称不能为空' }]">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="备注" prop="notes">
<el-input v-model="form.notes" :rows="3" type="textarea" />
</el-form-item>
<template v-if="form.crtim">
<el-form-item label="创建人" style="width: 50%">
<div>{{ form.cruna }}</div>
</el-form-item>
<el-form-item label="创建时间" style="width: 50%">
<div>{{ form.crtim }}</div>
</el-form-item>
<el-form-item label="更新人" style="width: 50%">
<div>{{ form.upuna }}</div>
</el-form-item>
<el-form-item label="更新时间" style="width: 50%">
<div>{{ form.uptim }}</div>
</el-form-item>
</template>
</el-form>
</template>
<template #footer>
<div style="flex: auto; margin: 20px">
<el-button type="primary" @click="save">保 存</el-button>
<el-button @click="state.show = false">关 闭</el-button>
</div>
</template>
</el-drawer>
</template>
@@ -0,0 +1,104 @@
<script setup lang="ts">
import { Page } from '@vben/common-ui';
import { requestClient } from '#/api/request';
import { listDelete, listItemDelete, listQuery, listSelect } from '#/utils/page/list';
import DrawerEdit from './edit.vue';
const state = reactive({
url: '/demo/gitee/vote',
loading: false,
ids: [],
form: {
pageSize: 10,
} as any,
single: true,
multiple: true,
rows: [],
total: 0,
});
const editRef = ref() as any;
const editClose = async () => {
await listQuery(state);
};
onMounted(async () => {
await listQuery(state);
});
const sync = async () => {
const data = await requestClient.get(`${state.url}/sync`, { params: state.form });
console.log(data);
};
</script>
<template>
<Page auto-content-height>
<el-card class="box-card" style="height: 100%" body-style="height: 100%">
<template #header>
<div class="flex justify-between">
<el-space>
<el-input style="width: 180px" v-model="state.form.name" placeholder="输入名称回车查询" clearable @keyup.enter="listQuery(state)" />
<el-button type="primary" @click="listQuery(state)" icon="Search"> 查询</el-button>
<el-button type="primary" @click="sync" icon="Search"> 同步</el-button>
</el-space>
<el-space>
<el-button icon="Plus" type="success" plain @click="editRef.open()">新增</el-button>
<el-button icon="Delete" type="danger" plain @click="listDelete(state)" :disabled="state.multiple">删除</el-button>
</el-space>
</div>
</template>
<el-table
@selection-change="listSelect($event, state)"
style="height: calc(100% - 90px)"
:cell-style="{ padding: '2px' }"
:row-style="{ height: '36px' }"
v-loading="state.loading"
:data="state.rows"
border
stripe
>
<el-table-column type="selection" width="44" align="center" />
<el-table-column label="#" type="index" width="50" align="center" />
<el-table-column label="案例名称">
<template #default="scope">
<span class="link_span" @click="editRef.open({ id: scope.row.id })">{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column label="创建时间" prop="crtim" width="164" />
<el-table-column label="创建人" prop="cruna" width="86" align="center" />
<el-table-column label="更新时间" prop="uptim" width="164" />
<el-table-column label="更新人" prop="upuna" width="86" align="center" />
<el-table-column label="案例备注" prop="notes" />
<el-table-column label="操作" align="center" width="86" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="editRef.open({ id: scope.row.id })" />
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="listItemDelete(state, scope.row.id)" />
</el-tooltip>
</template>
</el-table-column>
</el-table>
<el-pagination
style="margin-top: 10px"
@size-change="listQuery(state)"
@current-change="listQuery(state)"
:pager-count="5"
:page-sizes="[10, 20, 30]"
background
:total="state.total"
v-model:current-page="state.form.pageNum"
v-model:page-size="state.form.pageSize"
layout="total, sizes, prev, pager, next, jumper"
/>
</el-card>
<DrawerEdit ref="editRef" @close="editClose" />
</Page>
</template>
+97
View File
@@ -0,0 +1,97 @@
<script setup lang="ts">
import { Page } from '@vben/common-ui';
import { listDelete, listItemDelete, listQuery, listSelect } from '#/utils/page/list';
import DrawerEdit from './edit.vue';
const state = reactive({
url: '/demo/demo',
loading: false,
ids: [],
form: {
pageSize: 10,
} as any,
single: true,
multiple: true,
rows: [],
total: 0,
});
const editRef = ref() as any;
const editClose = async () => {
await listQuery(state);
};
onMounted(async () => {
await listQuery(state);
});
</script>
<template>
<Page auto-content-height>
<el-card class="box-card" style="height: 100%" body-style="height: 100%">
<template #header>
<div class="flex justify-between">
<el-space>
<el-input style="width: 180px" v-model="state.form.name" placeholder="输入名称回车查询" clearable @keyup.enter="listQuery(state)" />
<el-button type="primary" @click="listQuery(state)" icon="Search"> 查询</el-button>
</el-space>
<el-space>
<el-button icon="Plus" type="success" plain @click="editRef.open()">新增</el-button>
<el-button icon="Delete" type="danger" plain @click="listDelete(state)" :disabled="state.multiple">删除</el-button>
</el-space>
</div>
</template>
<el-table
@selection-change="listSelect($event, state)"
style="height: calc(100% - 90px)"
:cell-style="{ padding: '2px' }"
:row-style="{ height: '36px' }"
v-loading="state.loading"
:data="state.rows"
border
stripe
>
<el-table-column type="selection" width="44" align="center" />
<el-table-column label="#" type="index" width="50" align="center" />
<el-table-column label="主键">
<template #default="scope">
<span class="link_span" @click="editRef.open({ id: scope.row.id })">{{ scope.row.id }}</span>
</template>
</el-table-column>
<el-table-column label="部门ID" prop="deptId" />
<el-table-column label="用户ID" prop="userId" />
<el-table-column label="排序号" prop="orderNum" />
<el-table-column label="测试key" prop="testKey" />
<el-table-column label="测试value" prop="value" />
<el-table-column label="操作" align="center" width="86" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="editRef.open({ id: scope.row.id })" />
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="listItemDelete(state, scope.row.id)" />
</el-tooltip>
</template>
</el-table-column>
</el-table>
<el-pagination
style="margin-top: 10px"
@size-change="listQuery(state)"
@current-change="listQuery(state)"
:pager-count="5"
:page-sizes="[10, 20, 30]"
background
:total="state.total"
v-model:current-page="state.form.pageNum"
v-model:page-size="state.form.pageSize"
layout="total, sizes, prev, pager, next, jumper"
/>
</el-card>
<DrawerEdit ref="editRef" @close="editClose" />
</Page>
</template>
+161
View File
@@ -0,0 +1,161 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { buildUUID } from '@vben/utils';
import { requestClient } from '#/api/request';
import OrgModal from '#/components/sys/OrgModal.vue';
import { drawerSave } from '#/utils/page/edit';
const emits = defineEmits(['close']);
const formRef = ref();
const state = reactive({
url: '/demo/link/main',
show: false,
form: {} as any,
});
const rdata = reactive({} as any);
const { form } = toRefs(state);
// 暴露open方法给父组件调用
const open = async (data: any) => {
state.form = data && data.id ? await requestClient.get(`${state.url}/info/${data.id}`) : { avtag: true, items: [], catid: data.catid };
rdata.cates = await requestClient.get(`/demo/link/cate/tree`);
if (state.form.catid === 0 || state.form.catid === '0' || state.form.catid === undefined) {
delete state.form.catid;
}
state.show = true;
formRef?.value?.clearValidate();
};
defineExpose({ open });
const save = async () => {
await drawerSave({ formRef: formRef.value, state });
emits('close');
};
// region a 行项目逻辑
const addItem = () => {
let newOrnum = 1;
if (form.value.items.length > 0) {
newOrnum = form.value.items[form.value.items.length - 1].ornum + 1;
}
if (form.value.id) {
form.value.items.push({
id: buildUUID(),
maiid: form.value.id,
ornum: newOrnum,
});
} else {
form.value.items.push({
id: buildUUID(),
ornum: newOrnum,
});
}
};
// endregion
// region a 包含成员逻辑
const orgModal = ref();
const openOrgsModal = () => {
orgModal.value.open({
orgType: 15,
selectMode: 2,
orgs: toRaw(form.value.orgs),
});
};
const closeOrgModal = (data: any) => {
form.value.orgs = data.orgs;
};
const orgsName = computed(() => {
let names = '';
if (form.value.orgs && form.value.orgs.length > 0) {
for (const org of form.value.orgs) {
names += `${org.name};`;
}
}
return names;
});
// endregion
</script>
<template>
<el-drawer v-model="state.show" size="40%">
<template #header>
<h4>XX信息维护</h4>
<OrgModal ref="orgModal" @close="closeOrgModal" />
</template>
<template #default>
<el-form ref="formRef" :model="form" label-width="140px" class="zform">
<el-form-item label="所属分类">
<el-tree-select clearable v-model="form.catid" :data="rdata.cates" :props="{ value: 'id', label: 'name' }" value-key="catid" placeholder="选择分类" check-strictly />
</el-form-item>
<el-form-item label="XX名称" prop="name" :rules="[{ required: true, message: 'XX名称不能为空' }]">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="行项目列表" style="width: 100%">
<el-table size="small" border :data="form.items" :row-style="{ height: '36px' }" style="width: 100%">
<el-table-column label="排序号" width="90" align="center">
<template #default="scope">
<el-input-number v-model="scope.row.ornum" controls-position="right" style="width: 100%" />
</template>
</el-table-column>
<el-table-column label="行项目名称" width="200">
<template #default="scope">
<el-input v-model="scope.row.name" required />
</template>
</el-table-column>
<el-table-column label="行项目描述">
<template #default="scope">
<el-input v-model="scope.row.notes" required />
</template>
</el-table-column>
<el-table-column fixed="right" label="操作" width="50" align="center">
<template #header>
<el-icon :size="22" style="top: 5px; cursor: pointer" color="#666">
<CirclePlus @click="addItem" />
</el-icon>
</template>
<template #default="scope">
<el-icon :size="22" style="top: 3px; cursor: pointer">
<CircleClose @click="form.items.splice(scope.$index, 1)" />
</el-icon>
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-form-item label="包含成员">
<el-input type="textarea" placeholder="中间表测试" :rows="3" v-model="orgsName" readonly @click="openOrgsModal" />
</el-form-item>
<el-form-item label="XX备注" prop="notes">
<el-input v-model="form.notes" :rows="3" type="textarea" />
</el-form-item>
<template v-if="form.crtim">
<el-form-item label="创建人" style="width: 50%">
<div>{{ form.cruna }}</div>
</el-form-item>
<el-form-item label="创建时间" style="width: 50%">
<div>{{ form.crtim }}</div>
</el-form-item>
<el-form-item label="更新人" style="width: 50%">
<div>{{ form.upuna }}</div>
</el-form-item>
<el-form-item label="更新时间" style="width: 50%">
<div>{{ form.uptim }}</div>
</el-form-item>
</template>
</el-form>
</template>
<template #footer>
<div style="flex: auto; margin: 20px">
<el-button type="primary" @click="save">保 存</el-button>
<el-button @click="state.show = false">关 闭</el-button>
</div>
</template>
</el-drawer>
</template>
+109
View File
@@ -0,0 +1,109 @@
<script setup lang="ts">
import { Page } from '@vben/common-ui';
import EditTree from '#/components/tree/EditTree.vue';
import { listDelete, listItemDelete, listQuery, listSelect } from '#/utils/page/list';
import DrawerEdit from './edit.vue';
const state = reactive({
url: '/demo/link/main',
loading: false,
ids: [],
form: {
pageSize: 10,
} as any,
single: true,
multiple: true,
rows: [],
total: 0,
});
onMounted(async () => {
await listQuery(state);
});
const nodeClick = async (node: any) => {
state.form.catid = node.id;
if (node.id === '') {
delete state.form.catid;
}
await listQuery(state);
};
const editRef = ref() as any;
const editClose = async () => {
await listQuery(state);
};
</script>
<template>
<Page auto-content-height>
<div class="flex h-full gap-[8px]">
<div class="w-[260px]">
<EditTree @node-click="nodeClick" url="/demo/link/cate" tip="XX分类" />
</div>
<el-card style="height: 100%" body-style="height: 100%" class="box-card flex-1 overflow-hidden">
<template #header>
<div class="flex justify-between">
<el-space>
<el-input style="width: 180px" v-model="state.form.name" placeholder="输入名称回车查询" clearable @keyup.enter="listQuery(state)" />
<el-button type="primary" @click="listQuery(state)" icon="Search"> 查询</el-button>
</el-space>
<el-space>
<el-button icon="Plus" type="success" plain @click="editRef.open({ catid: state.form.catid })">新增 </el-button>
<el-button icon="Delete" type="danger" plain @click="listDelete(state)" :disabled="state.multiple">删除 </el-button>
</el-space>
</div>
</template>
<el-table
style="height: calc(100% - 90px)"
@selection-change="listSelect($event, state)"
:cell-style="{ padding: '2px' }"
:row-style="{ height: '36px' }"
v-loading="state.loading"
:data="state.rows"
border
stripec
>
<el-table-column type="selection" width="44" align="center" />
<el-table-column label="#" type="index" width="50" align="center" />
<el-table-column label="XX名称" align="center" prop="name" width="180">
<template #default="scope">
<span class="link_span" @click="editRef.open({ id: scope.row.id })">{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column label="所属分类" align="center" prop="catna" width="180" />
<el-table-column label="创建时间" align="center" prop="crtim" width="164" />
<el-table-column label="更新时间" align="center" prop="uptim" width="164" />
<el-table-column label="备注" align="center" prop="notes" />
<el-table-column label="操作" fixed="right" align="center" width="86" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="editRef.open({ id: scope.row.id })" />
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="listItemDelete(state, scope.row.id)" />
</el-tooltip>
</template>
</el-table-column>
</el-table>
<el-pagination
style="margin-top: 10px"
@size-change="listQuery(state)"
@current-change="listQuery(state)"
:pager-count="5"
:total="state.total"
v-model:current-page="state.form.pageNum"
v-model:page-size="state.form.pageSize"
layout="total, sizes, prev, pager, next, jumper"
/>
</el-card>
</div>
<DrawerEdit ref="editRef" @close="editClose" />
</Page>
</template>
@@ -0,0 +1,84 @@
<script lang="ts" setup>
import { requestClient } from '#/api/request';
import { drawerSave } from '#/utils/page/edit';
const emits = defineEmits(['close']);
const formRef = ref();
const state = reactive({
url: '/demo/single/cate',
show: false,
form: {} as any,
});
const rdata = reactive({} as any);
const { form } = toRefs(state);
const open = async (data: any) => {
if (data.id) {
state.form = await requestClient.get(`${state.url}/info/${data.id}`);
rdata.cates = await requestClient.get(`${state.url}/tree?id=${data.id}`);
} else {
state.form = { avtag: true, pid: data.pid };
rdata.cates = await requestClient.get(`${state.url}/tree`);
}
if (state.form.pid === 0 || state.form.pid === '0' || state.form.pid === undefined) {
delete state.form.pid;
}
state.show = true;
formRef?.value?.clearValidate();
};
defineExpose({ open });
const save = async () => {
await drawerSave({ formRef: formRef.value, state });
emits('close');
};
</script>
<template>
<el-drawer v-model="state.show" size="46%">
<template #header>
<h4>XX信息--{{ form.id ? '修改' : '新增' }}</h4>
</template>
<template #default>
<el-form ref="formRef" :model="form" label-width="140px" class="zform">
<el-form-item label="上级名称">
<el-tree-select clearable v-model="form.pid" :data="rdata.cates" :props="{ value: 'id', label: 'name' } as any" value-key="id" placeholder="选择上级菜单" check-strictly />
</el-form-item>
<el-form-item label="排序号" prop="ornum" :rules="[{ required: true, message: '排序号不能为空' }]" style="width: 50%">
<el-input-number v-model="form.ornum" controls-position="right" :min="0" style="width: 100%" />
</el-form-item>
<el-form-item label="是否可用" style="width: 50%">
<el-switch v-model="form.avtag" />
</el-form-item>
<el-form-item label="XX名称" prop="name" :rules="[{ required: true, message: 'XX名称不能为空' }]">
<el-input v-model="form.name" placeholder="请输入XX名称" maxlength="100" />
</el-form-item>
<el-form-item label="备注" prop="notes">
<el-input v-model="form.notes" :rows="3" type="textarea" />
</el-form-item>
<template v-if="form.crtim">
<el-form-item label="创建人" style="width: 50%">
<div>{{ form.cruna }}</div>
</el-form-item>
<el-form-item label="创建时间" style="width: 50%">
<div>{{ form.crtim }}</div>
</el-form-item>
<el-form-item label="更新人" style="width: 50%">
<div>{{ form.upuna }}</div>
</el-form-item>
<el-form-item label="更新时间" style="width: 50%">
<div>{{ form.uptim }}</div>
</el-form-item>
</template>
</el-form>
</template>
<template #footer>
<div style="flex: auto; margin: 20px">
<el-button type="primary" @click="save">保 存</el-button>
<el-button @click="state.show = false">关 闭</el-button>
</div>
</template>
</el-drawer>
</template>
@@ -0,0 +1,82 @@
<script setup lang="tsx">
import { Page } from '@vben/common-ui';
import { treeItemDelete, treeQuery } from '#/utils/page/tree';
import DrawerEdit from './edit.vue';
const state = reactive({
url: '/demo/single/cate',
list: [] as any,
form: { name: '' } as any,
});
const columns = [
{ key: 'id', dataKey: 'id', title: 'ID', width: 120, hidden: true },
{ key: 'pid', dataKey: 'pid', title: '父ID', width: 100, hidden: true },
{ key: 'name', dataKey: 'name', title: 'XX名称', width: 180 },
{ key: 'ornum', dataKey: 'ornum', title: '排序', width: 50 },
{ key: 'crtim', dataKey: 'crtim', title: '创建时间', width: 180 },
{ key: 'cruna', dataKey: 'cruna', title: '创建人', width: 100 },
{ key: 'uptim', dataKey: 'uptim', title: '更新时间', width: 180 },
{ key: 'upuna', dataKey: 'upuna', title: '更新人', width: 100 },
{ key: 'notes', dataKey: 'notes', title: '备注', width: 300 },
{
align: 'center',
key: 'operate',
title: '操作',
width: 100,
fixed: 'right',
cellRenderer: (row: any) => (
<>
<el-tooltip content="修改" placement="top">
<el-button icon="Edit" link onClick={() => editRef.value.open({ id: row.rowData.id })} type="primary" />
</el-tooltip>
<el-tooltip content="新增" placement="top">
<el-button icon="Plus" link onClick={() => editRef.value.open({ pid: row.rowData.id })} type="primary" />
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button icon="Delete" link onClick={() => treeItemDelete(state, row.rowData.id)} type="primary" />
</el-tooltip>
</>
),
},
] as any;
onMounted(async () => {
await treeQuery(state);
});
const editRef = ref() as any;
const editClose = async () => {
await treeQuery(state);
};
</script>
<template>
<Page auto-content-height>
<el-card class="box-card" style="height: 100%" body-style="height: 100%">
<template #header>
<div class="flex justify-between">
<el-space>
<el-input style="width: 180px" v-model="state.form.name" placeholder="输入菜单名称可回车查询" clearable @keyup.enter="treeQuery(state)" />
<el-button type="primary" icon="Search" @click="treeQuery(state)">查询</el-button>
</el-space>
<el-space>
<el-button icon="Plus" type="success" plain @click="editRef.open({})">新增</el-button>
</el-space>
</div>
</template>
<div :style="{ height: 'calc(100% - 50px)' }">
<el-auto-resizer>
<template #default="{ height, width }">
<el-table-v2 :columns="columns" :data="state.list" :width="width" expand-column-key="name" :height="height" fixed scrollbar-always-on />
</template>
</el-auto-resizer>
</div>
</el-card>
<DrawerEdit ref="editRef" @close="editClose" />
</Page>
</template>
@@ -0,0 +1,62 @@
<script lang="ts" setup>
import { requestClient } from '#/api/request';
import { drawerSave, reset } from '#/utils/page/edit';
const emits = defineEmits(['close']);
const state = reactive({
url: '/demo/single/main',
show: false,
form: {} as any,
});
const formRef = ref();
const { form } = toRefs(state);
const open = async (data: any) => {
state.form = data && data.id ? await requestClient.get(`${state.url}/info/${data.id}`) : { avtag: true };
await reset({ formRef: formRef.value, state });
};
defineExpose({ open });
const save = async () => {
await drawerSave({ formRef: formRef.value, state });
emits('close');
};
</script>
<template>
<el-drawer v-model="state.show" size="46%">
<template #header>
<h4>XX信息维护</h4>
</template>
<template #default>
<el-form ref="formRef" :model="form" label-width="140px" class="zform">
<el-form-item label="XX名称" prop="name" :rules="[{ required: true, message: 'XX名称不能为空' }]">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="备注" prop="notes">
<el-input v-model="form.notes" :rows="3" type="textarea" />
</el-form-item>
<template v-if="form.crtim">
<el-form-item label="创建人" style="width: 50%">
<div>{{ form.cruna }}</div>
</el-form-item>
<el-form-item label="创建时间" style="width: 50%">
<div>{{ form.crtim }}</div>
</el-form-item>
<el-form-item label="更新人" style="width: 50%">
<div>{{ form.upuna }}</div>
</el-form-item>
<el-form-item label="更新时间" style="width: 50%">
<div>{{ form.uptim }}</div>
</el-form-item>
</template>
</el-form>
</template>
<template #footer>
<div style="flex: auto; margin: 20px">
<el-button type="primary" @click="save">保 存</el-button>
<el-button @click="state.show = false">关 闭</el-button>
</div>
</template>
</el-drawer>
</template>
@@ -0,0 +1,97 @@
<script setup lang="ts">
import { Page } from '@vben/common-ui';
import { listDelete, listItemDelete, listQuery, listSelect } from '#/utils/page/list';
import DrawerEdit from './edit.vue';
const state = reactive({
url: '/demo/single/main',
loading: false,
ids: [],
form: {
pageSize: 10,
} as any,
single: true,
multiple: true,
rows: [],
total: 0,
});
const editRef = ref() as any;
const editClose = async () => {
await listQuery(state);
};
onMounted(async () => {
await listQuery(state);
});
</script>
<template>
<Page auto-content-height>
<el-card class="box-card" style="height: 100%" body-style="height: 100%">
<template #header>
<div class="flex justify-between">
<el-space>
<el-input style="width: 180px" v-model="state.form.name" placeholder="输入名称回车查询" clearable @keyup.enter="listQuery(state)" />
<el-button type="primary" @click="listQuery(state)" icon="Search"> 查询</el-button>
</el-space>
<el-space>
<el-button icon="Plus" type="success" plain @click="editRef.open()">新增</el-button>
<el-button icon="Delete" type="danger" plain @click="listDelete(state)" :disabled="state.multiple">删除</el-button>
</el-space>
</div>
</template>
<el-table
@selection-change="listSelect($event, state)"
style="height: calc(100% - 90px)"
:cell-style="{ padding: '2px' }"
:row-style="{ height: '36px' }"
v-loading="state.loading"
:data="state.rows"
border
stripe
>
<el-table-column type="selection" width="44" align="center" />
<el-table-column label="#" type="index" width="50" align="center" />
<el-table-column label="XX名称">
<template #default="scope">
<span class="link_span" @click="editRef.open({ id: scope.row.id })">{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column label="创建时间" prop="crtim" width="164" />
<el-table-column label="创建人" prop="cruna" width="86" align="center" />
<el-table-column label="更新时间" prop="uptim" width="164" />
<el-table-column label="更新人" prop="upuna" width="86" align="center" />
<el-table-column label="XX备注" prop="notes" />
<el-table-column label="操作" align="center" width="86" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="editRef.open({ id: scope.row.id })" />
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="listItemDelete(state, scope.row.id)" />
</el-tooltip>
</template>
</el-table-column>
</el-table>
<el-pagination
style="margin-top: 10px"
@size-change="listQuery(state)"
@current-change="listQuery(state)"
:pager-count="5"
:page-sizes="[10, 20, 30]"
background
:total="state.total"
v-model:current-page="state.form.pageNum"
v-model:page-size="state.form.pageSize"
layout="total, sizes, prev, pager, next, jumper"
/>
</el-card>
<DrawerEdit ref="editRef" @close="editClose" />
</Page>
</template>
@@ -1,117 +0,0 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { Page } from '@vben/common-ui';
import {
ElButton,
ElCard,
ElMessage,
ElNotification,
ElSegmented,
ElSpace,
ElTable,
} from 'element-plus';
type NotificationType = 'error' | 'info' | 'success' | 'warning';
function info() {
ElMessage.info('How many roads must a man walk down');
}
function error() {
ElMessage.error({
duration: 2500,
message: 'Once upon a time you dressed so fine',
});
}
function warning() {
ElMessage.warning('How many roads must a man walk down');
}
function success() {
ElMessage.success(
'Cause you walked hand in hand With another man in my place',
);
}
function notify(type: NotificationType) {
ElNotification({
duration: 2500,
message: '说点啥呢',
type,
});
}
const tableData = [
{ prop1: '1', prop2: 'A' },
{ prop1: '2', prop2: 'B' },
{ prop1: '3', prop2: 'C' },
{ prop1: '4', prop2: 'D' },
{ prop1: '5', prop2: 'E' },
{ prop1: '6', prop2: 'F' },
];
const segmentedValue = ref('Mon');
const segmentedOptions = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
</script>
<template>
<Page
description="支持多语言,主题功能集成切换等"
title="Element Plus组件使用演示"
>
<div class="flex flex-wrap gap-5">
<ElCard class="mb-5 w-auto">
<template #header> 按钮 </template>
<ElSpace>
<ElButton text>Text</ElButton>
<ElButton>Default</ElButton>
<ElButton type="primary"> Primary </ElButton>
<ElButton type="info"> Info </ElButton>
<ElButton type="success"> Success </ElButton>
<ElButton type="warning"> Warning </ElButton>
<ElButton type="danger"> Error </ElButton>
</ElSpace>
</ElCard>
<ElCard class="mb-5 w-80">
<template #header> Message </template>
<ElSpace>
<ElButton type="info" @click="info"> 信息 </ElButton>
<ElButton type="danger" @click="error"> 错误 </ElButton>
<ElButton type="warning" @click="warning"> 警告 </ElButton>
<ElButton type="success" @click="success"> 成功 </ElButton>
</ElSpace>
</ElCard>
<ElCard class="mb-5 w-80">
<template #header> Notification </template>
<ElSpace>
<ElButton type="info" @click="notify('info')"> 信息 </ElButton>
<ElButton type="danger" @click="notify('error')"> 错误 </ElButton>
<ElButton type="warning" @click="notify('warning')"> 警告 </ElButton>
<ElButton type="success" @click="notify('success')"> 成功 </ElButton>
</ElSpace>
</ElCard>
<ElCard class="mb-5 w-auto">
<template #header> Segmented </template>
<ElSegmented
v-model="segmentedValue"
:options="segmentedOptions"
size="large"
/>
</ElCard>
<ElCard class="mb-5 w-80">
<template #header> V-Loading </template>
<div class="flex size-72 items-center justify-center" v-loading="true">
一些演示的内容
</div>
</ElCard>
<ElCard class="mb-5 w-80">
<ElTable :data="tableData" stripe>
<ElTable.TableColumn label="测试列1" prop="prop1" />
<ElTable.TableColumn label="测试列2" prop="prop2" />
</ElTable>
</ElCard>
</div>
</Page>
</template>
-191
View File
@@ -1,191 +0,0 @@
<script lang="ts" setup>
import { h } from 'vue';
import { Page, useVbenDrawer } from '@vben/common-ui';
import { ElButton, ElCard, ElCheckbox, ElMessage } from 'element-plus';
import { useVbenForm } from '#/adapter/form';
import { getAllMenusApi } from '#/api';
const [Form, formApi] = useVbenForm({
commonConfig: {
// 所有表单项
componentProps: {
class: 'w-full',
},
},
layout: 'horizontal',
// 大屏一行显示3个,中屏一行显示2个,小屏一行显示1个
// wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',
handleSubmit: (values) => {
ElMessage.success(`表单数据:${JSON.stringify(values)}`);
},
schema: [
{
component: 'IconPicker',
fieldName: 'icon',
label: 'IconPicker',
},
{
// 组件需要在 #/adapter.ts内注册,并加上类型
component: 'ApiSelect',
// 对应组件的参数
componentProps: {
// 菜单接口转options格式
afterFetch: (data: { name: string; path: string }[]) => {
return data.map((item: any) => ({
label: item.name,
value: item.path,
}));
},
// 菜单接口
api: getAllMenusApi,
},
// 字段名
fieldName: 'api',
// 界面显示的label
label: 'ApiSelect',
},
{
component: 'ApiTreeSelect',
// 对应组件的参数
componentProps: {
// 菜单接口
api: getAllMenusApi,
childrenField: 'children',
// 菜单接口转options格式
labelField: 'name',
valueField: 'path',
},
// 字段名
fieldName: 'apiTree',
// 界面显示的label
label: 'ApiTreeSelect',
},
{
component: 'Input',
fieldName: 'string',
label: 'String',
},
{
component: 'InputNumber',
fieldName: 'number',
label: 'Number',
},
{
component: 'RadioGroup',
fieldName: 'radio',
label: 'Radio',
componentProps: {
options: [
{ value: 'A', label: 'A' },
{ value: 'B', label: 'B' },
{ value: 'C', label: 'C' },
{ value: 'D', label: 'D' },
{ value: 'E', label: 'E' },
],
},
},
{
component: 'RadioGroup',
fieldName: 'radioButton',
label: 'RadioButton',
componentProps: {
isButton: true,
options: ['A', 'B', 'C', 'D', 'E', 'F'].map((v) => ({
value: v,
label: `选项${v}`,
})),
},
},
{
component: 'CheckboxGroup',
fieldName: 'checkbox',
label: 'Checkbox',
componentProps: {
options: ['A', 'B', 'C'].map((v) => ({ value: v, label: `选项${v}` })),
},
},
{
component: 'CheckboxGroup',
fieldName: 'checkbox1',
label: 'Checkbox1',
renderComponentContent: () => {
return {
default: () => {
return ['A', 'B', 'C', 'D'].map((v) =>
h(ElCheckbox, { label: v, value: v }),
);
},
};
},
},
{
component: 'CheckboxGroup',
fieldName: 'checkbotton',
label: 'CheckBotton',
componentProps: {
isButton: true,
options: [
{ value: 'A', label: '选项A' },
{ value: 'B', label: '选项B' },
{ value: 'C', label: '选项C' },
],
},
},
{
component: 'DatePicker',
fieldName: 'date',
label: 'Date',
},
{
component: 'Select',
fieldName: 'select',
label: 'Select',
componentProps: {
filterable: true,
options: [
{ value: 'A', label: '选项A' },
{ value: 'B', label: '选项B' },
{ value: 'C', label: '选项C' },
],
},
},
],
});
const [Drawer, drawerApi] = useVbenDrawer();
function setFormValues() {
formApi.setValues({
string: 'string',
number: 123,
radio: 'B',
radioButton: 'C',
checkbox: ['A', 'C'],
checkbotton: ['B', 'C'],
checkbox1: ['A', 'B'],
date: new Date(),
select: 'B',
});
}
</script>
<template>
<Page
description="我们重新包装了CheckboxGroup、RadioGroup、Select,可以通过options属性传入选项属性数组以自动生成选项"
title="表单演示"
>
<Drawer class="w-[600px]" title="基础表单示例">
<Form />
</Drawer>
<ElCard>
<template #header>
<div class="flex items-center">
<span class="flex-auto">基础表单演示</span>
<ElButton type="primary" @click="setFormValues">设置表单值</ElButton>
</div>
</template>
<ElButton type="primary" @click="drawerApi.open"> 打开抽屉 </ElButton>
</ElCard>
</Page>
</template>
@@ -41,17 +41,17 @@ const save = async () => {
<template #default>
<el-form ref="formRef" :model="form" label-width="100px" class="zform">
<el-form-item label="上级部门">
<el-tree-select v-model="form.pid" :data="rdata.depts" :props="{ value: 'id', label: 'name' } as any" value-key="id" placeholder="选择上级部门" check-strictly />
<el-tree-select v-model="form.pid" clearable :data="rdata.depts" :props="{ value: 'id', label: 'name' } as any" value-key="id" placeholder="选择上级部门" check-strictly />
</el-form-item>
<el-form-item label="部门名称" prop="name" :rules="[{ required: true, message: '部门名称不能为空' }]">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="部门类型" style="width: 50%" prop="type" :rules="[{ required: true, message: '部门类型不能为空' }]">
<el-select v-model="form.type">
<el-option :value="1" label="集团" />
<el-option :value="2" label="公司" />
<el-option :value="4" label="机构" />
<el-option :value="8" label="部门" />
<el-option :value="1" label="部门" />
<el-option :value="2" label="机构" />
<el-option :value="4" label="公司" />
<el-option :value="8" label="集团" />
</el-select>
</el-form-item>
<el-form-item label="部门标签" prop="label" style="width: 50%">
@@ -52,7 +52,7 @@ const save = async () => {
<el-dialog v-model="state.show" title="部门编辑" draggable width="600px">
<el-form ref="formRef" :model="form" label-width="140px">
<el-form-item label="上级分类">
<el-tree-select v-model="form.pid" :data="rdata.cates" :props="{ value: 'id', label: 'name' } as any" value-key="id" placeholder="选择上级分类" check-strictly />
<el-tree-select v-model="form.pid" clearable :data="rdata.cates" :props="{ value: 'id', label: 'name' } as any" value-key="id" placeholder="选择上级分类" check-strictly />
</el-form-item>
<el-form-item label="分类名称" prop="name" :rules="[{ required: true, message: '分类名称不能为空' }]">
<el-input v-model="form.name" />
@@ -72,7 +72,7 @@ const editClose = async () => {
<span class="link_span" @click="editRef.open({ id: scope.row.id })">{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column label="所属分类" align="center" prop="name" width="180" />
<el-table-column label="所属分类" align="center" prop="catna" width="180" />
<el-table-column label="创建时间" align="center" prop="crtim" width="164" />
<el-table-column label="更新时间" align="center" prop="uptim" width="164" />
<el-table-column label="备注" align="center" prop="notes" />
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { Page, VbenAvatar } from "@vben/common-ui";
import { Page } from '@vben/common-ui';
import { Pane, Splitpanes } from 'splitpanes';
@@ -84,6 +84,7 @@ const editOpen = (data: any) => {
};
const handleStatusChange = async (row: any) => {
row.avtag = !(row.avtag === true || row.avtag === 1 || row.avtag === '1');
const text = row.avtag ? '启用' : '停用';
ElMessageBox.confirm(`确认要"${text}""${row.name}"用户吗?`, '提示')
.then(async () => {
@@ -98,11 +99,15 @@ const handleStatusChange = async (row: any) => {
ElMessage.info('已取消');
});
};
const isActive = (value: any) => {
return value === true || value === 1 || value === '1';
};
</script>
<template>
<Page auto-content-height>
<Splitpanes class="default-theme" v-show='state.pageShow'>
<Splitpanes class="default-theme" v-show="state.pageShow">
<Pane :size="state.leftPaneSize">
<DeptTree @node-click="nodeClick" url="/sys/org/dept/tree" tip="部门名称" :expand="true" />
</Pane>
@@ -111,7 +116,7 @@ const handleStatusChange = async (row: any) => {
<template #header>
<div class="flex justify-between">
<el-space>
<!-- <VbenAvatar alt="测试" src="http://localhost:5666/api/tool/oss/main/show?id=1977195329891160064" class="size-8" dot />-->
<!-- <VbenAvatar alt="测试" src="http://localhost:5666/api/tool/oss/main/show?id=1977195329891160064" class="size-8" dot />-->
<el-input style="width: 180px" v-model="state.form.name" placeholder="输入用户名称回车查询" clearable @keyup.enter="listQuery(state)" />
<el-button type="primary" @click="listQuery(state)" icon="Search"> 查询</el-button>
<el-button class="more-button" :icon="moreParams ? 'ArrowUp' : 'ArrowDown'" plain @click="moreParams = !moreParams" />
@@ -161,7 +166,7 @@ const handleStatusChange = async (row: any) => {
<el-table-column label="手机号码" align="center" prop="monum" width="120" />
<el-table-column label="状态" align="center" width="82">
<template #default="scope">
<el-switch v-model="scope.row.avtag" @change="handleStatusChange(scope.row)" v-if="scope.row.id !== 'u1'" />
<el-switch :model-value="isActive(scope.row.avtag)" :active-value="true" :inactive-value="false" @click="handleStatusChange(scope.row)" v-if="scope.row.id !== 'u1'" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="crtim" width="164">
+4 -11
View File
@@ -19,21 +19,14 @@ const { form } = toRefs(state);
const open = async (data: any) => {
if (data && data.id) {
state.form = await requestClient.get(`${state.url}/info/${data.id}`);
if (state.form.pid === 0) {
state.form.pid = undefined;
}
rdata.menus = await requestClient.get(`${state.url}/tree?id=${data.id}`);
for (let i = 0; i < rdata.menus.length; i++) {
if (rdata.menus[i].pid === data.id) {
rdata.menus.splice(i, 1);
break;
}
}
} else {
state.form = { avtag: true, shtag: true, catag: false, outag: false };
state.form.pid = data && data.pid ? data.pid : null;
state.form = { avtag: true, pid: data.pid, shtag: true, catag: false, outag: false };
rdata.menus = await requestClient.get(`${state.url}/tree`);
}
if (state.form.pid === 0 || state.form.pid === '0' || state.form.pid === undefined) {
delete state.form.pid;
}
state.show = true;
formRef?.value?.clearValidate();
};
+10 -57
View File
@@ -13,19 +13,8 @@ const state = reactive({
});
const columns = [
{
key: 'id',
dataKey: 'id',
title: 'ID',
width: 120,
hidden: true,
},
{
key: 'name',
dataKey: 'name',
title: '菜单名称',
width: 180,
},
{ key: 'id', dataKey: 'id', title: 'ID', width: 120, hidden: true },
{ key: 'name', dataKey: 'name', title: '菜单名称', width: 180 },
{
align: 'center',
key: 'icon',
@@ -45,49 +34,13 @@ const columns = [
</>
),
},
{
key: 'pid',
dataKey: 'pid',
title: '父ID',
width: 100,
hidden: true,
},
{
key: 'ornum',
dataKey: 'ornum',
title: '排序',
width: 50,
},
{
key: 'crtim',
dataKey: 'crtim',
title: '创建时间',
width: 180,
},
{
key: 'cruna',
dataKey: 'cruna',
title: '创建人',
width: 100,
},
{
key: 'uptim',
dataKey: 'uptim',
title: '更新时间',
width: 180,
},
{
key: 'upuna',
dataKey: 'upuna',
title: '更新人',
width: 100,
},
{
key: 'notes',
dataKey: 'notes',
title: '备注',
width: 150,
},
{ key: 'pid', dataKey: 'pid', title: '父ID', width: 100, hidden: true },
{ key: 'ornum', dataKey: 'ornum', title: '排序', width: 50 },
{ key: 'crtim', dataKey: 'crtim', title: '创建时间', width: 180 },
{ key: 'cruna', dataKey: 'cruna', title: '创建人', width: 100 },
{ key: 'uptim', dataKey: 'uptim', title: '更新时间', width: 180 },
{ key: 'upuna', dataKey: 'upuna', title: '更新人', width: 100 },
{ key: 'notes', dataKey: 'notes', title: '备注', width: 150 },
{
align: 'center',
key: 'operate',
@@ -131,7 +84,7 @@ const editClose = async () => {
<el-button type="primary" icon="Search" @click="treeQuery(state)">查询</el-button>
</el-space>
<el-space>
<el-button icon="Plus" type="success" plain @click="editRef.open()">新增</el-button>
<el-button icon="Plus" type="success" plain @click="editRef.open({})">新增</el-button>
</el-space>
</div>
</template>
+25 -10
View File
@@ -25,11 +25,7 @@ const treeProps = reactive({
onMounted(async () => {
const id = useRoute().query?.id;
if (id) {
state.form = await requestClient.get(`${state.url}/info/${id}`);
} else {
state.form = { avtag: true };
}
state.form = id ? await requestClient.get(`${state.url}/info/${id}`) : { avtag: true, type: 1 };
formRef?.value?.clearValidate();
const perms = await requestClient.get(`/sys/perm/role/perms`);
rdata.perms = handleTree(perms);
@@ -68,7 +64,7 @@ const orgModal = ref();
const openOrgsModal = () => {
orgModal.value.open({
orgType: 31,
orgType: 15,
selectMode: 2,
orgs: toRaw(form.value.orgs),
});
@@ -115,21 +111,40 @@ const orgsName = computed(() => {
<el-form-item label="是否可用:" style="width: 25%">
<el-switch v-model="form.avtag" />
</el-form-item>
<el-form-item label="权限成员:">
<el-form-item label="包含成员:">
<el-input type="textarea" placeholder="这里可以选择用户,部门,岗位,群组。权限都会生效" :rows="4" v-model="orgsName" readonly @click="openOrgsModal" />
</el-form-item>
<el-form-item label="角色类型:" style="width: 50%">
<el-select v-model="form.type">
<el-option :value="1" label="综合角色" />
<el-option :value="2" label="数据权限角色" />
<el-option :value="3" label="菜单角色" />
<el-option :value="4" label="接口角色" />
<el-option :value="5" label="菜单与接口角色" />
</el-select>
</el-form-item>
<el-form-item label="数据权限:" style="width: 50%">
<el-select v-model="form.scope" clearable>
<el-option :value="1" label="全部数据权限" />
<el-option :value="2" label="自定数据权限" />
<el-option :value="3" label="本部门数据权限" />
<el-option :value="4" label="本部门及以下数据权限" />
<el-option :value="5" label="仅本人数据权限" />
<el-option :value="6" label="部门及以下或本人数据权限" />
</el-select>
</el-form-item>
<el-form-item label="备注:" style="width: 100%">
<el-input style="font-family: 'Courier New', Helvetica, Arial, sans-serif; font-size: 16px" type="textarea" :rows="3" v-model="form.notes" />
</el-form-item>
<div v-show="form.crtim">
<el-form-item label="创建人:" style="width: 50%">
<div class="zinput">{{ form.crman ? form.crman.name : '' }}</div>
<div class="zinput">{{ form.cruna }}</div>
</el-form-item>
<el-form-item label="创建时间:" style="width: 50%">
<div class="zinput">{{ form.crtim }}</div>
</el-form-item>
<el-form-item label="更新人:" style="width: 50%">
<div class="zinput">{{ form.upman ? form.upman.name : '' }}</div>
<div class="zinput">{{ form.upuna }}</div>
</el-form-item>
<el-form-item label="更新时间:" style="width: 50%">
<div class="zinput">{{ form.uptim }}</div>
@@ -142,7 +157,7 @@ const orgsName = computed(() => {
<el-table-column prop="name" label="菜单名称" width="160" />
<el-table-column label="图标" prop="icon" width="55" align="center">
<template #default="scope">
<div style="display: flex; justify-content: center; align-items: center;">
<div style="display: flex; justify-content: center; align-items: center">
<VbenIcon :icon="scope.row.icon" />
</div>
</template>
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { Page } from '@vben/common-ui';
import { requestClient } from "#/api/request";
import { requestClient } from '#/api/request';
import { listDelete, listItemDelete, listQuery, listSelect } from '#/utils/page/list';
const state = reactive({
@@ -47,7 +47,7 @@ onMounted(async () => {
</el-space>
<el-space>
<el-button icon="Plus" type="success" plain @click="handleAdd">新增</el-button>
<el-button icon="Refresh" type="warning" plain @click="refreshCache">更新缓存</el-button>
<el-button icon="Refresh" type="warning" plain @click="refreshCache">刷新缓存</el-button>
<el-button icon="Delete" type="danger" plain @click="listDelete(state)" :disabled="state.multiple">删除</el-button>
</el-space>
</div>
+1 -1
View File
@@ -6,6 +6,7 @@
export {}
declare global {
const EffectScope: typeof import('vue')['EffectScope']
const ElLoading: typeof import('element-plus/es')['ElLoading']
const ElMessage: typeof import('element-plus/es')['ElMessage']
const ElMessageBox: typeof import('element-plus/es')['ElMessageBox']
const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
@@ -321,7 +322,6 @@ declare module 'vue' {
interface ComponentCustomProperties {
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
readonly ElMessage: UnwrapRef<typeof import('element-plus/es')['ElMessage']>
readonly ElMessageBox: UnwrapRef<typeof import('element-plus/es')['ElMessageBox']>
readonly acceptHMRUpdate: UnwrapRef<typeof import('pinia')['acceptHMRUpdate']>
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']>
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']>
+1
View File
@@ -27,6 +27,7 @@
"scripts": {
"build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 turbo build",
"build:analyze": "turbo build:analyze",
"build:ele": "pnpm run build --filter=@vben/web-ele build:prod",
"build:antd": "pnpm run build --filter=@vben/web-antd build:prod",
"build:antd:test": "pnpm run build --filter=@vben/web-antd build:test",
"build:docker": "./scripts/deploy/build-local-docker-image.sh",