Merge pull request #139 from cshaptx4869/patch-95
refactor: ♻️ 规整CURD组件
This commit is contained in:
@@ -472,160 +472,22 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ExcelJS from "exceljs";
|
||||
import { ref, reactive } from "vue";
|
||||
import { useDateFormat, useThrottleFn } from "@vueuse/core";
|
||||
import { hasAuth } from "@/plugins/permission";
|
||||
import SvgIcon from "@/components/SvgIcon/index.vue";
|
||||
import { hasAuth } from "@/plugins/permission";
|
||||
import { useDateFormat, useThrottleFn } from "@vueuse/core";
|
||||
import {
|
||||
type TableProps,
|
||||
type PaginationProps,
|
||||
genFileId,
|
||||
type FormInstance,
|
||||
type FormRules,
|
||||
type UploadInstance,
|
||||
type UploadUserFile,
|
||||
type UploadRawFile,
|
||||
genFileId,
|
||||
type UploadUserFile,
|
||||
} from "element-plus";
|
||||
import ExcelJS from "exceljs";
|
||||
import { reactive, ref } from "vue";
|
||||
import type { IContentConfig, IObject, IOperatData } from "./types";
|
||||
|
||||
// 对象类型
|
||||
export type IObject = Record<string, any>;
|
||||
// 定义接收的属性
|
||||
export interface IOperatData {
|
||||
name: string;
|
||||
row: any;
|
||||
column: any;
|
||||
$index: number;
|
||||
}
|
||||
export interface IContentConfig<T = any> {
|
||||
// 页面名称(参与组成权限标识,如sys:user:xxx)
|
||||
pageName: string;
|
||||
// table组件属性
|
||||
table?: Omit<TableProps<any>, "data">;
|
||||
// pagination组件属性
|
||||
pagination?:
|
||||
| boolean
|
||||
| Partial<
|
||||
Omit<
|
||||
PaginationProps,
|
||||
"v-model:page-size" | "v-model:current-page" | "total" | "currentPage"
|
||||
>
|
||||
>;
|
||||
// 列表的网络请求函数(需返回promise)
|
||||
indexAction: (queryParams: T) => Promise<any>;
|
||||
// 默认的分页相关的请求参数
|
||||
request?: {
|
||||
pageName: string;
|
||||
limitName: string;
|
||||
};
|
||||
// 数据格式解析的回调函数
|
||||
parseData?: (res: any) => {
|
||||
total: number;
|
||||
list: IObject[];
|
||||
[key: string]: any;
|
||||
};
|
||||
// 修改属性的网络请求函数(需返回promise)
|
||||
modifyAction?: (data: {
|
||||
[key: string]: any;
|
||||
field: string;
|
||||
value: boolean | string | number;
|
||||
}) => Promise<any>;
|
||||
// 删除的网络请求函数(需返回promise)
|
||||
deleteAction?: (ids: string) => Promise<any>;
|
||||
// 后端导出的网络请求函数(需返回promise)
|
||||
exportAction?: (queryParams: T) => Promise<any>;
|
||||
// 前端全量导出的网络请求函数(需返回promise)
|
||||
exportsAction?: (queryParams: T) => Promise<IObject[]>;
|
||||
// 前端导入模板
|
||||
importsTemplate?: string | (() => Promise<any>);
|
||||
// 前端导入的网络请求函数(需返回promise)
|
||||
importsAction?: (data: IObject[]) => Promise<any>;
|
||||
// 主键名(默认为id)
|
||||
pk?: string;
|
||||
// 表格工具栏(默认支持add,delete,export,也可自定义)
|
||||
toolbar?: Array<
|
||||
| "add"
|
||||
| "delete"
|
||||
| "export"
|
||||
| {
|
||||
auth: string;
|
||||
icon?: string;
|
||||
name: string;
|
||||
text: string;
|
||||
}
|
||||
>;
|
||||
// 表格工具栏右侧图标
|
||||
defaultToolbar?: Array<
|
||||
| "refresh"
|
||||
| "filter"
|
||||
| "imports"
|
||||
| "exports"
|
||||
| "search"
|
||||
| {
|
||||
name: string;
|
||||
icon: string;
|
||||
title?: string;
|
||||
auth?: string;
|
||||
}
|
||||
>;
|
||||
// table组件列属性(额外的属性templet,operat,slotName)
|
||||
cols: Array<{
|
||||
type?: "default" | "selection" | "index" | "expand";
|
||||
label?: string;
|
||||
prop?: string;
|
||||
width?: string | number;
|
||||
align?: "left" | "center" | "right";
|
||||
columnKey?: string;
|
||||
reserveSelection?: boolean;
|
||||
// 列是否显示
|
||||
show?: boolean;
|
||||
// 模板
|
||||
templet?:
|
||||
| "image"
|
||||
| "list"
|
||||
| "url"
|
||||
| "switch"
|
||||
| "input"
|
||||
| "price"
|
||||
| "percent"
|
||||
| "icon"
|
||||
| "date"
|
||||
| "tool"
|
||||
| "custom";
|
||||
// image模板相关参数
|
||||
imageWidth?: number;
|
||||
imageHeight?: number;
|
||||
// list模板相关参数
|
||||
selectList?: Record<string, any>;
|
||||
// switch模板相关参数
|
||||
activeValue?: boolean | string | number;
|
||||
inactiveValue?: boolean | string | number;
|
||||
activeText?: string;
|
||||
inactiveText?: string;
|
||||
// input模板相关参数
|
||||
inputType?: string;
|
||||
// price模板相关参数
|
||||
priceFormat?: string;
|
||||
// date模板相关参数
|
||||
dateFormat?: string;
|
||||
// tool模板相关参数
|
||||
operat?: Array<
|
||||
| "edit"
|
||||
| "delete"
|
||||
| {
|
||||
auth: string;
|
||||
icon?: string;
|
||||
name: string;
|
||||
text: string;
|
||||
}
|
||||
>;
|
||||
// filter值拼接符
|
||||
filterJoin?: string;
|
||||
[key: string]: any;
|
||||
// 初始化数据函数
|
||||
initFn?: (item: IObject) => void;
|
||||
}>;
|
||||
}
|
||||
const props = defineProps<{
|
||||
contentConfig: IContentConfig;
|
||||
}>();
|
||||
@@ -676,8 +538,6 @@ const cols = ref(
|
||||
);
|
||||
// 加载状态
|
||||
const loading = ref(false);
|
||||
// 删除ID集合 用于批量删除
|
||||
const removeIds = ref<(number | string)[]>([]);
|
||||
// 列表数据
|
||||
const pageData = ref<IObject[]>([]);
|
||||
// 显示分页
|
||||
@@ -704,14 +564,18 @@ const request = props.contentConfig.request ?? {
|
||||
|
||||
// 行选中
|
||||
const selectionData = ref<IObject[]>([]);
|
||||
// 删除ID集合 用于批量删除
|
||||
const removeIds = ref<(number | string)[]>([]);
|
||||
function handleSelectionChange(selection: any[]) {
|
||||
selectionData.value = selection;
|
||||
removeIds.value = selection.map((item) => item[pk]);
|
||||
}
|
||||
|
||||
// 刷新
|
||||
function handleRefresh() {
|
||||
fetchPageData(lastFormData);
|
||||
}
|
||||
|
||||
// 删除
|
||||
function handleDelete(id?: number | string) {
|
||||
const ids = [id || removeIds.value].join(",");
|
||||
@@ -735,6 +599,7 @@ function handleDelete(id?: number | string) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 导出表单
|
||||
const fields: string[] = [];
|
||||
cols.value.forEach((item) => {
|
||||
@@ -825,6 +690,7 @@ function handleExports() {
|
||||
.catch((error) => console.log(error));
|
||||
}
|
||||
}
|
||||
|
||||
// 导入表单
|
||||
const uploadRef = ref<UploadInstance>();
|
||||
const importsModalVisible = ref(false);
|
||||
@@ -943,6 +809,7 @@ function handleImports() {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 操作栏
|
||||
function handleToolbar(name: string) {
|
||||
switch (name) {
|
||||
@@ -972,6 +839,7 @@ function handleToolbar(name: string) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 操作列
|
||||
function handleOperat(data: IOperatData) {
|
||||
switch (data.name) {
|
||||
@@ -986,6 +854,7 @@ function handleOperat(data: IOperatData) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 属性修改
|
||||
function handleModify(
|
||||
field: string,
|
||||
@@ -1002,6 +871,7 @@ function handleModify(
|
||||
ElMessage.error("未配置modifyAction");
|
||||
}
|
||||
}
|
||||
|
||||
// 分页切换
|
||||
function handleSizeChange(value: number) {
|
||||
pagination.pageSize = value;
|
||||
@@ -1011,6 +881,7 @@ function handleCurrentChange(value: number) {
|
||||
pagination.currentPage = value;
|
||||
fetchPageData(lastFormData);
|
||||
}
|
||||
|
||||
// 远程数据筛选
|
||||
let filterParams: IObject = {};
|
||||
function handleFilterChange(newFilters: any) {
|
||||
@@ -1033,6 +904,7 @@ function handleFilterChange(newFilters: any) {
|
||||
function getFilterParams() {
|
||||
return filterParams;
|
||||
}
|
||||
|
||||
// 获取分页数据
|
||||
let lastFormData = {};
|
||||
function fetchPageData(formData: IObject = {}, isRestart = false) {
|
||||
@@ -1069,6 +941,7 @@ function fetchPageData(formData: IObject = {}, isRestart = false) {
|
||||
});
|
||||
}
|
||||
fetchPageData();
|
||||
|
||||
// 导出Excel
|
||||
function exportPageData(formData: IObject = {}) {
|
||||
if (props.contentConfig.exportAction) {
|
||||
@@ -1083,6 +956,7 @@ function exportPageData(formData: IObject = {}) {
|
||||
ElMessage.error("未配置exportAction");
|
||||
}
|
||||
}
|
||||
|
||||
// 浏览器保存文件
|
||||
function saveXlsx(fileData: BlobPart, fileName: string) {
|
||||
const fileType =
|
||||
@@ -84,30 +84,19 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { FormInstance, FormRules } from "element-plus";
|
||||
import { reactive, ref, watch, computed, watchEffect } from "vue";
|
||||
import { IForm, IFormItems, IObject } from "./types";
|
||||
import { reactive, ref, watch, watchEffect } from "vue";
|
||||
import { IObject, IPageForm } from "./types";
|
||||
|
||||
// 定义接收的属性
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
// 主键名(主要用于编辑数据,默认为id)
|
||||
pk?: string;
|
||||
// form组件属性
|
||||
form?: IForm;
|
||||
// 表单项
|
||||
formItems: IFormItems;
|
||||
}>(),
|
||||
{
|
||||
pk: "id",
|
||||
}
|
||||
);
|
||||
const props = withDefaults(defineProps<IPageForm>(), {
|
||||
pk: "id",
|
||||
});
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
const formItems = reactive(props.formItems);
|
||||
const formData = reactive<IObject>({});
|
||||
const formRules: FormRules = {};
|
||||
const prepareFuncs = [];
|
||||
// 初始化
|
||||
for (const item of formItems) {
|
||||
item.initFn && item.initFn(item);
|
||||
formData[item.prop] = item.initialValue ?? "";
|
||||
@@ -126,12 +115,8 @@ for (const item of formItems) {
|
||||
|
||||
if (item.computed !== undefined) {
|
||||
prepareFuncs.push(() => {
|
||||
formData[item.prop] = computed({
|
||||
get() {
|
||||
return item.computed ? item.computed(formData) : undefined;
|
||||
},
|
||||
// TODO
|
||||
set() {},
|
||||
watchEffect(() => {
|
||||
item.computed && (formData[item.prop] = item.computed(formData));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -145,10 +130,12 @@ for (const item of formItems) {
|
||||
}
|
||||
}
|
||||
prepareFuncs.forEach((func) => func());
|
||||
|
||||
// 获取表单数据
|
||||
function getFormData(key?: string) {
|
||||
return key === undefined ? formData : formData[key] ?? undefined;
|
||||
}
|
||||
|
||||
// 设置表单值
|
||||
function setFormData(data: IObject) {
|
||||
for (const key in formData) {
|
||||
@@ -160,6 +147,7 @@ function setFormData(data: IObject) {
|
||||
formData[props.pk] = data[props.pk];
|
||||
}
|
||||
}
|
||||
|
||||
// 设置表单项值
|
||||
function setFormItemData(key: string, value: any) {
|
||||
formData[key] = value;
|
||||
@@ -244,83 +244,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type {
|
||||
FormInstance,
|
||||
FormRules,
|
||||
FormItemRule,
|
||||
FormProps,
|
||||
DialogProps,
|
||||
DrawerProps,
|
||||
} from "element-plus";
|
||||
import { useThrottleFn } from "@vueuse/core";
|
||||
import { reactive, ref, watch, watchEffect, nextTick } from "vue";
|
||||
import type { FormInstance, FormRules } from "element-plus";
|
||||
import { nextTick, reactive, ref, watch, watchEffect } from "vue";
|
||||
import type { IModalConfig, IObject } from "./types";
|
||||
|
||||
// 对象类型
|
||||
export type IObject = Record<string, any>;
|
||||
// 定义接收的属性
|
||||
export interface IModalConfig<T = any> {
|
||||
// 页面名称
|
||||
pageName?: string;
|
||||
// 主键名(主要用于编辑数据,默认为id)
|
||||
pk?: string;
|
||||
// 组件类型
|
||||
component?: "dialog" | "drawer";
|
||||
// dialog组件属性
|
||||
dialog?: Partial<Omit<DialogProps, "modelValue">>;
|
||||
// drawer组件属性
|
||||
drawer?: Partial<Omit<DrawerProps, "modelValue">>;
|
||||
// form组件属性
|
||||
form?: Partial<Omit<FormProps, "model" | "rules">>;
|
||||
// 表单项
|
||||
formItems: Array<{
|
||||
// 组件类型(如input,select,radio,custom等,默认input)
|
||||
type?:
|
||||
| "input"
|
||||
| "select"
|
||||
| "radio"
|
||||
| "checkbox"
|
||||
| "tree-select"
|
||||
| "date-picker"
|
||||
| "input-number"
|
||||
| "text"
|
||||
| "custom";
|
||||
// 组件属性
|
||||
attrs?: IObject;
|
||||
// 组件可选项(适用于select,radio,checkbox组件)
|
||||
options?: Array<{
|
||||
label: string;
|
||||
value: any;
|
||||
disabled?: boolean;
|
||||
[key: string]: any;
|
||||
}>;
|
||||
// 插槽名(适用于组件类型为custom)
|
||||
slotName?: string;
|
||||
// 标签文本
|
||||
label: string;
|
||||
// 标签提示
|
||||
tips?: string;
|
||||
// 键名
|
||||
prop: string;
|
||||
// 验证规则
|
||||
rules?: FormItemRule[];
|
||||
// 初始值
|
||||
initialValue?: any;
|
||||
// 是否隐藏
|
||||
hidden?: boolean;
|
||||
// 监听函数
|
||||
watch?: (newValue: any, oldValue: any, data: T, items: IObject[]) => void;
|
||||
// 计算属性函数
|
||||
computed?: (data: T) => any;
|
||||
// 监听收集函数
|
||||
watchEffect?: (data: T) => void;
|
||||
// 初始化数据函数扩展
|
||||
initFn?: (item: IObject) => void;
|
||||
}>;
|
||||
// 提交之前处理
|
||||
beforeSubmit?: (data: T) => void;
|
||||
// 提交的网络请求函数(需返回promise)
|
||||
formAction: (data: T) => Promise<any>;
|
||||
}
|
||||
const props = defineProps<{
|
||||
modalConfig: IModalConfig;
|
||||
}>();
|
||||
@@ -336,7 +265,6 @@ const formItems = reactive(props.modalConfig.formItems);
|
||||
const formData = reactive<IObject>({});
|
||||
const formRules: FormRules = {};
|
||||
const prepareFuncs = [];
|
||||
// 初始化
|
||||
for (const item of formItems) {
|
||||
item.initFn && item.initFn(item);
|
||||
formData[item.prop] = item.initialValue ?? "";
|
||||
@@ -371,6 +299,37 @@ for (const item of formItems) {
|
||||
}
|
||||
prepareFuncs.forEach((func) => func());
|
||||
|
||||
// 获取表单数据
|
||||
function getFormData(key?: string) {
|
||||
return key === undefined ? formData : formData[key] ?? undefined;
|
||||
}
|
||||
|
||||
// 设置表单值
|
||||
function setFormData(data: IObject) {
|
||||
for (const key in formData) {
|
||||
if (Object.hasOwn(formData, key) && key in data) {
|
||||
formData[key] = data[key];
|
||||
}
|
||||
}
|
||||
if (Object.hasOwn(data, pk)) {
|
||||
formData[pk] = data[pk];
|
||||
}
|
||||
}
|
||||
|
||||
// 设置表单项值
|
||||
function setFormItemData(key: string, value: any) {
|
||||
formData[key] = value;
|
||||
}
|
||||
|
||||
// 显示modal
|
||||
function setModalVisible(data: IObject = {}) {
|
||||
modalVisible.value = true;
|
||||
// nextTick解决赋值后重置表单无效问题
|
||||
nextTick(() => {
|
||||
Object.values(data).length > 0 && setFormData(data);
|
||||
});
|
||||
}
|
||||
|
||||
// 表单提交
|
||||
const handleSubmit = useThrottleFn(() => {
|
||||
formRef.value?.validate((valid: boolean) => {
|
||||
@@ -396,6 +355,7 @@ const handleSubmit = useThrottleFn(() => {
|
||||
}
|
||||
});
|
||||
}, 3000);
|
||||
|
||||
// 关闭弹窗
|
||||
function handleCloseModal() {
|
||||
modalVisible.value = false;
|
||||
@@ -404,33 +364,6 @@ function handleCloseModal() {
|
||||
formRef.value?.clearValidate();
|
||||
});
|
||||
}
|
||||
// 显示modal
|
||||
function setModalVisible(data: IObject = {}) {
|
||||
modalVisible.value = true;
|
||||
// nextTick解决赋值后重置表单无效问题
|
||||
nextTick(() => {
|
||||
Object.values(data).length > 0 && setFormData(data);
|
||||
});
|
||||
}
|
||||
// 获取表单数据
|
||||
function getFormData(key?: string) {
|
||||
return key === undefined ? formData : formData[key] ?? undefined;
|
||||
}
|
||||
// 设置表单值
|
||||
function setFormData(data: IObject) {
|
||||
for (const key in formData) {
|
||||
if (Object.hasOwn(formData, key) && key in data) {
|
||||
formData[key] = data[key];
|
||||
}
|
||||
}
|
||||
if (Object.hasOwn(data, pk)) {
|
||||
formData[pk] = data[pk];
|
||||
}
|
||||
}
|
||||
// 设置表单项值
|
||||
function setFormItemData(key: string, value: any) {
|
||||
formData[key] = value;
|
||||
}
|
||||
|
||||
// 暴露的属性和方法
|
||||
defineExpose({ setModalVisible, getFormData, setFormData, setFormItemData });
|
||||
@@ -116,42 +116,12 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormInstance } from "element-plus";
|
||||
import { reactive, ref } from "vue";
|
||||
import type { IObject, ISearchConfig } from "./types";
|
||||
|
||||
// 对象类型
|
||||
type IObject = Record<string, any>;
|
||||
// 定义接收的属性
|
||||
export interface ISearchConfig {
|
||||
// 页面名称(参与组成权限标识,如sys:user:xxx)
|
||||
pageName: string;
|
||||
// 表单项
|
||||
formItems: Array<{
|
||||
// 组件类型(如input,select等)
|
||||
type?: "input" | "select" | "tree-select" | "date-picker" | "input-tag";
|
||||
// 标签文本
|
||||
label: string;
|
||||
// 标签提示
|
||||
tips?: string;
|
||||
// 键名
|
||||
prop: string;
|
||||
// 组件属性(input-tag组件支持join,btnText,size属性)
|
||||
attrs?: IObject;
|
||||
// 初始值
|
||||
initialValue?: any;
|
||||
// 可选项(适用于select组件)
|
||||
options?: { label: string; value: any }[];
|
||||
// 初始化数据函数扩展
|
||||
initFn?: (formItem: IObject) => void;
|
||||
}>;
|
||||
// 是否开启展开和收缩
|
||||
isExpandable?: boolean;
|
||||
// 默认展示的表单项数量
|
||||
showNumber?: number;
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
const props = defineProps<{
|
||||
searchConfig: ISearchConfig;
|
||||
}
|
||||
const props = defineProps<IProps>();
|
||||
}>();
|
||||
// 自定义事件
|
||||
const emit = defineEmits<{
|
||||
queryClick: [queryParams: IObject];
|
||||
@@ -218,23 +188,28 @@ for (const item of formItems) {
|
||||
queryParams[item.prop] = item.initialValue ?? "";
|
||||
}
|
||||
}
|
||||
|
||||
// 重置操作
|
||||
function handleReset() {
|
||||
queryFormRef.value?.resetFields();
|
||||
emit("resetClick", queryParams);
|
||||
}
|
||||
|
||||
// 查询操作
|
||||
function handleQuery() {
|
||||
emit("queryClick", queryParams);
|
||||
}
|
||||
|
||||
// 获取分页数据
|
||||
function getQueryParams() {
|
||||
return queryParams;
|
||||
}
|
||||
|
||||
// 显示/隐藏 SearchForm
|
||||
function toggleVisible() {
|
||||
visible.value = !visible.value;
|
||||
}
|
||||
|
||||
// 关闭标签
|
||||
function handleCloseTag(prop: string, tag: string) {
|
||||
inputTagMap[prop].data.splice(inputTagMap[prop].data.indexOf(tag), 1);
|
||||
262
src/components/CURD/types.ts
Normal file
262
src/components/CURD/types.ts
Normal file
@@ -0,0 +1,262 @@
|
||||
import type {
|
||||
DialogProps,
|
||||
DrawerProps,
|
||||
FormItemRule,
|
||||
FormProps,
|
||||
PaginationProps,
|
||||
TableProps,
|
||||
} from "element-plus";
|
||||
import PageContent from "./PageContent.vue";
|
||||
import PageForm from "./PageForm.vue";
|
||||
import PageModal from "./PageModal.vue";
|
||||
import PageSearch from "./PageSearch.vue";
|
||||
|
||||
export type PageSearchInstance = InstanceType<typeof PageSearch>;
|
||||
export type PageContentInstance = InstanceType<typeof PageContent>;
|
||||
export type PageModalInstance = InstanceType<typeof PageModal>;
|
||||
export type PageFormInstance = InstanceType<typeof PageForm>;
|
||||
|
||||
export type IObject = Record<string, any>;
|
||||
|
||||
export interface IOperatData {
|
||||
name: string;
|
||||
row: any;
|
||||
column: any;
|
||||
$index: number;
|
||||
}
|
||||
|
||||
export interface ISearchConfig {
|
||||
// 页面名称(参与组成权限标识,如sys:user:xxx)
|
||||
pageName: string;
|
||||
// 表单项
|
||||
formItems: Array<{
|
||||
// 组件类型(如input,select等)
|
||||
type?: "input" | "select" | "tree-select" | "date-picker" | "input-tag";
|
||||
// 标签文本
|
||||
label: string;
|
||||
// 标签提示
|
||||
tips?: string;
|
||||
// 键名
|
||||
prop: string;
|
||||
// 组件属性(input-tag组件支持join,btnText,size属性)
|
||||
attrs?: IObject;
|
||||
// 初始值
|
||||
initialValue?: any;
|
||||
// 可选项(适用于select组件)
|
||||
options?: { label: string; value: any }[];
|
||||
// 初始化数据函数扩展
|
||||
initFn?: (formItem: IObject) => void;
|
||||
}>;
|
||||
// 是否开启展开和收缩
|
||||
isExpandable?: boolean;
|
||||
// 默认展示的表单项数量
|
||||
showNumber?: number;
|
||||
}
|
||||
|
||||
export interface IContentConfig<T = any> {
|
||||
// 页面名称(参与组成权限标识,如sys:user:xxx)
|
||||
pageName: string;
|
||||
// table组件属性
|
||||
table?: Omit<TableProps<any>, "data">;
|
||||
// pagination组件属性
|
||||
pagination?:
|
||||
| boolean
|
||||
| Partial<
|
||||
Omit<
|
||||
PaginationProps,
|
||||
"v-model:page-size" | "v-model:current-page" | "total" | "currentPage"
|
||||
>
|
||||
>;
|
||||
// 列表的网络请求函数(需返回promise)
|
||||
indexAction: (queryParams: T) => Promise<any>;
|
||||
// 默认的分页相关的请求参数
|
||||
request?: {
|
||||
pageName: string;
|
||||
limitName: string;
|
||||
};
|
||||
// 数据格式解析的回调函数
|
||||
parseData?: (res: any) => {
|
||||
total: number;
|
||||
list: IObject[];
|
||||
[key: string]: any;
|
||||
};
|
||||
// 修改属性的网络请求函数(需返回promise)
|
||||
modifyAction?: (data: {
|
||||
[key: string]: any;
|
||||
field: string;
|
||||
value: boolean | string | number;
|
||||
}) => Promise<any>;
|
||||
// 删除的网络请求函数(需返回promise)
|
||||
deleteAction?: (ids: string) => Promise<any>;
|
||||
// 后端导出的网络请求函数(需返回promise)
|
||||
exportAction?: (queryParams: T) => Promise<any>;
|
||||
// 前端全量导出的网络请求函数(需返回promise)
|
||||
exportsAction?: (queryParams: T) => Promise<IObject[]>;
|
||||
// 前端导入模板
|
||||
importsTemplate?: string | (() => Promise<any>);
|
||||
// 前端导入的网络请求函数(需返回promise)
|
||||
importsAction?: (data: IObject[]) => Promise<any>;
|
||||
// 主键名(默认为id)
|
||||
pk?: string;
|
||||
// 表格工具栏(默认支持add,delete,export,也可自定义)
|
||||
toolbar?: Array<
|
||||
| "add"
|
||||
| "delete"
|
||||
| "export"
|
||||
| {
|
||||
auth: string;
|
||||
icon?: string;
|
||||
name: string;
|
||||
text: string;
|
||||
}
|
||||
>;
|
||||
// 表格工具栏右侧图标
|
||||
defaultToolbar?: Array<
|
||||
| "refresh"
|
||||
| "filter"
|
||||
| "imports"
|
||||
| "exports"
|
||||
| "search"
|
||||
| {
|
||||
name: string;
|
||||
icon: string;
|
||||
title?: string;
|
||||
auth?: string;
|
||||
}
|
||||
>;
|
||||
// table组件列属性(额外的属性templet,operat,slotName)
|
||||
cols: Array<{
|
||||
type?: "default" | "selection" | "index" | "expand";
|
||||
label?: string;
|
||||
prop?: string;
|
||||
width?: string | number;
|
||||
align?: "left" | "center" | "right";
|
||||
columnKey?: string;
|
||||
reserveSelection?: boolean;
|
||||
// 列是否显示
|
||||
show?: boolean;
|
||||
// 模板
|
||||
templet?:
|
||||
| "image"
|
||||
| "list"
|
||||
| "url"
|
||||
| "switch"
|
||||
| "input"
|
||||
| "price"
|
||||
| "percent"
|
||||
| "icon"
|
||||
| "date"
|
||||
| "tool"
|
||||
| "custom";
|
||||
// image模板相关参数
|
||||
imageWidth?: number;
|
||||
imageHeight?: number;
|
||||
// list模板相关参数
|
||||
selectList?: Record<string, any>;
|
||||
// switch模板相关参数
|
||||
activeValue?: boolean | string | number;
|
||||
inactiveValue?: boolean | string | number;
|
||||
activeText?: string;
|
||||
inactiveText?: string;
|
||||
// input模板相关参数
|
||||
inputType?: string;
|
||||
// price模板相关参数
|
||||
priceFormat?: string;
|
||||
// date模板相关参数
|
||||
dateFormat?: string;
|
||||
// tool模板相关参数
|
||||
operat?: Array<
|
||||
| "edit"
|
||||
| "delete"
|
||||
| {
|
||||
auth: string;
|
||||
icon?: string;
|
||||
name: string;
|
||||
text: string;
|
||||
}
|
||||
>;
|
||||
// filter值拼接符
|
||||
filterJoin?: string;
|
||||
[key: string]: any;
|
||||
// 初始化数据函数
|
||||
initFn?: (item: IObject) => void;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface IModalConfig<T = any> {
|
||||
// 页面名称
|
||||
pageName?: string;
|
||||
// 主键名(主要用于编辑数据,默认为id)
|
||||
pk?: string;
|
||||
// 组件类型
|
||||
component?: "dialog" | "drawer";
|
||||
// dialog组件属性
|
||||
dialog?: Partial<Omit<DialogProps, "modelValue">>;
|
||||
// drawer组件属性
|
||||
drawer?: Partial<Omit<DrawerProps, "modelValue">>;
|
||||
// form组件属性
|
||||
form?: IForm;
|
||||
// 表单项
|
||||
formItems: IFormItems<T>;
|
||||
// 提交之前处理
|
||||
beforeSubmit?: (data: T) => void;
|
||||
// 提交的网络请求函数(需返回promise)
|
||||
formAction: (data: T) => Promise<any>;
|
||||
}
|
||||
|
||||
export type IForm = Partial<Omit<FormProps, "model" | "rules">>;
|
||||
|
||||
// 表单项
|
||||
export type IFormItems<T = any> = Array<{
|
||||
// 组件类型(如input,select,radio,custom等,默认input)
|
||||
type?:
|
||||
| "input"
|
||||
| "select"
|
||||
| "radio"
|
||||
| "checkbox"
|
||||
| "tree-select"
|
||||
| "date-picker"
|
||||
| "input-number"
|
||||
| "text"
|
||||
| "custom";
|
||||
// 组件属性
|
||||
attrs?: IObject;
|
||||
// 组件可选项(适用于select,radio,checkbox组件)
|
||||
options?: Array<{
|
||||
label: string;
|
||||
value: any;
|
||||
disabled?: boolean;
|
||||
[key: string]: any;
|
||||
}>;
|
||||
// 插槽名(适用于组件类型为custom)
|
||||
slotName?: string;
|
||||
// 标签文本
|
||||
label: string;
|
||||
// 标签提示
|
||||
tips?: string;
|
||||
// 键名
|
||||
prop: string;
|
||||
// 验证规则
|
||||
rules?: FormItemRule[];
|
||||
// 初始值
|
||||
initialValue?: any;
|
||||
// 是否隐藏
|
||||
hidden?: boolean;
|
||||
// 监听函数
|
||||
watch?: (newValue: any, oldValue: any, data: T, items: IObject[]) => void;
|
||||
// 计算属性函数
|
||||
computed?: (data: T) => any;
|
||||
// 监听收集函数
|
||||
watchEffect?: (data: T) => void;
|
||||
// 初始化数据函数扩展
|
||||
initFn?: (item: IObject) => void;
|
||||
}>;
|
||||
|
||||
export interface IPageForm {
|
||||
// 主键名(主要用于编辑数据,默认为id)
|
||||
pk?: string;
|
||||
// form组件属性
|
||||
form?: IForm;
|
||||
// 表单项
|
||||
formItems: IFormItems;
|
||||
}
|
||||
@@ -1,15 +1,16 @@
|
||||
import { ref } from "vue";
|
||||
import type PageSearch from "@/components/PageSearch/index.vue";
|
||||
import type PageContent from "@/components/PageContent/index.vue";
|
||||
import type PageModal from "@/components/PageModal/index.vue";
|
||||
import type { IOperatData, IObject } from "@/components/PageContent/index.vue";
|
||||
export type { IOperatData, IObject };
|
||||
import type {
|
||||
IObject,
|
||||
PageContentInstance,
|
||||
PageModalInstance,
|
||||
PageSearchInstance,
|
||||
} from "./types";
|
||||
|
||||
function usePage() {
|
||||
const searchRef = ref<InstanceType<typeof PageSearch>>();
|
||||
const contentRef = ref<InstanceType<typeof PageContent>>();
|
||||
const addModalRef = ref<InstanceType<typeof PageModal>>();
|
||||
const editModalRef = ref<InstanceType<typeof PageModal>>();
|
||||
const searchRef = ref<PageSearchInstance>();
|
||||
const contentRef = ref<PageContentInstance>();
|
||||
const addModalRef = ref<PageModalInstance>();
|
||||
const editModalRef = ref<PageModalInstance>();
|
||||
|
||||
// 搜索
|
||||
function handleQueryClick(queryParams: IObject) {
|
||||
@@ -1,64 +0,0 @@
|
||||
import type {
|
||||
DialogProps,
|
||||
DrawerProps,
|
||||
FormProps,
|
||||
FormItemRule,
|
||||
} from "element-plus";
|
||||
|
||||
// dialog组件属性
|
||||
export type IDialog = Partial<Omit<DialogProps, "modelValue">>;
|
||||
|
||||
// drawer组件属性
|
||||
export type IDrawer = Partial<Omit<DrawerProps, "modelValue">>;
|
||||
|
||||
// form组件属性
|
||||
export type IForm = Partial<Omit<FormProps, "model" | "rules">>;
|
||||
|
||||
// 对象类型
|
||||
export type IObject = Record<string, any>;
|
||||
|
||||
// 表单项
|
||||
export type IFormItems<T = any> = Array<{
|
||||
// 组件类型(如input,select,radio,custom等,默认input)
|
||||
type?:
|
||||
| "input"
|
||||
| "select"
|
||||
| "radio"
|
||||
| "checkbox"
|
||||
| "tree-select"
|
||||
| "date-picker"
|
||||
| "input-number"
|
||||
| "text"
|
||||
| "custom";
|
||||
// 组件属性
|
||||
attrs?: IObject;
|
||||
// 组件可选项(适用于select,radio,checkbox组件)
|
||||
options?: Array<{
|
||||
label: string;
|
||||
value: any;
|
||||
disabled?: boolean;
|
||||
[key: string]: any;
|
||||
}>;
|
||||
// 插槽名(适用于组件类型为custom)
|
||||
slotName?: string;
|
||||
// 标签文本
|
||||
label: string;
|
||||
// 标签提示
|
||||
tips?: string;
|
||||
// 键名
|
||||
prop: string;
|
||||
// 验证规则
|
||||
rules?: FormItemRule[];
|
||||
// 初始值
|
||||
initialValue?: any;
|
||||
// 是否隐藏
|
||||
hidden?: boolean;
|
||||
// 监听函数
|
||||
watch?: (newValue: any, oldValue: any, data: T, items: IObject[]) => void;
|
||||
// 计算属性函数
|
||||
computed?: (data: T) => any;
|
||||
// 监听收集函数
|
||||
watchEffect?: (data: T) => void;
|
||||
// 初始化数据函数扩展
|
||||
initFn?: (item: IObject) => void;
|
||||
}>;
|
||||
4
src/typings/auto-imports.d.ts
vendored
4
src/typings/auto-imports.d.ts
vendored
@@ -325,14 +325,12 @@ declare module "vue" {
|
||||
interface GlobalComponents {}
|
||||
interface ComponentCustomProperties {
|
||||
readonly EffectScope: UnwrapRef<(typeof import("vue"))["EffectScope"]>;
|
||||
readonly ElForm: UnwrapRef<(typeof import("element-plus/es"))["ElForm"]>;
|
||||
readonly ElMessage: UnwrapRef<
|
||||
(typeof import("element-plus/es"))["ElMessage"]
|
||||
>;
|
||||
readonly ElMessageBox: UnwrapRef<
|
||||
(typeof import("element-plus/es"))["ElMessageBox"]
|
||||
>;
|
||||
readonly ElTree: UnwrapRef<(typeof import("element-plus/es"))["ElTree"]>;
|
||||
readonly acceptHMRUpdate: UnwrapRef<
|
||||
(typeof import("pinia"))["acceptHMRUpdate"]
|
||||
>;
|
||||
@@ -1055,14 +1053,12 @@ declare module "@vue/runtime-core" {
|
||||
interface GlobalComponents {}
|
||||
interface ComponentCustomProperties {
|
||||
readonly EffectScope: UnwrapRef<(typeof import("vue"))["EffectScope"]>;
|
||||
readonly ElForm: UnwrapRef<(typeof import("element-plus/es"))["ElForm"]>;
|
||||
readonly ElMessage: UnwrapRef<
|
||||
(typeof import("element-plus/es"))["ElMessage"]
|
||||
>;
|
||||
readonly ElMessageBox: UnwrapRef<
|
||||
(typeof import("element-plus/es"))["ElMessageBox"]
|
||||
>;
|
||||
readonly ElTree: UnwrapRef<(typeof import("element-plus/es"))["ElTree"]>;
|
||||
readonly acceptHMRUpdate: UnwrapRef<
|
||||
(typeof import("pinia"))["acceptHMRUpdate"]
|
||||
>;
|
||||
|
||||
23
src/typings/components.d.ts
vendored
23
src/typings/components.d.ts
vendored
@@ -11,6 +11,7 @@ declare module "vue" {
|
||||
AppMain: (typeof import("./../layout/components/AppMain/index.vue"))["default"];
|
||||
BarChart: (typeof import("./../views/dashboard/components/BarChart.vue"))["default"];
|
||||
Breadcrumb: (typeof import("./../components/Breadcrumb/index.vue"))["default"];
|
||||
CURD: (typeof import("./../components/CURD/index.vue"))["default"];
|
||||
DeptTree: (typeof import("./../views/system/user/components/dept-tree.vue"))["default"];
|
||||
Dictionary: (typeof import("./../components/Dictionary/index.vue"))["default"];
|
||||
DictItem: (typeof import("./../views/system/dict/components/dict-item.vue"))["default"];
|
||||
@@ -53,16 +54,13 @@ declare module "vue" {
|
||||
ElSwitch: (typeof import("element-plus/es"))["ElSwitch"];
|
||||
ElTable: (typeof import("element-plus/es"))["ElTable"];
|
||||
ElTableColumn: (typeof import("element-plus/es"))["ElTableColumn"];
|
||||
ElTabPane: (typeof import("element-plus/es"))["ElTabPane"];
|
||||
ElTabs: (typeof import("element-plus/es"))["ElTabs"];
|
||||
ElTag: (typeof import("element-plus/es"))["ElTag"];
|
||||
ElText: (typeof import("element-plus/es"))["ElText"];
|
||||
ElTooltip: (typeof import("element-plus/es"))["ElTooltip"];
|
||||
ElTree: (typeof import("element-plus/es"))["ElTree"];
|
||||
ElTreeSelect: (typeof import("element-plus/es"))["ElTreeSelect"];
|
||||
ElUpload: (typeof import("element-plus/es"))["ElUpload"];
|
||||
ElWatermark: (typeof import("element-plus/es"))["ElWatermark"];
|
||||
Form: (typeof import("./../components/PageModal/Form.vue"))["default"];
|
||||
Form: (typeof import("./../components/CURD/Form.vue"))["default"];
|
||||
FunnelChart: (typeof import("./../views/dashboard/components/FunnelChart.vue"))["default"];
|
||||
GithubCorner: (typeof import("./../components/GithubCorner/index.vue"))["default"];
|
||||
Hamburger: (typeof import("./../components/Hamburger/index.vue"))["default"];
|
||||
@@ -70,26 +68,17 @@ declare module "vue" {
|
||||
IEpArrowDown: (typeof import("~icons/ep/arrow-down"))["default"];
|
||||
IEpArrowUp: (typeof import("~icons/ep/arrow-up"))["default"];
|
||||
IEpClose: (typeof import("~icons/ep/close"))["default"];
|
||||
IEpDelete: (typeof import("~icons/ep/delete"))["default"];
|
||||
IEpDownload: (typeof import("~icons/ep/download"))["default"];
|
||||
IEpEdit: (typeof import("~icons/ep/edit"))["default"];
|
||||
IEpPlus: (typeof import("~icons/ep/plus"))["default"];
|
||||
IEpPosition: (typeof import("~icons/ep/position"))["default"];
|
||||
IEpQuestionFilled: (typeof import("~icons/ep/question-filled"))["default"];
|
||||
IEpRefresh: (typeof import("~icons/ep/refresh"))["default"];
|
||||
IEpRefreshLeft: (typeof import("~icons/ep/refresh-left"))["default"];
|
||||
IEpSearch: (typeof import("~icons/ep/search"))["default"];
|
||||
IEpTop: (typeof import("~icons/ep/top"))["default"];
|
||||
IEpUploadFilled: (typeof import("~icons/ep/upload-filled"))["default"];
|
||||
LangSelect: (typeof import("./../components/LangSelect/index.vue"))["default"];
|
||||
LayoutSelect: (typeof import("./../layout/components/Settings/components/LayoutSelect.vue"))["default"];
|
||||
MultiUpload: (typeof import("./../components/Upload/MultiUpload.vue"))["default"];
|
||||
NavBar: (typeof import("./../layout/components/NavBar/index.vue"))["default"];
|
||||
NavbarLeft: (typeof import("./../layout/components/NavBar/components/NavbarLeft.vue"))["default"];
|
||||
NavbarRight: (typeof import("./../layout/components/NavBar/components/NavbarRight.vue"))["default"];
|
||||
PageContent: (typeof import("./../components/PageContent/index.vue"))["default"];
|
||||
PageModal: (typeof import("./../components/PageModal/index.vue"))["default"];
|
||||
PageSearch: (typeof import("./../components/PageSearch/index.vue"))["default"];
|
||||
PageContent: (typeof import("./../components/CURD/PageContent.vue"))["default"];
|
||||
PageForm: (typeof import("./../components/CURD/PageForm.vue"))["default"];
|
||||
PageModal: (typeof import("./../components/CURD/PageModal.vue"))["default"];
|
||||
PageSearch: (typeof import("./../components/CURD/PageSearch.vue"))["default"];
|
||||
Pagination: (typeof import("./../components/Pagination/index.vue"))["default"];
|
||||
PieChart: (typeof import("./../views/dashboard/components/PieChart.vue"))["default"];
|
||||
RadarChart: (typeof import("./../views/dashboard/components/RadarChart.vue"))["default"];
|
||||
|
||||
@@ -2,7 +2,7 @@ import DeptAPI from "@/api/dept";
|
||||
import RoleAPI from "@/api/role";
|
||||
import UserAPI from "@/api/user";
|
||||
import type { UserForm } from "@/api/user/model";
|
||||
import type { IModalConfig } from "@/components/PageModal/index.vue";
|
||||
import type { IModalConfig } from "@/components/CURD/types";
|
||||
|
||||
const modalConfig: IModalConfig<UserForm> = {
|
||||
pageName: "sys:user",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import UserAPI from "@/api/user";
|
||||
import RoleAPI from "@/api/role";
|
||||
import type { UserQuery } from "@/api/user/model";
|
||||
import type { IContentConfig } from "@/components/PageContent/index.vue";
|
||||
import type { IContentConfig } from "@/components/CURD/types";
|
||||
|
||||
const contentConfig: IContentConfig<UserQuery> = {
|
||||
pageName: "sys:user",
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import type { IContentConfig } from "@/components/PageContent/index.vue";
|
||||
import type { IContentConfig } from "@/components/CURD/types";
|
||||
|
||||
const contentConfig: IContentConfig = {
|
||||
pageName: "sys:user",
|
||||
table: {
|
||||
showOverflowTooltip: true,
|
||||
},
|
||||
toolbar: [],
|
||||
indexAction: function (params) {
|
||||
// 模拟发起网络请求获取列表数据
|
||||
// console.log("indexAction:", params);
|
||||
return Promise.resolve({
|
||||
total: 2,
|
||||
@@ -44,11 +46,13 @@ const contentConfig: IContentConfig = {
|
||||
});
|
||||
},
|
||||
modifyAction(data) {
|
||||
console.log("modifyAction:", data);
|
||||
// 模拟发起网络请求修改字段
|
||||
// console.log("modifyAction:", data);
|
||||
ElMessage.success(JSON.stringify(data));
|
||||
return Promise.resolve(null);
|
||||
},
|
||||
cols: [
|
||||
{ type: "selection", width: 50, align: "center" },
|
||||
{ type: "index", width: 50, align: "center" },
|
||||
{ label: "ID", align: "center", prop: "id", show: false },
|
||||
{ label: "用户名", align: "center", prop: "username" },
|
||||
{ label: "图片", align: "center", prop: "avatar", templet: "image" },
|
||||
@@ -106,14 +110,6 @@ const contentConfig: IContentConfig = {
|
||||
templet: "date",
|
||||
dateFormat: "YYYY/MM/DD HH:mm:ss",
|
||||
},
|
||||
{
|
||||
label: "操作",
|
||||
align: "center",
|
||||
fixed: "right",
|
||||
width: 150,
|
||||
templet: "tool",
|
||||
operat: ["edit", "delete"],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import DeptAPI from "@/api/dept";
|
||||
import RoleAPI from "@/api/role";
|
||||
import UserAPI from "@/api/user";
|
||||
import type { UserForm } from "@/api/user/model";
|
||||
import type { IModalConfig } from "@/components/PageModal/index.vue";
|
||||
import type { IModalConfig } from "@/components/CURD/types";
|
||||
import { DeviceEnum } from "@/enums/DeviceEnum";
|
||||
import { useAppStore } from "@/store";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import DeptAPI from "@/api/dept";
|
||||
import type { ISearchConfig } from "@/components/PageSearch/index.vue";
|
||||
import type { ISearchConfig } from "@/components/CURD/types";
|
||||
|
||||
const searchConfig: ISearchConfig = {
|
||||
pageName: "sys:user",
|
||||
|
||||
@@ -1,72 +1,88 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-link
|
||||
href="https://gitee.com/youlaiorg/vue3-element-admin/blob/master/src/views/demo/curd/index.vue"
|
||||
type="primary"
|
||||
target="_blank"
|
||||
class="mb-10"
|
||||
>
|
||||
示例源码 请点击>>>>
|
||||
</el-link>
|
||||
|
||||
<!-- 搜索 -->
|
||||
<page-search
|
||||
ref="searchRef"
|
||||
:search-config="searchConfig"
|
||||
@query-click="handleQueryClick"
|
||||
@reset-click="handleResetClick"
|
||||
/>
|
||||
<div class="flex-x-between mb-10">
|
||||
<el-link
|
||||
href="https://gitee.com/youlaiorg/vue3-element-admin/blob/master/src/views/demo/curd/index.vue"
|
||||
type="primary"
|
||||
target="_blank"
|
||||
>
|
||||
示例源码 请点击>>>>
|
||||
</el-link>
|
||||
<el-button type="primary" plain round size="small" @click="isA = !isA">
|
||||
切换示例
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 列表 -->
|
||||
<page-content
|
||||
ref="contentRef"
|
||||
:content-config="contentConfig"
|
||||
@add-click="handleAddClick"
|
||||
@edit-click="handleEditClick"
|
||||
@export-click="handleExportClick"
|
||||
@search-click="handleSearchClick"
|
||||
@toolbar-click="handleToolbarClick"
|
||||
@operat-click="handleOperatClick"
|
||||
@filter-change="handleFilterChange"
|
||||
>
|
||||
<template #status="scope">
|
||||
<el-tag :type="scope.row[scope.prop] == 1 ? 'success' : 'info'">
|
||||
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</page-content>
|
||||
<template v-if="isA">
|
||||
<!-- 搜索 -->
|
||||
<page-search
|
||||
ref="searchRef"
|
||||
:search-config="searchConfig"
|
||||
@query-click="handleQueryClick"
|
||||
@reset-click="handleResetClick"
|
||||
/>
|
||||
|
||||
<!-- 新增 -->
|
||||
<page-modal
|
||||
ref="addModalRef"
|
||||
:modal-config="addModalConfig"
|
||||
@submit-click="handleSubmitClick"
|
||||
>
|
||||
<template #gender="scope">
|
||||
<dictionary v-model="scope.formData[scope.prop]" type-code="gender" />
|
||||
</template>
|
||||
</page-modal>
|
||||
<!-- 列表 -->
|
||||
<page-content
|
||||
ref="contentRef"
|
||||
:content-config="contentConfig"
|
||||
@add-click="handleAddClick"
|
||||
@edit-click="handleEditClick"
|
||||
@export-click="handleExportClick"
|
||||
@search-click="handleSearchClick"
|
||||
@toolbar-click="handleToolbarClick"
|
||||
@operat-click="handleOperatClick"
|
||||
@filter-change="handleFilterChange"
|
||||
>
|
||||
<template #status="scope">
|
||||
<el-tag :type="scope.row[scope.prop] == 1 ? 'success' : 'info'">
|
||||
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</page-content>
|
||||
|
||||
<!-- 编辑 -->
|
||||
<page-modal
|
||||
ref="editModalRef"
|
||||
:modal-config="editModalConfig"
|
||||
@submit-click="handleSubmitClick"
|
||||
>
|
||||
<template #gender="scope">
|
||||
<dictionary v-model="scope.formData[scope.prop]" type-code="gender" />
|
||||
</template>
|
||||
</page-modal>
|
||||
<!-- 新增 -->
|
||||
<page-modal
|
||||
ref="addModalRef"
|
||||
:modal-config="addModalConfig"
|
||||
@submit-click="handleSubmitClick"
|
||||
>
|
||||
<template #gender="scope">
|
||||
<dictionary v-model="scope.formData[scope.prop]" type-code="gender" />
|
||||
</template>
|
||||
</page-modal>
|
||||
|
||||
<!-- 编辑 -->
|
||||
<page-modal
|
||||
ref="editModalRef"
|
||||
:modal-config="editModalConfig"
|
||||
@submit-click="handleSubmitClick"
|
||||
>
|
||||
<template #gender="scope">
|
||||
<dictionary v-model="scope.formData[scope.prop]" type-code="gender" />
|
||||
</template>
|
||||
</page-modal>
|
||||
</template>
|
||||
<template v-else>
|
||||
<page-content ref="contentRef" :content-config="contentConfig2">
|
||||
<template #status="scope">
|
||||
<el-tag :type="scope.row[scope.prop] == 1 ? 'success' : 'info'">
|
||||
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</page-content>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import UserAPI from "@/api/user";
|
||||
import type { IObject, IOperatData } from "@/hooks/usePage";
|
||||
import usePage from "@/hooks/usePage";
|
||||
import type { IObject, IOperatData } from "@/components/CURD/types";
|
||||
import usePage from "@/components/CURD/usePage";
|
||||
import addModalConfig from "./config/add";
|
||||
import contentConfig from "./config/content";
|
||||
// import contentConfig from "./config/content2";
|
||||
import contentConfig2 from "./config/content2";
|
||||
import editModalConfig from "./config/edit";
|
||||
import searchConfig from "./config/search";
|
||||
|
||||
@@ -120,4 +136,7 @@ function handleOperatClick(data: IOperatData) {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 切换示例
|
||||
const isA = ref(true);
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user