!11 follow后端发布

* docs: readme
* fix: missing formPath
* chore: 去除锁定的esbuild版本
* perf: 去除debug组件
* perf: 参数键值 自动高度
* refactor: 代码生成配置页面重构 去除步骤条
* perf: 移除文件
* docs: 文件夹说明
* chore: 移除一些配置项
* chore: 注释优化
* refactor: 移除ele和naive目录
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* perf: request support to set how to return response (#5436)
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* refactor: 登录超时的i18n
* fix: requestClient缺失i18n内容
* refactor: 优化oss下载进度提示
* feat: 下载进度loading
* fix: antd button icon style (#5421)
* feat: oss下载进度(已下载的KB 无法作为进度显示 total返回为null)
* fix: 下载文件时(responseType === 'blob')需要判断下载失败(返回json而非二进制)的情况
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* refactor: 新增后跳转到未发布流程
* fix: same name route
* chore: 调整为部署json类型
* fix: mouse events ignored on modal loading (#5409)
* docs: update docs (#5408)
* refactor: 移除已经弃用的方法
* refactor: follow官方handleRangeTimeValue更新
* chore: 删除文件夹(前端路由需要的)
* chore: 修改本地路由写法(新版)/新增本地菜单图标
* fix: form update state error before form mounted (#5406)
* fix: demos route fixed (#5405)
* chore: 不使用基础布局(仅在顶级生效)
* feat: modal state locked on submitting (#5401)
* chore: 修改zIndex
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* refactor: fix popup component zIndex (#5397)
* style: element plus loading style fixed (#5393)
* perf: improve fieldMappingTime to support format function (#5392)
* fix: hide root route in breadcrumb
* feat: support set default props for drawer and modal (#5390)
* fix: root router config fixed (#5389)
* fix: 修改Vxe默认zIndex为995 解决右上角全屏后modal/drawer(zIndex: 1000)被遮挡
* feat: add `noBasicLayout` in route meta (#5386)
* chore: wechat image
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* chore: 改为全局参数配置 去除局部参数
* fix: spinner may stop playing animation after dismiss (#5365)
* style: popover bgColor is too close to common (#5364)
* docs: version update
* docs: changelog
* chore: 文件上传 描述
* ci: retry deploy while faild
* feat: 文件上传 进度条+提示文字
* feat: 文件上传 进度条
* feat: 上传文件格式说明
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into warmflow
* fix: useEcharts return invalid instance (#5360)
* feat: popup component support overlay blur effect (#5359)
* feat: improve `tippy` demo (#5357)
* feat: integrate new component `Tippy` with demo (#5355)
* chore: 优化表格图片显示
* perf: add nested modal demo (#5353)
* chore: 默认显示右边的滚动条 防止出现滚动条被挤压
* perf: modal and drawer api support chain calls (#5351)
* feat: allow close tab when mouse middle button click (#5347)
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into warmflow
* refactor: 重构显示total的逻辑
* chore: 调整高度自适应代码
* chore: vxe升级4.10.0版本(锁定)
* fix: 添加失效的option
* fix: 需要为数组
* fix: locale switching logic correction (#5344)
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into warmflow
* chore: 导入类型优化 解决eslint报红
* refactor: type/注释优化 去除大量any
* fix: vxeGrid init without search form (#5342)
* chore: 锁屏默认false  关闭该功能
* chore: 调整接口
* chore: update deps
* fix: primaryColor calculation (#5337)
* fix: form valid-error style in naive (#5336)
* fix: form `fieldMappingTime` improve and `modelPropName` support (#5335)
* fix: code lint
* fix: form `fieldMappingTime` is not working (#5333)
* chore: 选人组件样式
* fix: download from url triggered twice sometimes (#5319)
* chore: 优化代码
* chore: 动态类名(无效)改为style
* refactor: 字典相关功能重构 采用一个Map储存字典(之前为两个Map)
* feat: 字典支持number类型存储
* chore: 调整样式
* chore: 修改选中border为1px
* chore: 字段
* chore: 改为新窗口打开(适用于pdf/图片)而非直接下载
* chore: 更新样式
* chore: 更新字段
* chore: 改为computed
* chore: 跳转到未发布流程tab
* chore: 优化样式
* docs: readme
* fix: name重复导致的404
* Merge branch 'dev' of https://gitee.com/dapppp/ruoyi-plus-vben5 into warmflow
* chore: 使用legacy来保证copy的兼容性
* chore: 去除log 添加说明
* chore: 优化代码
* feat: 节点关联/节点独立的切换逻辑
* chore: remove logic
* chore: vxe可编辑表格demo
* chore: 不允许在按钮下添加数据
* docs: changelog
* fix: wrong code
* chore: 移除测试菜单
* chore: 优化代码
* refactor: 租户套餐菜单替换为新版
* refactor: 使用新版菜单勾选
* chore: 点行会勾选/取消全部权限  点权限不会勾选行
* chore: 全屏引导+样式优化
* chore: 调整间距
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* feat: useEcharts exports echarts instance#5294 (#5299)
* chore: update quick-start.md (#5303)
* chore: updateCheckedNumber
* refactor: 优化代码
* chore: 优化代码
* chore: 优化样式
* chore: keys依赖于menu 需要先加载menu
* chore: 菜单加载完毕再显示
* feat: 新的菜单选择组件(beta)
* chore: $t
* chore: 测试菜单页面
* chore: 优化代码
* feat: 对ossId回显的支持
* chore: 只获取一次默认密码而非每次打开modal都获取
* fix: vben select placeholder color (#5286)
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* perf: format code with better style (#5283)
* chore: 工作流演示站
* fix: sidebar preferences fixed (#5276)
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* fix: breadcrumb setting not valid for `header-sidebar-nav` layout (#5275)
* fix: header logo may not be collapsed in `header-sidebar-nav` layout (#5274)
* feat: new layout `sidebar nav with full header` (#5270)
* feat: drawer close icon placement (#5269)
* docs: update dialog and drawer docs
* feat: drawer support destroy on close
* feat: drawer support `onOpened` & `onClosed`
* feat: modal support destroy on close
* fix: wrong boolean
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* chore: 调整tab位置
* chore: 删除历史流程 改为tab切换
* fix: header-mixed layout side-menu active (#5265)
* feat: header mixed layout (#5263)
* chore: release 5.5.2
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* chore: downgrade vue-tsc version
* feat: header menu align support (#5256)
* chore: update deps
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* chore: add apiSelect remote search demo (#5246)
* chore: 审批改为description而非disabled的表单
* chore: 改为ts
* chore: 错误的conetnt
* refactor: 终止/转办/委托支持填写意见
* chore: 第一次拿到的是readonly的数据 如果需要修改 需要cloneDeep
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* fix: grid form submit button locale switch (#5205)
* chore: 调整驳回
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* fix: build error (#5199)
* fix: esbuild自动升级导致运行/打包报错
* fix: esbuild自动升级导致运行/打包报错
* chore: 流程定义 激活改为switch
* chore: 流程申请支持上传文件
* chore: title 审批通过
* fix: vxeGrid top padding (#5193)
* fix: 表格排序翻页会丢失排序参数
* chore: 去除log打印
* chore: 流程监控 待办任务
* chore: 我发起的
* chore: 去除已经移除的菜单页面
* chore: 我的已办
* chore: 页面优化
* chore: 重置tooltip
* feat: 我的抄送搜索/优化重复触发的接口
* feat: 流程定义 历史
* chore: 修改分类
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* fix: grid tools in toolbar config not working as expected (#5190)
* feat: add `resizable` and `ColPage` component (#5188)
* chore: 条件
* chore: break-all
* feat: 流程分类 搜索
* chore: 弹窗关闭后仍然显示表单浮层
* chore: 选人组件的样式
* chore: 搜索的样式
* chore: 漏掉的导入
* chore: 最大显示的头像数量 超过显示为省略号头像
* fix: 选人的一些问题
* Merge branch 'warmflow' of https://gitee.com/dapppp/ruoyi-plus-vben5 i…
* chore: 没有更多数据了
* fix: sidebar header height (#5183)
* chore: 搜索表单布局+申请人
* fix: remove the overlap caused by border-b (#5160)
* docs: fix typos (#5169)
* fix: resolve eslint errors as well as TS type errors (#5172)
* chore: enter提交表单
* chore: 修改文案
* chore: 默认全部展开
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* feat: page content class override (#5179)
* fix: sidebar style on focus (#5178)
* fix: 抄送选人 最右侧已选中删除item无效
* feat: 复制
* chore: 昵称过长的显示
* chore: 默认选中第一个
* chore: 修改relative位置
* chore: 搜索
* feat: 我的待办 - 搜索条件
* chore: 流程监控 - 待办任务页面的id不唯一 改为前端处理
* feat: 修改办理人
* chore: 流程干预 - 加签/减签
* chore: avatar大小
* chore: 抄送需要手动添加createByName
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* chore: 审批通过 抄送
* feat: 流程实例-流程预览
* chore: spell
* chore: clientid
* chore: 分类条件
* chore: 修改办理人
* chore: 更改postMessage参数
* chore: 内嵌iframe高度根据表单高度调整
* chore: 流程详情
* feat: 抄送选择
* chore: 调整分类树
* fix: user homePath no effect sometimes (#5166)
* feat: form compact mode support (#5165)
* fix: form auto submit no effect when showDefaultActions is false (#5163)
* chore: 修改width
* feat: 待办任务
* feat: 我的抄送
* chore: 流程定义 样式
* chore: 退回后重新申请
* chore: 请假申请布局
* chore: 请假申请-并行会签网关
* chore: 分类去除根目录
* chore: 详情modal(未完成)
* chore: 请假申请根据不同状态显示按钮
* chore: 流程删除/撤销
* chore: 审批完成后刷新当前页
* feat: 选人组件(未完成) 加签减签
* docs: fix docs-link and add `EllipsisText` docs (#5158)
* chore: 新窗口打开文件
* chore: 审批通过
* chore: 使用useEventListener替换原生
* chore: 字段错误
* chore: iframe通信 加载完毕后才显示表单 解决卡顿问题
* chore: 审批终止/驳回
* chore: 附件图标
* chore: process_running显示按钮
* chore: label错误
* chore: 保存的事件
* chore: 需要加上clientId
* Merge branch 'main' of https://github.com/vbenjs/vue-vben-admin into dev
* feat: form `colon` support (#5156)
* chore: 完善请假申请
* feat: improve code login demo (#5154)
* chore: 客户端管理 行高自适应
* chore: 内嵌表单的路径
* chore: 修改avatar背景色
* chore: 注释
* chore: activePath
* chore: leave表单
* chore: 修改请假demo路径
* chore: categoryId
* chore: 我的已办
* chore: 我发起的
* chore: loading
* chore: 历史版本
* chore: 完善task api
* chore: 隐藏'菜单加载中'
* chore: missing import
* feat: add demo for modify menu badge data
* chore: 流程实例
* chore: 审批附件
* chore: 我的待办 提取公共组件
* chore: 流程部署
* chore: 新增/编辑/导出xml
* chore: 流程定义(除历史版本)
* feat: `autoActivateChild` support more layout mode (#5148)
* feat: auto activate subMenu on select root menu (#5147)
* fix: `disabledOnChangeListener` not work in form (#5146)
* fix: login expired modal z-index (#5145)
* feat: user-dropdown support `hover` trigger (#5143)
* fix: pinInput value synchronous update (#5142)
* fix: vxeGrid default sort data no effect in first query (#5141)
* fix: vscode debug profile (#5140)
* fix: form component events bind (#5137)
* chore: 在线用户样式 开启虚拟滚动
* chore: 去掉个人中心 在线设备的分页
* chore: 去掉在线用户的分页
* chore: changelog
* refactor: 获取字典的方法 提取公共函数 减少冗余代码
* fix: element plus validate failed style (#5130)
* chore: 使用私有桶的提示
* feat: tabbar support mouse wheel vertical (#5129)
* fix: form support `disabledOnInputListener` (#5127)
* fix: form submission not appropriate (#5126)
* Merge branch 'main' of https://gitee.com/dapppp/ruoyi-plus-vben5 into dev
* chore: release 5.5.1
* feat: table search form visible control (#5121)
* chore: 需要隐藏菜单
* chore: 我的待办 & 请假
* chore: 流程定义(未完成)
* chore: 流程定义(开发中)
* Merge branch 'main' of https://gitee.com/dapppp/ruoyi-plus-vben5 into dev
* Merge branch 'main' of https://gitee.com/dapppp/ruoyi-plus-vben5 into dev
* Merge branch 'main' of https://gitee.com/dapppp/ruoyi-plus-vben5 into dev
* chore: version
* chore: 锁定vxe-table版本 4.9.8版本存在样式问题
* chore: 暂时锁定cspell版本
* refactor: 由于不能输入 需要使用watch监听
* chore: https://gitee.com/dapppp/ruoyi-plus-vben5/issues/IB7ANL
* chore: 移除冗余代码
* chore: 组件卸载时移除emitter
* fix: the route path did not synchronize with the page (#4947)
* style: typo (#4948)
* chore: 替换为commonDownloadExcel
* fix: 左边部门树错误emit导致会调用两次列表api
* chore: label样式
* chore: 改为Textarea
* chore: 滚动条宽度
* chore: 审批样式
* chore: 部门及以下或本人数据权限
* Merge branch 'main' of https://gitee.com/dapppp/ruoyi-plus-vben5 into dev
* chore: 个人中心强退设备接口路径
This commit is contained in:
玲娜贝er
2025-01-20 03:43:19 +00:00
parent 8ab0bd2212
commit 29f9f3de31
729 changed files with 12839 additions and 9132 deletions

View File

@@ -1,10 +1,10 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { DictEnum } from '@vben/constants';
import { getPopupContainer } from '@vben/utils';
import { type FormSchemaGetter } from '#/adapter/form';
import { getDict, getDictOptions } from '#/utils/dict';
import { getDictOptions } from '#/utils/dict';
import { renderDict, renderDictTags } from '#/utils/render';
export const querySchema: FormSchemaGetter = () => [
@@ -53,7 +53,9 @@ export const columns: VxeGridProps['columns'] = [
}
return renderDictTags(
row.grantTypeList,
getDict(DictEnum.SYS_GRANT_TYPE),
getDictOptions(DictEnum.SYS_GRANT_TYPE),
true,
4,
);
},
},

View File

@@ -1,17 +1,16 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { Client } from '#/api/system/client/model';
import { useAccess } from '@vben/access';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { Page, useVbenDrawer } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import {
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps,
} from '#/adapter/vxe-table';
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
import {
clientChangeStatus,
clientExport,
@@ -43,7 +42,7 @@ const gridOptions: VxeGridProps = {
reserve: true,
// 点击行选中
// trigger: 'row',
checkMethod: (row: any) => row?.id !== 1,
checkMethod: ({ row }) => (row as Client)?.id !== 1,
},
columns,
height: 'auto',
@@ -61,11 +60,10 @@ const gridOptions: VxeGridProps = {
},
},
rowConfig: {
isHover: true,
keyField: 'id',
height: 90,
},
id: 'system-client-index',
showOverflow: false,
};
const [BasicTable, tableApi] = useVbenVxeGrid({
@@ -82,19 +80,19 @@ function handleAdd() {
drawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
async function handleEdit(record: Client) {
drawerApi.setData({ id: record.id });
drawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
await clientRemove(row.id);
async function handleDelete(row: Client) {
await clientRemove([row.id]);
await tableApi.query();
}
function handleMultiDelete() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: any) => row.id);
const ids = rows.map((row: Client) => row.id);
Modal.confirm({
title: '提示',
okType: 'danger',

View File

@@ -1,9 +1,9 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { DictEnum } from '@vben/constants';
import { getPopupContainer } from '@vben/utils';
import { type FormSchemaGetter } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';
@@ -102,6 +102,9 @@ export const modalSchema: FormSchemaGetter = () => [
formItemClass: 'items-baseline',
fieldName: 'configValue',
label: '参数键值',
componentProps: {
autosize: true,
},
rules: 'required',
},
{

View File

@@ -1,16 +1,15 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { VbenFormProps } from '@vben/common-ui';
import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { SysConfig } from '#/api/system/config/model';
import { Page, useVbenModal } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import {
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps,
} from '#/adapter/vxe-table';
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
import {
configExport,
configList,
@@ -64,7 +63,6 @@ const gridOptions: VxeGridProps = {
},
},
rowConfig: {
isHover: true,
keyField: 'configId',
},
id: 'system-config-index',
@@ -83,19 +81,19 @@ function handleAdd() {
modalApi.open();
}
async function handleEdit(record: Recordable<any>) {
async function handleEdit(record: SysConfig) {
modalApi.setData({ id: record.configId });
modalApi.open();
}
async function handleDelete(row: Recordable<any>) {
await configRemove(row.configId);
async function handleDelete(row: SysConfig) {
await configRemove([row.configId]);
await tableApi.query();
}
function handleMultiDelete() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: any) => row.configId);
const ids = rows.map((row: SysConfig) => row.configId);
Modal.confirm({
title: '提示',
okType: 'danger',

View File

@@ -1,9 +1,10 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { DictEnum } from '@vben/constants';
import { getPopupContainer } from '@vben/utils';
import { type FormSchemaGetter, z } from '#/adapter/form';
import { z } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';

View File

@@ -1,4 +1,6 @@
<script setup lang="ts">
import type { Dept } from '#/api/system/dept/model';
import { computed, ref } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
@@ -43,7 +45,7 @@ const [BasicForm, formApi] = useVbenForm({
});
async function getDeptTree(deptId?: number | string, exclude = false) {
let ret: any[] = [];
let ret: Dept[] = [];
ret = await (!deptId || exclude ? deptList({}) : deptNodeList(deptId));
const treeData = listToTree(ret, { id: 'deptId', pid: 'parentId' });
// 添加部门名称 如 xx-xx-xx

View File

@@ -1,14 +1,17 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { Dept } from '#/api/system/dept/model';
import { nextTick } from 'vue';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { Page, useVbenDrawer } from '@vben/common-ui';
import { eachTree, getVxePopupContainer } from '@vben/utils';
import { Popconfirm, Space } from 'ant-design-vue';
import { useVbenVxeGrid, type VxeGridProps } from '#/adapter/vxe-table';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { deptList, deptRemove } from '#/api/system/dept';
import { columns, querySchema } from './data';
@@ -59,7 +62,6 @@ const gridOptions: VxeGridProps = {
gt: 0,
},
rowConfig: {
isHover: true,
keyField: 'deptId',
},
treeConfig: {
@@ -74,7 +76,7 @@ const [BasicTable, tableApi] = useVbenVxeGrid({
formOptions,
gridOptions,
gridEvents: {
cellDblclick: (e: any) => {
cellDblclick: (e) => {
const { row = {} } = e;
if (!row?.children) {
return;
@@ -84,7 +86,7 @@ const [BasicTable, tableApi] = useVbenVxeGrid({
row.expand = !isExpanded;
},
// 需要监听使用箭头展开的情况 否则展开/折叠的数据不一致
toggleTreeExpand: (e: any) => {
toggleTreeExpand: (e) => {
const { row = {}, expanded } = e;
row.expand = expanded;
},
@@ -99,18 +101,18 @@ function handleAdd() {
drawerApi.open();
}
function handleSubAdd(row: Recordable<any>) {
function handleSubAdd(row: Dept) {
const { deptId } = row;
drawerApi.setData({ id: deptId, update: false });
drawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
async function handleEdit(record: Dept) {
drawerApi.setData({ id: record.deptId, update: true });
drawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
async function handleDelete(row: Dept) {
await deptRemove(row.deptId);
await tableApi.query();
}

View File

@@ -1,6 +1,7 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { DictData } from '#/api/system/dict/dict-data-model';
import { type FormSchemaGetter } from '#/adapter/form';
import { renderDictTag } from '#/utils/render';
export const querySchema: FormSchemaGetter = () => [
@@ -18,8 +19,8 @@ export const columns: VxeGridProps['columns'] = [
field: 'cssClass',
slots: {
default: ({ row }) => {
const { dictValue } = row;
return renderDictTag(dictValue, [row as any]);
const { dictValue } = row as DictData;
return renderDictTag(dictValue, [row]);
},
},
},

View File

@@ -1,18 +1,18 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { PageQuery } from '#/api/common';
import type { DictData } from '#/api/system/dict/dict-data-model';
import { ref } from 'vue';
import { useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { useVbenDrawer } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import {
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps,
} from '#/adapter/vxe-table';
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
import {
dictDataExport,
dictDataList,
@@ -53,7 +53,7 @@ const gridOptions: VxeGridProps = {
proxyConfig: {
ajax: {
query: async ({ page }, formValues = {}) => {
const params: any = {
const params: PageQuery = {
pageNum: page.currentPage,
pageSize: page.pageSize,
...formValues,
@@ -67,7 +67,6 @@ const gridOptions: VxeGridProps = {
},
},
rowConfig: {
isHover: true,
keyField: 'dictCode',
},
id: 'system-dict-data-index',
@@ -87,7 +86,7 @@ function handleAdd() {
drawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
async function handleEdit(record: DictData) {
drawerApi.setData({
dictType: dictType.value,
dictCode: record.dictCode,
@@ -95,14 +94,14 @@ async function handleEdit(record: Recordable<any>) {
drawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
await dictDataRemove(row.dictCode);
async function handleDelete(row: DictData) {
await dictDataRemove([row.dictCode]);
await tableApi.query();
}
function handleMultiDelete() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: any) => row.dictCode);
const ids = rows.map((row: DictData) => row.dictCode);
Modal.confirm({
title: '提示',
okType: 'danger',

View File

@@ -1,12 +1,11 @@
<script setup lang="ts">
import { computed, type PropType } from 'vue';
import type { RadioChangeEvent } from 'ant-design-vue';
import {
Input,
type RadioChangeEvent,
RadioGroup,
Select,
} from 'ant-design-vue';
import type { PropType } from 'vue';
import { computed } from 'vue';
import { Input, RadioGroup, Select } from 'ant-design-vue';
import { tagSelectOptions } from '#/components/dict';

View File

@@ -1,6 +1,7 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { type FormSchemaGetter, z } from '#/adapter/form';
import { z } from '#/adapter/form';
export const querySchema: FormSchemaGetter = () => [
{

View File

@@ -1,18 +1,17 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { DictType } from '#/api/system/dict/dict-type-model';
import { ref } from 'vue';
import { useVbenModal, type VbenFormProps } from '@vben/common-ui';
import { useVbenModal } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import {
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps,
} from '#/adapter/vxe-table';
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
import {
dictTypeExport,
dictTypeList,
@@ -61,7 +60,6 @@ const gridOptions: VxeGridProps = {
},
},
rowConfig: {
isHover: true,
keyField: 'dictId',
},
id: 'system-dict-type-index',
@@ -73,7 +71,7 @@ const [BasicTable, tableApi] = useVbenVxeGrid({
formOptions,
gridOptions,
gridEvents: {
cellClick: (e: any) => {
cellClick: (e) => {
const { row } = e;
if (lastDictType.value === row.dictType) {
return;
@@ -92,19 +90,19 @@ function handleAdd() {
modalApi.open();
}
async function handleEdit(record: Recordable<any>) {
async function handleEdit(record: DictType) {
modalApi.setData({ id: record.dictId });
modalApi.open();
}
async function handleDelete(row: Recordable<any>) {
await dictTypeRemove(row.dictId);
async function handleDelete(row: DictType) {
await dictTypeRemove([row.dictId]);
await tableApi.query();
}
function handleMultiDelete() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: any) => row.dictId);
const ids = rows.map((row: DictType) => row.dictId);
Modal.confirm({
title: '提示',
okType: 'danger',

View File

@@ -1,3 +1,4 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { h } from 'vue';
@@ -7,7 +8,7 @@ import { FolderIcon, MenuIcon, OkButtonIcon, VbenIcon } from '@vben/icons';
import { $t } from '@vben/locales';
import { getPopupContainer } from '@vben/utils';
import { type FormSchemaGetter, z } from '#/adapter/form';
import { z } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';

View File

@@ -1,16 +1,18 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { Menu } from '#/api/system/menu/model';
import { computed } from 'vue';
import { useAccess } from '@vben/access';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { Fallback } from '@vben/common-ui';
import { Fallback, Page, useVbenDrawer } from '@vben/common-ui';
import { eachTree, getVxePopupContainer } from '@vben/utils';
import { Popconfirm, Space } from 'ant-design-vue';
import { useVbenVxeGrid, type VxeGridProps } from '#/adapter/vxe-table';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { menuList, menuRemove } from '#/api/system/menu';
import { columns, querySchema } from './data';
@@ -49,7 +51,6 @@ const gridOptions: VxeGridProps = {
},
},
rowConfig: {
isHover: true,
keyField: 'menuId',
},
/**
@@ -74,7 +75,7 @@ const [BasicTable, tableApi] = useVbenVxeGrid({
formOptions,
gridOptions,
gridEvents: {
cellDblclick: (e: any) => {
cellDblclick: (e) => {
const { row = {} } = e;
if (!row?.children) {
return;
@@ -84,7 +85,7 @@ const [BasicTable, tableApi] = useVbenVxeGrid({
row.expand = !isExpanded;
},
// 需要监听使用箭头展开的情况 否则展开/折叠的数据不一致
toggleTreeExpand: (e: any) => {
toggleTreeExpand: (e) => {
const { row = {}, expanded } = e;
row.expand = expanded;
},
@@ -99,19 +100,19 @@ function handleAdd() {
drawerApi.open();
}
function handleSubAdd(row: Recordable<any>) {
function handleSubAdd(row: Menu) {
const { menuId } = row;
drawerApi.setData({ id: menuId, update: false });
drawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
async function handleEdit(record: Menu) {
drawerApi.setData({ id: record.menuId, update: true });
drawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
await menuRemove(row.menuId);
async function handleDelete(row: Menu) {
await menuRemove([row.menuId]);
await tableApi.query();
}

View File

@@ -48,7 +48,12 @@ async function setupMenuSelect() {
item.menuName = $t(item.menuName);
});
// const folderArray = menuArray.filter((item) => item.menuType === 'M');
const menuTree = listToTree(menuArray, { id: 'menuId', pid: 'parentId' });
/**
* 这里需要过滤掉按钮类型
* 不允许在按钮下添加数据
*/
const filteredList = menuArray.filter((item) => item.menuType !== 'F');
const menuTree = listToTree(filteredList, { id: 'menuId', pid: 'parentId' });
const fullMenuTree = [
{
menuId: 0,

View File

@@ -1,9 +1,9 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { DictEnum } from '@vben/constants';
import { getPopupContainer } from '@vben/utils';
import { type FormSchemaGetter } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';

View File

@@ -1,16 +1,15 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { VbenFormProps } from '@vben/common-ui';
import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { Notice } from '#/api/system/notice/model';
import { Page, useVbenModal } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import {
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps,
} from '#/adapter/vxe-table';
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
import { noticeList, noticeRemove } from '#/api/system/notice';
import { columns, querySchema } from './data';
@@ -52,7 +51,6 @@ const gridOptions: VxeGridProps = {
},
},
rowConfig: {
isHover: true,
keyField: 'noticeId',
},
id: 'system-notice-index',
@@ -72,19 +70,19 @@ function handleAdd() {
modalApi.open();
}
async function handleEdit(record: Recordable<any>) {
async function handleEdit(record: Notice) {
modalApi.setData({ id: record.noticeId });
modalApi.open();
}
async function handleDelete(row: Recordable<any>) {
await noticeRemove(row.noticeId);
async function handleDelete(row: Notice) {
await noticeRemove([row.noticeId]);
await tableApi.query();
}
function handleMultiDelete() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: any) => row.noticeId);
const ids = rows.map((row: Notice) => row.noticeId);
Modal.confirm({
title: '提示',
okType: 'danger',

View File

@@ -1,10 +1,11 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { DictEnum } from '@vben/constants';
import { Tag } from 'ant-design-vue';
import { type FormSchemaGetter, z } from '#/adapter/form';
import { z } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
const accessPolicyOptions = [
@@ -128,6 +129,12 @@ export const drawerSchema: FormSchemaGetter = () => [
fieldName: 'domain',
label: '自定义域名',
},
{
component: 'Input',
fieldName: 'tip',
label: '占位作为提示使用',
hideLabel: true,
},
{
component: 'Divider',
componentProps: {

View File

@@ -1,17 +1,16 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { OssConfig } from '#/api/system/oss-config/model';
import { useAccess } from '@vben/access';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { Page, useVbenDrawer } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import {
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps,
} from '#/adapter/vxe-table';
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
import {
ossConfigChangeStatus,
ossConfigList,
@@ -58,7 +57,6 @@ const gridOptions: VxeGridProps = {
},
},
rowConfig: {
isHover: true,
keyField: 'ossConfigId',
},
id: 'system-oss-config-index',
@@ -78,19 +76,19 @@ function handleAdd() {
drawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
async function handleEdit(record: OssConfig) {
drawerApi.setData({ id: record.ossConfigId });
drawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
await ossConfigRemove(row.ossConfigId);
async function handleDelete(row: OssConfig) {
await ossConfigRemove([row.ossConfigId]);
await tableApi.query();
}
function handleMultiDelete() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: any) => row.ossConfigId);
const ids = rows.map((row: OssConfig) => row.ossConfigId);
Modal.confirm({
title: '提示',
okType: 'danger',

View File

@@ -5,6 +5,8 @@ import { useVbenDrawer } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { cloneDeep } from '@vben/utils';
import { Alert } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import {
ossConfigAdd,
@@ -79,7 +81,17 @@ async function handleCancel() {
<template>
<BasicDrawer :close-on-click-modal="false" :title="title" class="w-[650px]">
<BasicForm />
<BasicForm>
<template #tip>
<div class="ml-7 w-full">
<Alert
message="私有桶使用自定义域名无法预览, 但可以正常上传/下载"
show-icon
type="warning"
/>
</div>
</template>
</BasicForm>
</BasicDrawer>
</template>

View File

@@ -1,7 +1,6 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { type FormSchemaGetter } from '#/adapter/form';
export const querySchema: FormSchemaGetter = () => [
{
component: 'Input',
@@ -73,3 +72,9 @@ export const columns: VxeGridProps['columns'] = [
width: 180,
},
];
/**
* 图片加载失败的fallback
*/
export const fallbackImageBase64 =
'data:image/png;base64,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';

View File

@@ -45,6 +45,7 @@ const message = computed(() => {
v-model:value="fileList"
:accept="accept"
:max-number="maxNumber"
:max-size="5"
/>
</div>
</BasicModal>

View File

@@ -1,10 +1,14 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { PageQuery } from '#/api/common';
import type { OssFile } from '#/api/system/oss/model';
import { onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import { Page, useVbenModal, type VbenFormProps } from '@vben/common-ui';
import { Page, useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { getVxePopupContainer } from '@vben/utils';
@@ -14,21 +18,22 @@ import {
Modal,
Popconfirm,
Space,
Spin,
Switch,
Tooltip,
} from 'ant-design-vue';
import {
addSortParams,
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps,
vxeSortEvent,
} from '#/adapter/vxe-table';
import { configInfoByKey } from '#/api/system/config';
import { ossDownload, ossList, ossRemove } from '#/api/system/oss';
import { calculateFileSize } from '#/utils/file';
import { downloadByData } from '#/utils/file/download';
import { columns, querySchema } from './data';
import { columns, fallbackImageBase64, querySchema } from './data';
import fileUploadModal from './file-upload-modal.vue';
import imageUploadModal from './image-upload-modal.vue';
@@ -66,18 +71,19 @@ const gridOptions: VxeGridProps = {
pagerConfig: {},
proxyConfig: {
ajax: {
query: async ({ page }, formValues = {}) => {
const params: any = {
query: async ({ page, sorts }, formValues = {}) => {
const params: PageQuery = {
pageNum: page.currentPage,
pageSize: page.pageSize,
...formValues,
};
// 添加排序参数
addSortParams(params, sorts);
return await ossList(params);
},
},
},
rowConfig: {
isHover: true,
keyField: 'ossId',
height: 65,
},
@@ -94,28 +100,42 @@ const [BasicTable, tableApi] = useVbenVxeGrid({
formOptions,
gridOptions,
gridEvents: {
sortChange: (sortParams) => vxeSortEvent(tableApi, sortParams),
// 排序 重新请求接口
sortChange: () => tableApi.query(),
},
});
async function handleDownload(row: Recordable<any>) {
const hideLoading = message.loading($t('pages.common.downloadLoading'), 0);
async function handleDownload(row: OssFile) {
const downloadSize = ref($t('pages.common.downloadLoading'));
const hideLoading = message.loading({
content: () => downloadSize.value,
duration: 0,
});
try {
const data = await ossDownload(row.ossId);
const data = await ossDownload(row.ossId, (e) => {
// 计算下载进度
const percent = Math.floor((e.loaded / e.total!) * 100);
// 已经下载
const current = calculateFileSize(e.loaded);
// 总大小
const total = calculateFileSize(e.total!);
downloadSize.value = `已下载: ${current}/${total} (${percent}%)`;
});
downloadByData(data, row.originalName);
message.success('下载完成');
} finally {
hideLoading();
}
}
async function handleDelete(row: Recordable<any>) {
await ossRemove(row.ossId);
async function handleDelete(row: OssFile) {
await ossRemove([row.ossId]);
await tableApi.query();
}
function handleMultiDelete() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: any) => row.ossId);
const ids = rows.map((row: OssFile) => row.ossId);
Modal.confirm({
title: '提示',
okType: 'danger',
@@ -134,8 +154,8 @@ function handleToSettings() {
const preview = ref(false);
onMounted(async () => {
const resp = await configInfoByKey('sys.oss.previewListResource');
preview.value = Boolean(resp);
const previewStr = await configInfoByKey('sys.oss.previewListResource');
preview.value = previewStr === 'true';
});
function isImageFile(ext: string) {
@@ -189,11 +209,22 @@ const [FileUploadModal, fileUploadApi] = useVbenModal({
</Space>
</template>
<template #url="{ row }">
<!-- placeholder为图片未加载时显示的占位图 -->
<!-- fallback为图片加载失败时显示 -->
<!-- 需要设置key属性 否则切换翻页会有延迟 -->
<Image
:key="row.ossId"
v-if="preview && isImageFile(row.url)"
:src="row.url"
height="50px"
/>
:fallback="fallbackImageBase64"
>
<template #placeholder>
<div class="flex size-full items-center justify-center">
<Spin />
</div>
</template>
</Image>
<span v-else>{{ row.url }}</span>
</template>
<template #action="{ row }">

View File

@@ -1,9 +1,9 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { DictEnum } from '@vben/constants';
import { getPopupContainer } from '@vben/utils';
import { type FormSchemaGetter } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
import { renderDict } from '#/utils/render';

View File

@@ -1,18 +1,17 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { Post } from '#/api/system/post/model';
import { ref } from 'vue';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { Page, useVbenDrawer } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import {
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps,
} from '#/adapter/vxe-table';
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
import { postExport, postList, postRemove } from '#/api/system/post';
import { commonDownloadExcel } from '#/utils/file/download';
import DeptTree from '#/views/system/user/dept-tree.vue';
@@ -73,7 +72,6 @@ const gridOptions: VxeGridProps = {
},
},
rowConfig: {
isHover: true,
keyField: 'postId',
},
id: 'system-post-index',
@@ -93,19 +91,19 @@ function handleAdd() {
drawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
async function handleEdit(record: Post) {
drawerApi.setData({ id: record.postId });
drawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
await postRemove(row.postId);
async function handleDelete(row: Post) {
await postRemove([row.postId]);
await tableApi.query();
}
function handleMultiDelete() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: any) => row.postId);
const ids = rows.map((row: Post) => row.postId);
Modal.confirm({
title: '提示',
okType: 'danger',

View File

@@ -1,7 +1,6 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { type FormSchemaGetter } from '#/adapter/form';
export const querySchema: FormSchemaGetter = () => [
{
component: 'Input',

View File

@@ -1,18 +1,17 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { User } from '#/api/system/user/model';
import { useRoute } from 'vue-router';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { Page, useVbenDrawer } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import {
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps,
} from '#/adapter/vxe-table';
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
import {
roleAllocatedList,
roleAuthCancel,
@@ -62,7 +61,6 @@ const gridOptions: VxeGridProps = {
},
},
rowConfig: {
isHover: true,
keyField: 'userId',
},
id: 'system-role-assign-index',
@@ -85,7 +83,7 @@ function handleAdd() {
/**
* 取消授权 一条记录
*/
async function handleAuthCancel(record: Recordable<any>) {
async function handleAuthCancel(record: User) {
await roleAuthCancel({ userId: record.userId, roleId });
await tableApi.query();
}
@@ -95,7 +93,7 @@ async function handleAuthCancel(record: Recordable<any>) {
*/
function handleMultipleAuthCancel() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: any) => row.userId);
const ids = rows.map((row: User) => row.userId);
Modal.confirm({
title: '提示',
okType: 'danger',

View File

@@ -1,9 +1,13 @@
<script setup lang="ts">
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { useRoute } from 'vue-router';
import { useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { useVbenDrawer } from '@vben/common-ui';
import { useVbenVxeGrid, type VxeGridProps } from '#/adapter/vxe-table';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { roleSelectAll, roleUnallocatedList } from '#/api/system/role';
import { columns, querySchema } from './data';
@@ -52,7 +56,6 @@ const gridOptions: VxeGridProps = {
},
},
rowConfig: {
isHover: true,
keyField: 'userId',
},
};

View File

@@ -1,3 +1,4 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { DictEnum } from '@vben/constants';
@@ -5,7 +6,6 @@ import { getPopupContainer } from '@vben/utils';
import { Tag } from 'ant-design-vue';
import { type FormSchemaGetter } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
/**
@@ -17,6 +17,7 @@ export const authScopeOptions = [
{ color: 'orange', label: '本部门数据权限', value: '3' },
{ color: 'cyan', label: '本部门及以下数据权限', value: '4' },
{ color: 'error', label: '仅本人数据权限', value: '5' },
{ color: 'default', label: '部门及以下或本人数据权限', value: '6' },
];
export const querySchema: FormSchemaGetter = () => [

View File

@@ -1,16 +1,14 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { Role } from '#/api/system/role/model';
import { computed } from 'vue';
import { useRouter } from 'vue-router';
import { useAccess } from '@vben/access';
import {
Page,
useVbenDrawer,
useVbenModal,
type VbenFormProps,
} from '@vben/common-ui';
import { Page, useVbenDrawer, useVbenModal } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import {
@@ -22,11 +20,7 @@ import {
Space,
} from 'ant-design-vue';
import {
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps,
} from '#/adapter/vxe-table';
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
import {
roleChangeStatus,
roleExport,
@@ -85,7 +79,6 @@ const gridOptions: VxeGridProps = {
},
},
rowConfig: {
isHover: true,
keyField: 'roleId',
},
id: 'system-role-index',
@@ -104,19 +97,19 @@ function handleAdd() {
drawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
async function handleEdit(record: Role) {
drawerApi.setData({ id: record.roleId });
drawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
await roleRemove(row.roleId);
async function handleDelete(row: Role) {
await roleRemove([row.roleId]);
await tableApi.query();
}
function handleMultiDelete() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: any) => row.roleId);
const ids = rows.map((row: Role) => row.roleId);
Modal.confirm({
title: '提示',
okType: 'danger',
@@ -142,13 +135,13 @@ const [RoleAuthModal, authModalApi] = useVbenModal({
connectedComponent: roleAuthModal,
});
function handleAuthEdit(record: Recordable<any>) {
function handleAuthEdit(record: Role) {
authModalApi.setData({ id: record.roleId });
authModalApi.open();
}
const router = useRouter();
function handleAssignRole(record: Recordable<any>) {
function handleAssignRole(record: Role) {
router.push(`/system/role-assign/${record.roleId}`);
}
</script>

View File

@@ -1,4 +1,6 @@
<script setup lang="ts">
import type { DeptOption } from '#/api/system/role/model';
import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
@@ -23,7 +25,7 @@ const [BasicForm, formApi] = useVbenForm({
showDefaultActions: false,
});
const deptTree = ref<any[]>([]);
const deptTree = ref<DeptOption[]>([]);
async function setupDeptTree(id: number | string) {
const resp = await roleDeptTree(id);
formApi.setFieldValue('deptIds', resp.checkedKeys);

View File

@@ -1,5 +1,7 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import type { MenuOption } from '#/api/system/menu/model';
import { computed, nextTick, ref } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
import { $t } from '@vben/locales';
@@ -8,7 +10,7 @@ import { cloneDeep, eachTree } from '@vben/utils';
import { useVbenForm } from '#/adapter/form';
import { menuTreeSelect, roleMenuTreeSelect } from '#/api/system/menu';
import { roleAdd, roleInfo, roleUpdate } from '#/api/system/role';
import { TreeSelectPanel } from '#/components/tree';
import { MenuSelectTable } from '#/components/tree';
import { drawerSchema } from './data';
@@ -32,11 +34,10 @@ const [BasicForm, formApi] = useVbenForm({
wrapperClass: 'grid-cols-2 gap-x-4',
});
const menuTree = ref<any[]>([]);
const menuTree = ref<MenuOption[]>([]);
async function setupMenuTree(id?: number | string) {
if (id) {
const resp = await roleMenuTreeSelect(id);
formApi.setFieldValue('menuIds', resp.checkedKeys);
const menus = resp.menus;
// i18n处理
eachTree(menus, (node) => {
@@ -44,15 +45,20 @@ async function setupMenuTree(id?: number | string) {
});
// 设置菜单信息
menuTree.value = resp.menus;
// keys依赖于menu 需要先加载menu
await nextTick();
await formApi.setFieldValue('menuIds', resp.checkedKeys);
} else {
const resp = await menuTreeSelect();
formApi.setFieldValue('menuIds', []);
// i18n处理
eachTree(resp, (node) => {
node.label = $t(node.label);
});
// 设置菜单信息
menuTree.value = resp;
// keys依赖于menu 需要先加载menu
await nextTick();
await formApi.setFieldValue('menuIds', []);
}
}
@@ -78,11 +84,7 @@ const [BasicDrawer, drawerApi] = useVbenDrawer({
},
});
/**
* 这里拿到的是一个数组ref
*/
const menuSelectRef = ref();
const menuSelectRef = ref<InstanceType<typeof MenuSelectTable>>();
async function handleConfirm() {
try {
drawerApi.drawerLoading(true);
@@ -91,7 +93,7 @@ async function handleConfirm() {
return;
}
// 这个用于提交
const menuIds = menuSelectRef.value?.[0]?.getCheckedKeys() ?? [];
const menuIds = menuSelectRef.value?.getCheckedKeys?.() ?? [];
// formApi.getValues拿到的是一个readonly对象不能直接修改需要cloneDeep
const data = cloneDeep(await formApi.getValues());
data.menuIds = menuIds;
@@ -120,17 +122,19 @@ function handleMenuCheckStrictlyChange(value: boolean) {
</script>
<template>
<BasicDrawer :close-on-click-modal="false" :title="title" class="w-[600px]">
<BasicDrawer :close-on-click-modal="false" :title="title" class="w-[800px]">
<BasicForm>
<template #menuIds="slotProps">
<!-- check-strictly为readonly 不能通过v-model绑定 -->
<TreeSelectPanel
ref="menuSelectRef"
v-bind="slotProps"
:check-strictly="formApi.form.values.menuCheckStrictly"
:tree-data="menuTree"
@check-strictly-change="handleMenuCheckStrictlyChange"
/>
<div class="h-[600px] w-full">
<!-- association为readonly 不能通过v-model绑定 -->
<MenuSelectTable
ref="menuSelectRef"
:checked-keys="slotProps.value"
:association="formApi.form.values.menuCheckStrictly"
:menus="menuTree"
@update:association="handleMenuCheckStrictlyChange"
/>
</div>
</template>
</BasicForm>
</BasicDrawer>

View File

@@ -1,10 +1,11 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { getPopupContainer } from '@vben/utils';
import dayjs from 'dayjs';
import { type FormSchemaGetter, z } from '#/adapter/form';
import { z } from '#/adapter/form';
export const querySchema: FormSchemaGetter = () => [
{

View File

@@ -1,20 +1,18 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { Tenant } from '#/api/system/tenant/model';
import { computed } from 'vue';
import { useAccess } from '@vben/access';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { Fallback } from '@vben/common-ui';
import { Fallback, Page, useVbenDrawer } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import {
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps,
} from '#/adapter/vxe-table';
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
import {
dictSyncTenant,
tenantExport,
@@ -67,7 +65,6 @@ const gridOptions: VxeGridProps = {
},
},
rowConfig: {
isHover: true,
keyField: 'id',
},
id: 'system-tenant-index',
@@ -87,20 +84,20 @@ function handleAdd() {
drawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
async function handleEdit(record: Tenant) {
drawerApi.setData({ id: record.id });
drawerApi.open();
}
async function handleSync(record: Recordable<any>) {
async function handleSync(record: Tenant) {
const { tenantId, packageId } = record;
await tenantSyncPackage(tenantId, packageId);
await tableApi.query();
}
const tenantStore = useTenantStore();
async function handleDelete(row: Recordable<any>) {
await tenantRemove(row.id);
async function handleDelete(row: Tenant) {
await tenantRemove([row.id]);
await tableApi.query();
// 重新加载租户信息
tenantStore.initTenant();
@@ -108,7 +105,7 @@ async function handleDelete(row: Recordable<any>) {
function handleMultiDelete() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: any) => row.id);
const ids = rows.map((row: Tenant) => row.id);
Modal.confirm({
title: '提示',
okType: 'danger',

View File

@@ -1,7 +1,6 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { type FormSchemaGetter } from '#/adapter/form';
export const querySchema: FormSchemaGetter = () => [
{
component: 'Input',

View File

@@ -1,20 +1,18 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { TenantPackage } from '#/api/system/tenant-package/model';
import { computed } from 'vue';
import { useAccess } from '@vben/access';
import { Page, useVbenDrawer, type VbenFormProps } from '@vben/common-ui';
import { Fallback } from '@vben/common-ui';
import { Fallback, Page, useVbenDrawer } from '@vben/common-ui';
import { getVxePopupContainer } from '@vben/utils';
import { Modal, Popconfirm, Space } from 'ant-design-vue';
import {
useVbenVxeGrid,
vxeCheckboxChecked,
type VxeGridProps,
} from '#/adapter/vxe-table';
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
import {
packageChangeStatus,
packageExport,
@@ -63,7 +61,6 @@ const gridOptions: VxeGridProps = {
},
},
rowConfig: {
isHover: true,
keyField: 'packageId',
},
id: 'system-tenant-package-index',
@@ -83,19 +80,19 @@ function handleAdd() {
drawerApi.open();
}
async function handleEdit(record: Recordable<any>) {
async function handleEdit(record: TenantPackage) {
drawerApi.setData({ id: record.packageId });
drawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
await packageRemove(row.packageId);
async function handleDelete(row: TenantPackage) {
await packageRemove([row.packageId]);
await tableApi.query();
}
function handleMultiDelete() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: any) => row.packageId);
const ids = rows.map((row: TenantPackage) => row.packageId);
Modal.confirm({
title: '提示',
okType: 'danger',

View File

@@ -1,23 +1,24 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import type { MenuOption } from '#/api/system/menu/model';
import { computed, nextTick, ref } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { cloneDeep, eachTree, listToTree } from '@vben/utils';
import { cloneDeep, eachTree } from '@vben/utils';
import { omit } from 'lodash-es';
import { useVbenForm } from '#/adapter/form';
import { menuList, tenantPackageMenuTreeSelect } from '#/api/system/menu';
import { menuTreeSelect, tenantPackageMenuTreeSelect } from '#/api/system/menu';
import {
packageAdd,
packageInfo,
packageUpdate,
} from '#/api/system/tenant-package';
import { TreeSelectPanel } from '#/components/tree';
import { MenuSelectTable } from '#/components/tree';
import { drawerSchema } from './data';
import TreeItem from './tree-item';
const emit = defineEmits<{ reload: [] }>();
@@ -36,25 +37,34 @@ const [BasicForm, formApi] = useVbenForm({
wrapperClass: 'grid-cols-2',
});
async function setupMenuTreeSelect(id?: number | string) {
const menuTree = ref<MenuOption[]>([]);
async function setupMenuTree(id?: number | string) {
if (id) {
const resp = await tenantPackageMenuTreeSelect(id);
const menus = resp.menus;
// i18n处理
eachTree(menus, (node) => {
node.label = $t(node.label);
});
// 设置菜单信息
menuTree.value = resp.menus;
// keys依赖于menu 需要先加载menu
await nextTick();
await formApi.setFieldValue('menuIds', resp.checkedKeys);
} else {
const resp = await menuTreeSelect();
// i18n处理
eachTree(resp, (node) => {
node.label = $t(node.label);
});
// 设置菜单信息
menuTree.value = resp;
// keys依赖于menu 需要先加载menu
await nextTick();
await formApi.setFieldValue('menuIds', []);
}
}
const menuTree = ref<any[]>([]);
async function setupMenuTree() {
const resp = await menuList();
const treeData = listToTree(resp, { id: 'menuId' });
// i18n处理
eachTree(treeData, (node) => {
node.menuName = $t(node.menuName);
});
// 设置菜单信息
menuTree.value = treeData;
}
const [BasicDrawer, drawerApi] = useVbenDrawer({
onCancel: handleCancel,
onConfirm: handleConfirm,
@@ -72,20 +82,14 @@ const [BasicDrawer, drawerApi] = useVbenDrawer({
// 通过setupMenuTreeSelect设置
await formApi.setValues(omit(record, ['menuIds']));
}
/**
* 加载菜单树和已勾选菜单
*/
await Promise.all([setupMenuTree(), setupMenuTreeSelect(id)]);
// init菜单 注意顺序要放在赋值record之后 内部watch会依赖record
await setupMenuTree(id);
drawerApi.drawerLoading(false);
},
});
/**
* 这里拿到的是一个数组ref
*/
const menuSelectRef = ref();
const menuSelectRef = ref<InstanceType<typeof MenuSelectTable>>();
async function handleConfirm() {
try {
drawerApi.drawerLoading(true);
@@ -94,7 +98,7 @@ async function handleConfirm() {
return;
}
// 这个用于提交
const menuIds = menuSelectRef.value?.[0]?.getCheckedKeys() ?? [];
const menuIds = menuSelectRef.value?.getCheckedKeys?.() ?? [];
// formApi.getValues拿到的是一个readonly对象不能直接修改需要cloneDeep
const data = cloneDeep(await formApi.getValues());
data.menuIds = menuIds;
@@ -123,22 +127,19 @@ function handleMenuCheckStrictlyChange(value: boolean) {
</script>
<template>
<BasicDrawer :close-on-click-modal="false" :title="title" class="w-[600px]">
<BasicDrawer :close-on-click-modal="false" :title="title" class="w-[800px]">
<BasicForm>
<template #menuIds="slotProps">
<TreeSelectPanel
ref="menuSelectRef"
v-bind="slotProps"
:check-strictly="formApi.form.values.menuCheckStrictly"
:expand-all-on-init="false"
:field-names="{ title: 'menuName', key: 'menuId' }"
:tree-data="menuTree"
@check-strictly-change="handleMenuCheckStrictlyChange"
>
<template #title="data">
<TreeItem :data="data" />
</template>
</TreeSelectPanel>
<div class="h-[600px] w-full">
<!-- association为readonly 不能通过v-model绑定 -->
<MenuSelectTable
ref="menuSelectRef"
:checked-keys="slotProps.value"
:association="formApi.form.values.menuCheckStrictly"
:menus="menuTree"
@update:association="handleMenuCheckStrictlyChange"
/>
</div>
</template>
</BasicForm>
</BasicDrawer>

View File

@@ -1,6 +1,8 @@
import type { PropType } from 'vue';
import type { Menu } from '#/api/system/menu/model';
import { computed, defineComponent, type PropType } from 'vue';
import { computed, defineComponent } from 'vue';
import { Tag } from 'ant-design-vue';

View File

@@ -1,9 +1,10 @@
import type { FormSchemaGetter } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { DictEnum } from '@vben/constants';
import { getPopupContainer } from '@vben/utils';
import { type FormSchemaGetter, z } from '#/adapter/form';
import { z } from '#/adapter/form';
import { getDictOptions } from '#/utils/dict';
export const querySchema: FormSchemaGetter = () => [

View File

@@ -1,7 +1,9 @@
<script setup lang="ts">
import type { PropType } from 'vue';
import type { DeptTree } from '#/api/system/user/model';
import { onMounted, type PropType, ref } from 'vue';
import { onMounted, ref } from 'vue';
import { SyncOutlined } from '@ant-design/icons-vue';
import { Empty, InputSearch, Skeleton, Tree } from 'ant-design-vue';
@@ -10,6 +12,8 @@ import { getDeptTree } from '#/api/system/user';
defineOptions({ inheritAttrs: false });
withDefaults(defineProps<{ showSearch?: boolean }>(), { showSearch: true });
const emit = defineEmits<{
/**
* 点击刷新按钮的事件
@@ -68,7 +72,10 @@ onMounted(loadTree);
class="bg-background flex h-full flex-col overflow-y-auto rounded-lg"
>
<!-- 固定在顶部 必须加上bg-background背景色 否则会产生'穿透'效果 -->
<div class="bg-background z-100 sticky left-0 top-0 p-[8px]">
<div
v-if="showSearch"
class="bg-background z-100 sticky left-0 top-0 p-[8px]"
>
<InputSearch
v-model:value="searchValue"
:placeholder="$t('pages.common.search')"

View File

@@ -1,15 +1,13 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { VbenFormProps } from '@vben/common-ui';
import type { VxeGridProps } from '#/adapter/vxe-table';
import type { User } from '#/api/system/user/model';
import { ref } from 'vue';
import { useAccess } from '@vben/access';
import {
Page,
useVbenDrawer,
useVbenModal,
type VbenFormProps,
} from '@vben/common-ui';
import { Page, useVbenDrawer, useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { preferences } from '@vben/preferences';
import { getVxePopupContainer } from '@vben/utils';
@@ -24,8 +22,7 @@ import {
Space,
} from 'ant-design-vue';
import { useVbenVxeGrid, type VxeGridProps } from '#/adapter/vxe-table';
import { vxeCheckboxChecked } from '#/adapter/vxe-table';
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
import {
userExport,
userList,
@@ -117,7 +114,6 @@ const gridOptions: VxeGridProps = {
},
},
rowConfig: {
isHover: true,
keyField: 'userId',
height: 48,
},
@@ -137,19 +133,19 @@ function handleAdd() {
userDrawerApi.open();
}
function handleEdit(row: Recordable<any>) {
function handleEdit(row: User) {
userDrawerApi.setData({ id: row.userId });
userDrawerApi.open();
}
async function handleDelete(row: Recordable<any>) {
await userRemove(row.userId);
async function handleDelete(row: User) {
await userRemove([row.userId]);
await tableApi.query();
}
function handleMultiDelete() {
const rows = tableApi.grid.getCheckboxRecords();
const ids = rows.map((row: any) => row.userId);
const ids = rows.map((row: User) => row.userId);
Modal.confirm({
title: '提示',
okType: 'danger',
@@ -170,7 +166,7 @@ function handleDownloadExcel() {
const [UserInfoModal, userInfoModalApi] = useVbenModal({
connectedComponent: userInfoModal,
});
function handleUserInfo(row: Recordable<any>) {
function handleUserInfo(row: User) {
userInfoModalApi.setData({ userId: row.userId });
userInfoModalApi.open();
}
@@ -179,7 +175,7 @@ const [UserResetPwdModal, userResetPwdModalApi] = useVbenModal({
connectedComponent: userResetPwdModal,
});
function handleResetPwd(record: Recordable<any>) {
function handleResetPwd(record: User) {
userResetPwdModalApi.setData({ record });
userResetPwdModalApi.open();
}

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { Role } from '#/api/system/user/model';
import { computed, h, ref } from 'vue';
import { computed, h, onMounted, ref } from 'vue';
import { useVbenDrawer } from '@vben/common-ui';
import { $t } from '@vben/locales';
@@ -117,13 +117,20 @@ async function setupDeptSelect() {
]);
}
const defaultPassword = ref('');
onMounted(async () => {
const password = await configInfoByKey('sys.user.initPassword');
if (password) {
defaultPassword.value = password;
}
});
/**
* 新增时候 从参数设置获取默认密码
*/
async function loadDefaultPassword(update: boolean) {
if (!update) {
const defaultPassword = await configInfoByKey('sys.user.initPassword');
defaultPassword && formApi.setFieldValue('password', defaultPassword);
if (!update && defaultPassword.value) {
formApi.setFieldValue('password', defaultPassword.value);
}
}

View File

@@ -1,4 +1,6 @@
<script setup lang="ts">
import type { User } from '#/api/system/user/model';
import { useVbenModal } from '@vben/common-ui';
import { findUserInfo } from '#/api/system/user';
@@ -39,8 +41,12 @@ async function handleOpenChange(open: boolean) {
.filter((item) => roleIds.includes(item.roleId))
.map((item) => item.roleName);
(user as any).postNames = postNames;
(user as any).roleNames = roleNames;
interface UserWithNames extends User {
postNames: string[];
roleNames: string[];
}
(user as UserWithNames).postNames = postNames;
(user as UserWithNames).roleNames = roleNames;
// 赋值
setDescProps({ data: user });

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import type { Recordable } from '@vben/types';
import type { ResetPwdParam, User } from '#/api/system/user/model';
import { useVbenModal, z } from '@vben/common-ui';
@@ -68,7 +68,7 @@ async function handleOpenChange(open: boolean) {
if (!open) {
return null;
}
const { record } = modalApi.getData() as { record: Recordable<any> };
const { record } = modalApi.getData() as { record: User };
setDescProps({ data: record }, true);
await formApi.setValues({ userId: record.userId });
}
@@ -81,7 +81,7 @@ async function handleSubmit() {
return;
}
const data = await formApi.getValues();
await userResetPassword(data as any);
await userResetPassword(data as ResetPwdParam);
emit('reload');
handleCancel();
} catch (error) {