sen
1 天以前 7ed2a032d0724e68aec8af940f2ce0023a9f0eb7
ui/admin-ui3/src/hooks/usePagePlus.ts
@@ -1,162 +1,184 @@
import {reactive, ref, Ref, UnwrapRef} from "vue";
import {PageF, PageInterface, PagesInterface} from "@/utils/globalInterface";
import {ElMessage, ElMessageBox} from "element-plus";
import {requestType} from "@/utils/request";
import { reactive, ref, onMounted, onUnmounted } from "vue"; // 1. 引入生命周期钩子
import { PageF, PagesInterface } from "@/utils/globalInterface";
import { ElMessage, ElMessageBox } from "element-plus";
import { requestType } from "@/utils/request";
/**
 * @description usePage 接收一个opts 参数,返回通用页面所需数据
 * @param {Object} opts.form 表单对象
 * @param {string} opts.title 页面标题
 * @param {Object} opts.queryParams 查询参数
 * @param {Function} opts.getListApi 获取列表数据的接口
 * @param {Function} opts.getDetailApi 获取详情数据的接口
 * @param {Function} opts.deleteApi 删除数据的接口
 * @param {Function} opts.exportApi 导出数据的接口
 * @param {Function} opts.getBeginListFunc 获取前getList数据的接口
 * @param {Function} opts.getListFunc 执行完getList成功后执行的逻辑
 * @param {Function} opts.resetFunc 执行完reset成功后执行的逻辑
 * @param {Function} opts.resetQueryFunc 执行完resetQuery成功后执行的逻辑
 * @param {Function} opts.handleSelectionChangeFunc 执行完handleSelectionChange成功后执行的逻辑
 * @description usePagePlus 增加全局回车搜索逻辑
 */
export const usePagePlus = (opts: {
    form?:any,
    option?:any,
    idKey?:any,
    page:any,
    queryParams?:any,
    getListApi?:requestType,
    addApi?:requestType,
    updateApi?:requestType,
    getDetailApi?:requestType,
    deleteApi?:requestType,
    exportApi?:requestType,
    getBeginListFunc?:Function,
    getListFunc?:Function,
    resetFunc?:Function,
    handleQueryFunc?:Function,
    resetQueryFunc?:Function,
    handleSelectionChangeFunc?:Function,
    handleAddFunc?:Function,
    handleUpdateFunc?:Function,
    handleBeforeOpenFunc?:Function,
    handleEndOpenFunc?:Function,
    rowSaveBegin?:Function,
    rowUpdateBegin?:Function,
})=>{
    const pageF = reactive({...PageF});
    form?: any,
    option?: any,
    idKey?: any,
    page: any,
    queryParams?: any, // 确保外部传入的是 ref 对象
    getListApi?: requestType,
    addApi?: requestType,
    updateApi?: requestType,
    getDetailApi?: requestType,
    deleteApi?: requestType,
    exportApi?: requestType,
    getBeginListFunc?: Function,
    getListFunc?: Function,
    resetFunc?: Function,
    handleQueryFunc?: Function,
    resetQueryFunc?: Function,
    handleSelectionChangeFunc?: Function,
    handleAddFunc?: Function,
    handleUpdateFunc?: Function,
    handleBeforeOpenFunc?: Function,
    handleEndOpenFunc?: Function,
    rowSaveBegin?: Function,
    rowUpdateBegin?: Function,
}) => {
    const pageF = reactive({ ...PageF });
    const tableData = ref([]);
    opts.idKey = opts.idKey?opts.idKey: 'id';
    opts.idKey = opts.idKey ? opts.idKey : 'id';
    /**
     * 获取列表数据
     */
    const onLoad = (page:PagesInterface, params?:Object) =>{
        if(opts.getBeginListFunc){
    const onLoad = (page: PagesInterface, params?: Object) => {
        if (opts.getBeginListFunc) {
            params = opts.getBeginListFunc!(params)
        }
        pageF.loading = true;
        opts.getListApi!({pageNum:page.currentPage,pageSize:page.pageSize,...Object.assign(params?params:{},opts.queryParams.value)}).then((res:any)=>{
            tableData.value = res.rows|| [];
        const queryParams = filterEmptyParams(opts.queryParams.value);
        opts.getListApi!({
            pageNum: page.currentPage,
            pageSize: page.pageSize,
            ...Object.assign(params ? params : {}, opts.queryParams.value)
        }).then((res: any) => {
            tableData.value = res.rows || [];
            pageF.loading = false;
            opts.page.total = res.total || 0;
            if(opts.getListFunc){
            if (opts.getListFunc) {
                opts.getListFunc!(res)
            }
        })
    }
    /**
     * 清空搜索回调方法
     * 2. 新增:手动触发搜索逻辑 (用于回车搜索)
     */
    const searchReset = () =>{
        opts.queryParams = {};
        if (opts.handleQueryFunc){
    const manualSearch = () => {
        if (!opts.queryParams || !opts.queryParams.value) return; // 容错处理
        opts.page.currentPage = 1; // 回车搜索默认切回第一页
        if (opts.handleQueryFunc) {
            opts.handleQueryFunc();
        }
        onLoad(opts.page, opts.queryParams.value);
    }
    /**
     * 3. 新增:全局按键监听处理函数
     */
    const handleKeyDown = (e: KeyboardEvent) => {
        // 判断是否按下 Enter 键
        if (e.key === 'Enter') {
            // 关键判断:为了防止在新增/编辑弹窗输入时触发背景列表刷新
            // 只有当焦点在 Input 框中且不在弹窗内(通常根据业务状态判断)才触发
            const target = e.target as HTMLElement;
            if (target.tagName === 'INPUT') {
                // 如果页面上有 open 状态控制弹窗,可以在此增加判断条件
                manualSearch();
            }
        }
    };
    // 4. 挂载时监听,卸载时移除,确保不影响其他非 Avue 页面
    onMounted(() => {
        window.addEventListener("keydown", handleKeyDown);
    });
    onUnmounted(() => {
        window.removeEventListener("keydown", handleKeyDown);
    });
    /** 清空搜索回调方法 */
    const searchReset = () => {
     //   opts.queryParams = {}; // 修改为操作 .value
     // ✅ 正确写法:清空 ref 内部的值
    if (opts.queryParams && opts.queryParams.value) {
        // 方案 A:直接清空对象内部属性
        Object.keys(opts.queryParams.value).forEach(key => {
            delete opts.queryParams.value[key];
        });
      }
        if (opts.handleQueryFunc) {
            opts.handleQueryFunc();
        }
        onLoad(opts.page);
    }
    /** 搜索按钮操作 */
    const searchChange = (params:any, done:any) => {
        // opts.queryParams = params;
    const searchChange = (params: any, done: any) => {
        opts.page.currentPage = 1;
        if (opts.handleQueryFunc){
        if (opts.handleQueryFunc) {
            opts.handleQueryFunc();
        }
        onLoad(opts.page,params);
        onLoad(opts.page, params);
        done();
    }
    // 多选框选中数据
    // --- 以下保持原有逻辑不变 ---
    const selectionChange = (selection?: any[]) => {
        pageF.ids = selection!.map(item => item[opts.idKey]);
        pageF.single = selection!.length != 1;
        pageF.multiple = !selection!.length;
        if (opts.handleSelectionChangeFunc){
        if (opts.handleSelectionChangeFunc) {
            opts.handleSelectionChangeFunc!(selection);
        }
    }
    /** 新增操作 */
    const rowSave = (row:any, done:any, loading:any) => {
        if (opts.rowSaveBegin){
            opts.rowSaveBegin!(row,loading);
    const rowSave = (row: any, done: any, loading: any) => {
        if (opts.rowSaveBegin) {
            opts.rowSaveBegin!(row, loading);
        }
        opts.addApi!(row).then(()=>{
            ElMessage({
                message: "新增成功!",
                type: 'success'
            })
        opts.addApi!(row).then(() => {
            ElMessage({ message: "新增成功!", type: 'success' });
            onLoad(opts.page);
            done()
        }).catch(()=>{
            loading()
        })
            done();
        }).catch(() => { loading() })
    }
    /** 修改操作 */
    const rowUpdate = (row:any, index:any, done:any, loading:any) => {
        if (opts.rowUpdateBegin){
            opts.rowUpdateBegin!(row,loading);
    const rowUpdate = (row: any, index: any, done: any, loading: any) => {
        if (opts.rowUpdateBegin) {
            opts.rowUpdateBegin!(row, loading);
        }
        opts.updateApi!(row).then((response:any) => {
            ElMessage({
                message: "修改成功!",
                type: 'success'
            })
        opts.updateApi!(row).then((response: any) => {
            ElMessage({ message: "修改成功!", type: 'success' });
            onLoad(opts.page);
            done()
        }).catch(()=>{
            loading()
        })
            done();
        }).catch(() => { loading() })
    }
    const handleUpdate = ()=>{
        if ( !(pageF?.ids)|| pageF?.ids?.length === 0) {
            ElMessage({
                message: "请选择至少一条数据!",
                type: 'warning'
            })
            return;
        }
        if(opts.handleUpdateFunc){
            opts.handleUpdateFunc!()
        }
    }
    const rowDel  = (row:any) =>{
        ElMessageBox.confirm("确定将选择数据删除?", '系统提示', {confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning'}).then(() => {
    const rowDel = (row: any) => {
        ElMessageBox.confirm("确定将选择数据删除?", '系统提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
            return opts.deleteApi!(row[opts.idKey]);
        }).then(() => {
            onLoad(opts.page);
            ElMessage({
                message: "删除成功!",
                type: 'success'
            })
            ElMessage({ message: "删除成功!", type: 'success' });
        });
    }
    const refreshChange = () => {
        onLoad(opts.page, opts.queryParams.value);
    }
    const currentChange = (currentPage: number) => {
        opts.page.currentPage = currentPage;
    }
    const sizeChange = (pageSize: number) => {
        opts.page.pageSize = pageSize;
    }
      /**
     * 导出
     */
    const handleExport =()=>{
        const queryParams = filterEmptyParams(opts.queryParams.value);
        opts.exportApi!( opts.queryParams.value);
    }
    const handleDelete  = () =>{
        if ( !(pageF?.ids)|| pageF?.ids?.length === 0) {
@@ -176,40 +198,33 @@
            })
        });
    }
  const handleUpdate = ()=>{
        if ( !(pageF?.ids)|| pageF?.ids?.length === 0) {
            ElMessage({
                message: "请选择至少一条数据!",
                type: 'warning'
            })
            return;
        }
        if(opts.handleUpdateFunc){
            opts.handleUpdateFunc!()
        }
    }
    /**
     * 导出
     */
    const handleExport =()=>{
        console.log(opts.queryParams.value)
        opts.exportApi!(opts.queryParams.value);
    }
    const beforeOpen = (done:any, type:string) => {
        if(opts.handleBeforeOpenFunc){
            opts.handleBeforeOpenFunc!(type)
 * 过滤空字符串参数
 */
const filterEmptyParams = (params: any) => {
    const result: any = {};
    for (const key in params) {
        const val = params[key];
        // 过滤空字符串、null、undefined
        if (val !== '' && val !== null && val !== undefined) {
            result[key] = val;
        }
        if (["edit", "view"].includes(type)) {
            opts.getDetailApi!(opts.form.value[opts.idKey]).then(res => {
                opts.form.value = res.data;
                if(opts.handleEndOpenFunc){
                    opts.handleEndOpenFunc!(type,res)
                }
            });
        }
        done();
    }
    const currentChange = (currentPage:number) => {
        opts.page.currentPage = currentPage;
    }
    const sizeChange = (pageSize:number) => {
        opts.page.pageSize = pageSize;
    }
    const refreshChange = () => {
        onLoad(opts.page,opts.queryParams.value);
    }
    return result;
};
    return {
        pageF,
        tableData,
@@ -219,14 +234,24 @@
        selectionChange,
        rowSave,
        rowUpdate,
        rowDel,
        handleDelete,
        handleExport,
        beforeOpen,
        handleDelete,
        handleUpdate,
        rowDel,
        refreshChange,
        currentChange,
        sizeChange,
        handleUpdate,
        refreshChange
        manualSearch, // 导出此方法备用
        // ...其他原有返回项
        beforeOpen: (done: any, type: string) => {
            if (opts.handleBeforeOpenFunc) opts.handleBeforeOpenFunc!(type);
            if (["edit", "view"].includes(type)) {
                opts.getDetailApi!(opts.form.value[opts.idKey]).then(res => {
                    opts.form.value = res.data;
                    if (opts.handleEndOpenFunc) opts.handleEndOpenFunc!(type, res);
                });
            }
            done();
        }
    }
}
}