import { createVNode, inject } from 'vue'; import { NsMessage } from '../component/message'; import { NsModal } from '../component/modal'; import { ExclamationCircleOutlined } from '@ant-design/icons-vue'; import { useRouter, useRoute } from 'vue-router'; import { cloneDeep, isBoolean, isEmpty, isFunction, isString, isUndefined } from 'lodash-es'; import { useParams } from '/nerv-lib/use/use-params'; import { usePath } from '/nerv-lib/use/use-path'; import { useApi } from '/nerv-lib/use/use-api'; import type { AxiosRequestConfig } from 'axios'; import { authorizationService } from '/nerv-base/store/modules/authorization-service'; import { stringUtil } from '/nerv-lib/util/string-util'; import { appConfigStore } from '/nerv-base/store/modules/app-config'; import { xlsxExport, xlsxImport } from '/nerv-lib/util/xlsx-util'; export interface Confirm { title: string; // 弹窗标题 content: string; // 弹窗内容 icon: string; //弹窗图标 okButtonProps: object; okText: string; //确定按钮文本 } export interface Action { label: string; //操作中文名 name: string; //操作英文名 openPermission?: boolean; // true则不鉴权 checkApi?: string | Function | AxiosRequestConfig; // 检查api checkDynamicParams?: string | Array | object; //check api传参 || url传参 checkDefaultParams?: object; //check默认参数 固定值 route?: string | Recordable; // 配置了路由则直接跳转 confirm?: boolean | Confirm; //先弹窗再操作, true则使用默认显示方案 showSuccess?: Boolean; api?: string | Function | AxiosRequestConfig; // 自动请求api dynamicParams?: string | Array | object; //api传参 || url传参 defaultParams?: object; //默认参数 固定值 handle?: Function; //自定义回调,路由模式不触发 finalHandle?: Function; //最终执行的函数 ifShow?: boolean | Function; //显示依赖 type?: string; //按钮 primary | ghost | dashed | link | text | default dynamicDisabled?: boolean | Function; isReload?: boolean; state?: String; // edit 为编辑态 其他为编辑中 extra?: Recordable; } /** * step1:检测route,有则直接跳转。 * step2:检测api,有则设置handle先行请求api,请求成功,有默认handle则执行。 * step3:检测confirm,有则先弹窗,再执行step2 */ interface actionParams { reload?: Function; } export function useAction(actionParams: actionParams = {}) { const router = useRouter(); const route = useRoute(); const { reload } = actionParams; const { getPath } = usePath(); const { httpRequest } = useApi(); const authService = authorizationService(); const appConfig = appConfigStore(); //todo 类型定义需简化 const { tableEdit, tableSave, tableCancel, addRow, validate, getValue, getKey, tableDelete } = inject('tableEdit', { tableEdit: () => {}, tableSave: () => {}, tableCancel: () => {}, addRow: () => {}, validate: () => {}, getValue: () => {}, getKey: () => {}, tableDelete: () => {}, }) as { tableEdit: Function; tableSave: Function; tableCancel: Function; addRow: Function; validate: Function; getValue: Function; getKey: Function; tableDelete: Function; }; function isIfShow(action: Action, data: any): boolean { const ifShow = action.ifShow; if (isBoolean(ifShow)) return ifShow; if (isFunction(ifShow)) return ifShow(data); return true; } function hasPermission(action: Action, data: any) { //todo 临时处理saas不鉴权 if (__APP_INFO__.serviceMode === 'saas') { if (action.children) { return true; } if (action.openPermission) return true; return authService.checkAllPermission(action.name); } if (action.openPermission) return true; if (!appConfig.actionPermission) { return true; } if (isUndefined(route.name) || isUndefined(route.matched[0].name)) { console.error('route name is required'); } const { projectName } = route.params; //处理IASSAction判断 if (data && data.viewInfo && Array.isArray(data.viewInfo.actions)) { return data.viewInfo.actions.includes(action.name); } else { return authService.checkPermission( route.meta?.app ? route.meta?.app : (route.matched[0].name as string), route.meta?.bindView ? route.meta?.bindView : (route.name as string), stringUtil.firstToLower( action.name.replace( route.meta?.bindView ? route.meta?.bindView : (route.name as string), '', ), ), data.projectName || projectName, ); } } function filterAction(action: Action, data: any) { const { state } = action; let stateShow = true; if (state && state !== 'add') { if (getValue(getKey(data))) { stateShow = state === 'edit' || isUndefined(state) ? false : true; } else { stateShow = state === 'edit' || isUndefined(state) ? true : false; } } return stateShow && hasPermission(action, data) && isIfShow(action, data); } function filterActionNoAuth(action: Action, data: any) { const { state } = action; let stateShow = true; if (state && state !== 'add') { if (getValue(getKey(data))) { stateShow = state === 'edit' || isUndefined(state) ? false : true; } else { stateShow = state === 'edit' || isUndefined(state) ? true : false; } } return stateShow && isIfShow(action, data); } function transformAction(action: Action, data: any) { const { label, name, state, route: toRoute, api, dynamicParams, defaultParams, showSuccess, confirm, checkApi, checkDynamicParams, checkDefaultParams, handle, isReload = false, extra, } = action; const { getParams } = useParams(); const tableDynamicDisabledAction = ['deletes', 'exports']; //表格默认动态禁用操作 let { dynamicDisabled } = action; const extraData = { router, reload, action }; // handle传出数据 if (tableDynamicDisabledAction.includes(name)) { dynamicDisabled = (data: any) => { return data.list.length === 0; }; } if (dynamicDisabled) { if (isFunction(dynamicDisabled)) { action.dynamicDisabled = dynamicDisabled(data); } } else { action.dynamicDisabled = false; } if (state === 'edit') { action.finalHandle = () => { tableEdit(getKey(data)); }; return action; } if (state === 'save') { action.finalHandle = () => { console.log('save', getKey(data)); validate(getKey(data)) .then(() => { tableSave(getKey(data)); }) .catch((_: any) => {}); }; return action; } if (state === 'cancel') { action.finalHandle = () => { console.log('cancel', getKey(data)); tableCancel(getKey(data)); }; return action; } if (state === 'delete') { action.finalHandle = () => { console.log("state === 'delete'", getKey(data)); tableDelete(getKey(data)); }; return action; } if (state === 'add') { action.finalHandle = () => { addRow(data); }; return action; } const handleList: Recordable = { confirm: null, checkApi: null, route: null, api: null, handle, isReload, }; let modelInstance: Recordable = {}; if (name && name.toLowerCase().includes('exports')) { action.finalHandle = () => { xlsxExport({ data: data.list, ...extra } as any); }; return action; } if (name && name.toLowerCase().includes('import')) { if (!action.handle) { action.finalHandle = () => { xlsxImport({ ...extra, reload } as any); }; return action; } } function routeGo(toRoute: any) { const query = getParams(data, dynamicParams, defaultParams); if (isString(toRoute)) { router.push({ path: getPath(toRoute, data), query }); } else { if (toRoute.path) { toRoute.path = getPath(toRoute.path, data); toRoute.query = query; } if (toRoute.name) { toRoute.query = query; } router.push(toRoute); } } if (checkApi) { handleList.checkApi = () => { const params = getParams(data, checkDynamicParams, checkDefaultParams); const requestConfig: AxiosRequestConfig = { method: 'get' }; return httpRequest({ api: checkApi, params, pathParams: data, requestConfig }); }; } if (api) { handleList.api = () => { const params = getParams(data, dynamicParams, defaultParams); const requestConfig: AxiosRequestConfig = { method: 'post' }; if (__APP_INFO__.serviceMode === 'saas') { if (requestConfig.headers) { requestConfig.headers.resourceCode = action.name; } else { requestConfig.headers = { resourceCode: action.name, }; } } console.log('eeee', requestConfig); return httpRequest({ api, params, pathParams: data, requestConfig }).then(() => { showSuccess !== false && NsMessage.success(`${label}成功`); }); }; } //todo router name支持 if (toRoute) { handleList.route = () => { return routeGo(toRoute); }; } const modeUpdate = (prop: Recordable) => { if (!isEmpty(modelInstance)) { modelInstance.update(prop); } }; action.finalHandle = async () => { modeUpdate({ okButtonProps: { disabled: true, }, }); if (handleList.checkApi) await handleList.checkApi(); if (handleList.route) return handleList.route(); if (handleList.api) await handleList.api(); // handleList.api && showSuccess !== false && NsMessage.success(`${label}成功`); try { if (handleList.handle) await handleList.handle(data, name, { ...extraData }); } catch (error) { console.log(error); } if (isReload) { isFunction(reload) && reload(); } setTimeout(() => { modeUpdate({ okButtonProps: { disabled: false, }, }); }, 100); }; if (confirm) { const _finalHandle: any = action.finalHandle; const { title, content, icon, okText, okButtonProps } = confirm as Confirm; action.finalHandle = () => { modelInstance = NsModal.confirm({ title: title || '警告', content: content || `确定要${label}吗?`, icon: icon || createVNode(ExclamationCircleOutlined), okText: okText || '确认', cancelText: '取消', okButtonProps, onOk: _finalHandle, }); }; } return action; } return { filterAction, filterActionNoAuth, transformAction, }; }