拆分项目,移除无用应用
Frontend CI/CD / build (web-office) (push) Failing after 10s
Details
Frontend CI/CD / build (web-office) (push) Failing after 10s
Details
This commit is contained in:
parent
26c496f3db
commit
d16c0fdba3
|
@ -1,5 +0,0 @@
|
|||
# 应用标题
|
||||
VITE_APP_TITLE=热力合同系统
|
||||
|
||||
# 应用命名空间,用于缓存、store等功能的前缀,确保隔离
|
||||
VITE_APP_NAMESPACE=contract
|
|
@ -1,7 +0,0 @@
|
|||
# public path
|
||||
VITE_BASE=/
|
||||
|
||||
# Basic interface address SPA
|
||||
VITE_GLOB_API_URL=/api
|
||||
|
||||
VITE_VISUALIZER=true
|
|
@ -1,16 +0,0 @@
|
|||
# 端口号
|
||||
VITE_PORT=5666
|
||||
|
||||
VITE_BASE=/
|
||||
|
||||
# 接口地址
|
||||
VITE_GLOB_API_URL=/api
|
||||
|
||||
# 是否开启 Nitro Mock服务,true 为开启,false 为关闭
|
||||
VITE_NITRO_MOCK=true
|
||||
|
||||
# 是否打开 devtools,true 为打开,false 为关闭
|
||||
VITE_DEVTOOLS=false
|
||||
|
||||
# 是否注入全局loading
|
||||
VITE_INJECT_APP_LOADING=true
|
|
@ -1,19 +0,0 @@
|
|||
VITE_BASE=/
|
||||
|
||||
# 接口地址
|
||||
VITE_GLOB_API_URL=/api
|
||||
|
||||
# 是否开启压缩,可以设置为 none, brotli, gzip
|
||||
VITE_COMPRESS=none
|
||||
|
||||
# 是否开启 PWA
|
||||
VITE_PWA=false
|
||||
|
||||
# vue-router 的模式
|
||||
VITE_ROUTER_HISTORY=history
|
||||
|
||||
# 是否注入全局loading
|
||||
VITE_INJECT_APP_LOADING=true
|
||||
|
||||
# 打包后是否生成dist.zip
|
||||
VITE_ARCHIVER=true
|
|
@ -1,134 +0,0 @@
|
|||
/* eslint-disable */
|
||||
/* prettier-ignore */
|
||||
// @ts-nocheck
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
// Generated by unplugin-auto-import
|
||||
// biome-ignore lint: disable
|
||||
export {}
|
||||
declare global {
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const computed: typeof import('vue')['computed']
|
||||
const createApp: typeof import('vue')['createApp']
|
||||
const customRef: typeof import('vue')['customRef']
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
||||
const defineComponent: typeof import('vue')['defineComponent']
|
||||
const effectScope: typeof import('vue')['effectScope']
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||
const h: typeof import('vue')['h']
|
||||
const inject: typeof import('vue')['inject']
|
||||
const isProxy: typeof import('vue')['isProxy']
|
||||
const isReactive: typeof import('vue')['isReactive']
|
||||
const isReadonly: typeof import('vue')['isReadonly']
|
||||
const isRef: typeof import('vue')['isRef']
|
||||
const markRaw: typeof import('vue')['markRaw']
|
||||
const nextTick: typeof import('vue')['nextTick']
|
||||
const onActivated: typeof import('vue')['onActivated']
|
||||
const onBeforeMount: typeof import('vue')['onBeforeMount']
|
||||
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
|
||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
|
||||
const onDeactivated: typeof import('vue')['onDeactivated']
|
||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
|
||||
const onMounted: typeof import('vue')['onMounted']
|
||||
const onRenderTracked: typeof import('vue')['onRenderTracked']
|
||||
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
|
||||
const onScopeDispose: typeof import('vue')['onScopeDispose']
|
||||
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
|
||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
||||
const onUpdated: typeof import('vue')['onUpdated']
|
||||
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
|
||||
const provide: typeof import('vue')['provide']
|
||||
const reactive: typeof import('vue')['reactive']
|
||||
const readonly: typeof import('vue')['readonly']
|
||||
const ref: typeof import('vue')['ref']
|
||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
const toRaw: typeof import('vue')['toRaw']
|
||||
const toRef: typeof import('vue')['toRef']
|
||||
const toRefs: typeof import('vue')['toRefs']
|
||||
const toValue: typeof import('vue')['toValue']
|
||||
const triggerRef: typeof import('vue')['triggerRef']
|
||||
const unref: typeof import('vue')['unref']
|
||||
const useAttrs: typeof import('vue')['useAttrs']
|
||||
const useCssModule: typeof import('vue')['useCssModule']
|
||||
const useCssVars: typeof import('vue')['useCssVars']
|
||||
const useId: typeof import('vue')['useId']
|
||||
const useModel: typeof import('vue')['useModel']
|
||||
const useSlots: typeof import('vue')['useSlots']
|
||||
const useTemplateRef: typeof import('vue')['useTemplateRef']
|
||||
const watch: typeof import('vue')['watch']
|
||||
const watchEffect: typeof import('vue')['watchEffect']
|
||||
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
||||
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
|
||||
}
|
||||
// for type re-export
|
||||
declare global {
|
||||
// @ts-ignore
|
||||
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
|
||||
import('vue')
|
||||
}
|
||||
// for vue template auto import
|
||||
import { UnwrapRef } from 'vue'
|
||||
declare module 'vue' {
|
||||
interface GlobalComponents {}
|
||||
interface ComponentCustomProperties {
|
||||
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']>
|
||||
readonly computed: UnwrapRef<typeof import('vue')['computed']>
|
||||
readonly createApp: UnwrapRef<typeof import('vue')['createApp']>
|
||||
readonly customRef: UnwrapRef<typeof import('vue')['customRef']>
|
||||
readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']>
|
||||
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']>
|
||||
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
|
||||
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
|
||||
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']>
|
||||
readonly h: UnwrapRef<typeof import('vue')['h']>
|
||||
readonly inject: UnwrapRef<typeof import('vue')['inject']>
|
||||
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']>
|
||||
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']>
|
||||
readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']>
|
||||
readonly isRef: UnwrapRef<typeof import('vue')['isRef']>
|
||||
readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
|
||||
readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
|
||||
readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
|
||||
readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
|
||||
readonly onBeforeUnmount: UnwrapRef<typeof import('vue')['onBeforeUnmount']>
|
||||
readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']>
|
||||
readonly onDeactivated: UnwrapRef<typeof import('vue')['onDeactivated']>
|
||||
readonly onErrorCaptured: UnwrapRef<typeof import('vue')['onErrorCaptured']>
|
||||
readonly onMounted: UnwrapRef<typeof import('vue')['onMounted']>
|
||||
readonly onRenderTracked: UnwrapRef<typeof import('vue')['onRenderTracked']>
|
||||
readonly onRenderTriggered: UnwrapRef<typeof import('vue')['onRenderTriggered']>
|
||||
readonly onScopeDispose: UnwrapRef<typeof import('vue')['onScopeDispose']>
|
||||
readonly onServerPrefetch: UnwrapRef<typeof import('vue')['onServerPrefetch']>
|
||||
readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']>
|
||||
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
|
||||
readonly onWatcherCleanup: UnwrapRef<typeof import('vue')['onWatcherCleanup']>
|
||||
readonly provide: UnwrapRef<typeof import('vue')['provide']>
|
||||
readonly reactive: UnwrapRef<typeof import('vue')['reactive']>
|
||||
readonly readonly: UnwrapRef<typeof import('vue')['readonly']>
|
||||
readonly ref: UnwrapRef<typeof import('vue')['ref']>
|
||||
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
|
||||
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']>
|
||||
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']>
|
||||
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']>
|
||||
readonly toRaw: UnwrapRef<typeof import('vue')['toRaw']>
|
||||
readonly toRef: UnwrapRef<typeof import('vue')['toRef']>
|
||||
readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']>
|
||||
readonly toValue: UnwrapRef<typeof import('vue')['toValue']>
|
||||
readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']>
|
||||
readonly unref: UnwrapRef<typeof import('vue')['unref']>
|
||||
readonly useAttrs: UnwrapRef<typeof import('vue')['useAttrs']>
|
||||
readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']>
|
||||
readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']>
|
||||
readonly useId: UnwrapRef<typeof import('vue')['useId']>
|
||||
readonly useModel: UnwrapRef<typeof import('vue')['useModel']>
|
||||
readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']>
|
||||
readonly useTemplateRef: UnwrapRef<typeof import('vue')['useTemplateRef']>
|
||||
readonly watch: UnwrapRef<typeof import('vue')['watch']>
|
||||
readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']>
|
||||
readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']>
|
||||
readonly watchSyncEffect: UnwrapRef<typeof import('vue')['watchSyncEffect']>
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
const createEntry = (description = '', data: any = []) => ({
|
||||
description,
|
||||
data,
|
||||
});
|
||||
|
||||
const staticDicts = {
|
||||
cancel_reson: createEntry('变更原因', [
|
||||
{ label: '未填写原因', value: '0' },
|
||||
{ label: '用户取消', value: '1' },
|
||||
{ label: '系统取消', value: '2' },
|
||||
{ label: '其他原因', value: '3' },
|
||||
]),
|
||||
};
|
||||
|
||||
export default {
|
||||
// 配置路径,如果存在,则使用配置路径下的文件
|
||||
configPath: '',
|
||||
// 接口配置,仅用于生成 api 接口文件
|
||||
apis: {
|
||||
enable: true,
|
||||
generator: [
|
||||
{
|
||||
input: '',
|
||||
templatePath: 'src/api/template',
|
||||
output: 'src/api/index.ts',
|
||||
needTs: true,
|
||||
outputTs: 'src/api/globals.d.ts',
|
||||
handleApi: (apiDescriptor) => {
|
||||
// 返回falsy值表示过滤此api
|
||||
if (!apiDescriptor.path.startWith('/user')) {
|
||||
return;
|
||||
}
|
||||
|
||||
apiDescriptor.parameter = apiDescriptor.parameter.filter(
|
||||
(param) => param.in === 'header' && param.name === 'token',
|
||||
);
|
||||
delete apiDescriptor.requestBody.id;
|
||||
apiDescriptor.url = apiDescriptor.url.replace('/user', '');
|
||||
return apiDescriptor;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// 字典配置,仅用于生成字典枚举文件
|
||||
dicts: {
|
||||
enable: true,
|
||||
generator: [
|
||||
{
|
||||
input: '',
|
||||
templatePath: 'src/api/template',
|
||||
output: 'src/utils/dict/shared.ts',
|
||||
handleDict: async (dictDescriptor) => {
|
||||
// await dictDescriptor.request();
|
||||
|
||||
// 请求数据类型表为了生成对应注释
|
||||
// 返回falsy值表示过滤此api
|
||||
staticDicts[dictDescriptor.name] = dictDescriptor;
|
||||
return dictDescriptor;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
|
@ -1,39 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="renderer" content="webkit" />
|
||||
<meta name="description" content="Erp Management System" />
|
||||
<meta name="keywords" content="erp" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0"
|
||||
/>
|
||||
<!-- 由 vite 注入 VITE_APP_TITLE 变量,在 .env 文件内配置 -->
|
||||
<title><%= VITE_APP_TITLE %></title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<script></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
var ua = navigator.userAgent.toLocaleLowerCase();
|
||||
var browserType = '',
|
||||
browserVersion = '';
|
||||
if (ua.match(/msie/) != null || ua.match(/trident/) != null) {
|
||||
browserType = 'IE';
|
||||
browserVersion =
|
||||
ua.match(/msie ([\d.]+)/) != null
|
||||
? ua.match(/msie ([\d.]+)/)[1]
|
||||
: ua.match(/rv:([\d.]+)/)[1];
|
||||
if (1 * browserVersion < 12) {
|
||||
alert('请在ie11版本浏览器上使用系统');
|
||||
}
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,66 +0,0 @@
|
|||
{
|
||||
"name": "web-contract",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "pnpm vite build --mode production",
|
||||
"build:dev": "pnpm vite build --mode development",
|
||||
"build:analyze": "pnpm vite build --mode analyze",
|
||||
"dev": "pnpm vite --mode development",
|
||||
"dev:prod": "pnpm vite --mode production",
|
||||
"preview": "vite preview --port 4174",
|
||||
"typecheck": "vue-tsc --noEmit --skipLibCheck"
|
||||
},
|
||||
"imports": {
|
||||
"#/*": "./src/*"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fast-crud/fast-crud": "^1.21.2",
|
||||
"@fast-crud/fast-extends": "^1.21.2",
|
||||
"@fast-crud/ui-antdv4": "^1.21.2",
|
||||
"@fast-crud/ui-interface": "^1.21.2",
|
||||
"@vben-core/shadcn-ui": "workspace:*",
|
||||
"@vben/access": "workspace:*",
|
||||
"@vben/common-ui": "workspace:*",
|
||||
"@vben/constants": "workspace:*",
|
||||
"@vben/hooks": "workspace:*",
|
||||
"@vben/icons": "workspace:*",
|
||||
"@vben/layouts": "workspace:*",
|
||||
"@vben/locales": "workspace:*",
|
||||
"@vben/plugins": "workspace:*",
|
||||
"@vben/preferences": "workspace:*",
|
||||
"@vben/request": "workspace:*",
|
||||
"@vben/stores": "workspace:*",
|
||||
"@vben/styles": "workspace:*",
|
||||
"@vben/types": "workspace:*",
|
||||
"@vben/utils": "workspace:*",
|
||||
"@vueuse/core": "^11.0.3",
|
||||
"alova": "^3.0.14",
|
||||
"ant-design-vue": "^4.2.3",
|
||||
"big.js": "^6.2.1",
|
||||
"common-utils": "workspace:*",
|
||||
"dayjs": "^1.11.13",
|
||||
"exceljs": "^4.4.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"pinia": "2.2.2",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"sortablejs": "^1.15.2",
|
||||
"tyme4ts": "^1.1.2",
|
||||
"vue": "^3.4.38",
|
||||
"vue-router": "^4.4.3",
|
||||
"vxe-pc-ui": "^4.1.12",
|
||||
"vxe-table": "^4.7.74",
|
||||
"vxe-table-plugin-antd": "^4.0.8",
|
||||
"vxe-table-plugin-export-xlsx": "^4.0.2",
|
||||
"xe-utils": "^3.5.30"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/big.js": "^6.2.2",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"sass": "^1.77.8",
|
||||
"typescript": "^5.5.4",
|
||||
"unplugin-auto-import": "^0.18.2",
|
||||
"unplugin-vue-components": "^0.27.4",
|
||||
"vite-plugin-lazy-import": "^1.0.7"
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
export { default } from '@vben/tailwind-config/postcss';
|
Binary file not shown.
Before Width: | Height: | Size: 66 KiB |
|
@ -1,3 +0,0 @@
|
|||
pnpm i @fast-crud/fast-crud
|
||||
pnpm i @fast-crud/fast-extends
|
||||
pnpm i @fast-crud/ui-interface
|
|
@ -1,28 +0,0 @@
|
|||
export interface QueryOptions {
|
||||
params?: AnyObject;
|
||||
pathParams?: AnyObject;
|
||||
config?: AnyObject;
|
||||
}
|
||||
|
||||
export interface BodyOptions {
|
||||
params?: AnyObject;
|
||||
data?: AnyObject;
|
||||
pathParams?: AnyObject;
|
||||
config?: AnyObject;
|
||||
}
|
||||
|
||||
export interface RequestOptions {
|
||||
url: string;
|
||||
data?: QueryOptions;
|
||||
}
|
||||
|
||||
export interface MutationOptions {
|
||||
url: string;
|
||||
data?: BodyOptions;
|
||||
}
|
||||
|
||||
declare interface PageVo {
|
||||
rows: number;
|
||||
data: any;
|
||||
message: string;
|
||||
}
|
|
@ -1,958 +0,0 @@
|
|||
import type { BodyOptions, QueryOptions } from './global.d';
|
||||
|
||||
import { http } from './request/index';
|
||||
|
||||
export default {
|
||||
meeting: {
|
||||
/** 协同办公/会议管理 分页查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/meeting/page', data),
|
||||
/** 协同办公/会议管理 删除会议 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/meeting/deletes', data),
|
||||
/** 协同办公/会议管理 会议保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/meeting/save', data),
|
||||
/** 协同办公/会议管理 查看会议台账 */
|
||||
get_list: (data?: QueryOptions) => http.get('/app/meeting/list', data),
|
||||
list: {
|
||||
/** 协同办公/会议管理 会议台账导出 */
|
||||
get_export: (data?: QueryOptions) =>
|
||||
http.get('/app/meeting/list/export', data),
|
||||
},
|
||||
/** 协同办公/会议管理 门户获取会议数据 */
|
||||
get_getFundingSource: (data?: QueryOptions) =>
|
||||
http.get('/app/meeting/getFundingSource', data),
|
||||
},
|
||||
tysq: {
|
||||
zzjg: {
|
||||
yhjbda: {
|
||||
YhjbdaController: {
|
||||
/** 统一授权 未命名接口 */
|
||||
get_yhjbdaGrid: (data?: QueryOptions) =>
|
||||
http.get('/app/tysq/zzjg/yhjbda/YhjbdaController/yhjbdaGrid', data),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
dictType: {
|
||||
/** 协同办公/字典表 字典类型查询 */
|
||||
get_list: (data?: QueryOptions) => http.get('/app/dictType/list', data),
|
||||
/** 协同办公/字典表 字典类型保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/dictType/save', data),
|
||||
/** 协同办公/字典表 字典类型删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/dictType/deletes', data),
|
||||
},
|
||||
uaa: {
|
||||
/** 用户中心 用户登陆 */
|
||||
post_validateAccount: (data?: BodyOptions) =>
|
||||
http.post('/uc/uaa/validateAccount', data),
|
||||
},
|
||||
api: {
|
||||
core: {
|
||||
orgemplbc: {
|
||||
employee: {
|
||||
/** 用户中心 获取用户信息(分页) */
|
||||
post_paging: (data?: BodyOptions) =>
|
||||
http.post('/uc/api/core/orgemplbc/employee/paging', data),
|
||||
},
|
||||
organization: {
|
||||
RL: {
|
||||
/** 用户中心 根据组织机构id获取员工信息 */
|
||||
get_employee: (data?: QueryOptions) =>
|
||||
http.get('/uc/api/core/orgemplbc/organization/RL/employee', data),
|
||||
},
|
||||
/** 用户中心 获取组织结构信息 */
|
||||
post_paging: (data?: BodyOptions) =>
|
||||
http.post('/uc/api/core/orgemplbc/organization/paging', data),
|
||||
},
|
||||
/** 用户中心 根据组织机构id和用户信息查询 */
|
||||
post_employee: (data?: BodyOptions) =>
|
||||
http.post('/uc/api/core/orgemplbc/employee', data),
|
||||
},
|
||||
},
|
||||
},
|
||||
sys: {
|
||||
user: {
|
||||
/** 用户中心 根据token获取用户信息 */
|
||||
post_checkToken: (data?: BodyOptions) =>
|
||||
http.post('/uc/sys/user/checkToken', data),
|
||||
functiontree: {
|
||||
/** 用户中心 获取菜单接口 */
|
||||
get_XTBGXT: (data?: QueryOptions) =>
|
||||
http.get('/uc/sys/user/functiontree/HTGL', data),
|
||||
/** 统一授权 未命名接口 */
|
||||
get_PLRL: (data?: QueryOptions) =>
|
||||
http.get('/uc/sys/user/functiontree/PLRL', data),
|
||||
},
|
||||
},
|
||||
},
|
||||
zbgl: {
|
||||
/** 协同办公/值班管理 值班查询 */
|
||||
get_queryZbInfo: (data?: QueryOptions) =>
|
||||
http.get('/app/zbgl/queryZbInfo', data),
|
||||
/** 协同办公/值班管理 保存值班信息 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/zbgl/save', data),
|
||||
/** 协同办公/值班管理 删除值班信息 */
|
||||
get_deletes: (data?: QueryOptions) => http.get('/app/zbgl/deletes', data),
|
||||
/** 协同办公/值班管理 导入值班人员信息 */
|
||||
post_importZbry: (data?: BodyOptions) =>
|
||||
http.post('/app/zbgl/importZbry', data),
|
||||
/** 协同办公/值班管理 门户值班信息查询 */
|
||||
get_getDutyInfo: (data?: QueryOptions) =>
|
||||
http.get('/app/zbgl/getDutyInfo', data),
|
||||
/** 协同办公/值班管理 导出 */
|
||||
post_export: (data?: BodyOptions) => http.post('/app/zbgl/export', data),
|
||||
},
|
||||
dictData: {
|
||||
/** 协同办公/字典表 字典数据保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/dictData/save', data),
|
||||
/** 合同系统/项目管理 保存 */
|
||||
get_save: (data?: QueryOptions) => http.get('/app/dictData/save', data),
|
||||
/** 合同系统/项目名称管理 查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/dictData/page', data),
|
||||
/** 协同办公/字典表 字典数据删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/dictData/deletes', data),
|
||||
/** 合同系统/项目管理 删除 */
|
||||
get_deletes: (data?: QueryOptions) =>
|
||||
http.get('/app/dictData/deletes', data),
|
||||
},
|
||||
user: {
|
||||
/** 统一授权 获取用户列表 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/user/page', data),
|
||||
},
|
||||
dish: {
|
||||
/** 协同办公/订餐管理/菜谱管理 菜谱查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/dish/page', data),
|
||||
/** 协同办公/订餐管理/菜谱管理 菜谱保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/dish/save', data),
|
||||
/** 协同办公/订餐管理/食谱管理 菜谱删除 */
|
||||
post_deletes: (data?: BodyOptions) => http.post('/app/dish/deletes', data),
|
||||
},
|
||||
recipe: {
|
||||
/** 协同办公/订餐管理/食谱管理 食谱查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/recipe/page', data),
|
||||
/** 协同办公/订餐管理/食谱管理 食谱保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/recipe/save', data),
|
||||
/** 协同办公/订餐管理/食谱管理 食谱导出 */
|
||||
get_export: (data?: QueryOptions) => http.get('/app/recipe/export', data),
|
||||
/** 协同办公/订餐管理/食谱管理 批量保存 */
|
||||
post_saveBatch: (data?: BodyOptions) =>
|
||||
http.post('/app/recipe/saveBatch', data),
|
||||
/** 协同办公/订餐管理/食谱管理 食谱编辑 */
|
||||
post_edit: (data?: BodyOptions) => http.post('/app/recipe/edit', data),
|
||||
},
|
||||
ccsq: {
|
||||
/** 协同办公/出差申请 出差申请查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/ccsq/page', data),
|
||||
/** 协同办公/出差申请 申请单保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/ccsq/save', data),
|
||||
/** 协同办公/出差申请 申请单删除 */
|
||||
post_deletes: (data?: BodyOptions) => http.post('/app/ccsq/deletes', data),
|
||||
/** 协同办公/出差申请 退回 */
|
||||
post_rollback: (data?: BodyOptions) =>
|
||||
http.post('/app/ccsq/rollback', data),
|
||||
/** 协同办公/出差申请 启动流程 */
|
||||
post_startWorkFlow: (data?: BodyOptions) =>
|
||||
http.post('/app/ccsq/startWorkFlow', data),
|
||||
/** 协同办公/出差申请 审核 */
|
||||
post_submit: (data?: BodyOptions) => http.post('/app/ccsq/submit', data),
|
||||
/** 协同办公/出差申请 待办 */
|
||||
get_toDoPage: (data?: QueryOptions) => http.get('/app/ccsq/toDoPage', data),
|
||||
/** 协同办公/出差申请 已办 */
|
||||
get_donePage: (data?: QueryOptions) => http.get('/app/ccsq/donePage', data),
|
||||
/** 协同办公/出差申请 获取可退回节点信息 */
|
||||
get_getBackNode: (data?: QueryOptions) =>
|
||||
http.get('/app/ccsq/getBackNode', data),
|
||||
/** 协同办公/出差申请 查询流程节点 */
|
||||
get_getFlowNodeUserConfig: (data?: QueryOptions) =>
|
||||
http.get('/app/ccsq/getFlowNodeUserConfig', data),
|
||||
/** 协同办公/出差申请 下一审核节点 */
|
||||
post_getNextNodeUserConfig: (data?: BodyOptions) =>
|
||||
http.post('/app/ccsq/getNextNodeUserConfig', data),
|
||||
/** 协同办公/出差申请 查看出差信息 */
|
||||
get_getBusinessTripInfo: (data?: QueryOptions) =>
|
||||
http.get('/app/ccsq/getBusinessTripInfo', data),
|
||||
/** 协同办公/出差申请 查看审核过程 */
|
||||
get_history: (data?: QueryOptions) => http.get('/app/ccsq/history', data),
|
||||
},
|
||||
orderfood: {
|
||||
/** 协同办公/订餐管理/订餐 订餐加载接口 */
|
||||
get_getOne: (data?: QueryOptions) =>
|
||||
http.get('/app/orderfood/getOne', data),
|
||||
/** 协同办公/订餐管理/订餐 订餐保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/orderfood/save', data),
|
||||
/** 协同办公/订餐管理/订餐 取消订餐 */
|
||||
post_cancel: (data?: BodyOptions) =>
|
||||
http.post('/app/orderfood/cancel', data),
|
||||
/** 协同办公/订餐管理/订餐 协助取消他人订餐 */
|
||||
post_assistCancel: (data?: BodyOptions) =>
|
||||
http.post('/app/orderfood/assistCancel', data),
|
||||
},
|
||||
orderfoods: {
|
||||
/** 协同办公/订餐管理/汇总 单位订餐汇总 */
|
||||
get_departmentSummary: (data?: QueryOptions) =>
|
||||
http.get('/app/orderfoods/departmentSummary', data),
|
||||
/** 协同办公/订餐管理/汇总 订餐汇总 */
|
||||
get_infoList: (data?: QueryOptions) =>
|
||||
http.get('/app/orderfoods/infoList', data),
|
||||
/** 协同办公/订餐管理/汇总 个人结算汇总 */
|
||||
get_personalSummary: (data?: QueryOptions) =>
|
||||
http.get('/app/orderfoods/personalSummary', data),
|
||||
infoList: {
|
||||
/** 协同办公/订餐管理/汇总 订餐汇总导出 */
|
||||
get_export: (data?: QueryOptions) =>
|
||||
http.get('/app/orderfoods/infoList/export', data),
|
||||
},
|
||||
personalSummary: {
|
||||
/** 协同办公/订餐管理/汇总 个人结算汇总导出 */
|
||||
get_export: (data?: QueryOptions) =>
|
||||
http.get('/app/orderfoods/personalSummary/export', data),
|
||||
},
|
||||
departmentSummary: {
|
||||
/** 协同办公/订餐管理/汇总 单位订餐汇总导出 */
|
||||
get_export: (data?: QueryOptions) =>
|
||||
http.get('/app/orderfoods/departmentSummary/export', data),
|
||||
},
|
||||
/** 协同办公/订餐管理/汇总 结算单 */
|
||||
get_finalStatement: (data?: QueryOptions) =>
|
||||
http.get('/app/orderfoods/finalStatement', data),
|
||||
finalStatement: {
|
||||
/** 协同办公/订餐管理/汇总 结算表导出 */
|
||||
get_export: (data?: QueryOptions) =>
|
||||
http.get('/app/orderfoods/finalStatement/export', data),
|
||||
},
|
||||
/** 协同办公/订餐管理/汇总 结算操作 */
|
||||
post_balance: (data?: BodyOptions) =>
|
||||
http.post('/app/orderfoods/balance', data),
|
||||
},
|
||||
officeSuppliesApply: {
|
||||
/** 协同办公/办公用品/办公用品申请 申请页面查询 */
|
||||
get_page: (data?: QueryOptions) =>
|
||||
http.get('/app/officeSuppliesApply/page', data),
|
||||
/** 协同办公/办公用品/办公用品申请 申请保存 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/officeSuppliesApply/save', data),
|
||||
/** 协同办公/办公用品/办公用品申请 批量审核 */
|
||||
post_audit: (data?: BodyOptions) =>
|
||||
http.post('/app/officeSuppliesApply/audit', data),
|
||||
/** 协同办公/办公用品/办公用品申请 批量申请 */
|
||||
post_saveBatch: (data?: BodyOptions) =>
|
||||
http.post('/app/officeSuppliesApply/saveBatch', data),
|
||||
/** 协同办公/办公用品/办公用品申请 撤销申请 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/officeSuppliesApply/deletes', data),
|
||||
},
|
||||
warehousing: {
|
||||
/** 协同办公/办公用品/入库/出库 入库查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/warehousing/page', data),
|
||||
},
|
||||
inOrOut: {
|
||||
/** 协同办公/办公用品/入库/出库 入库/保存 */
|
||||
post_saveBatch: (data?: BodyOptions) =>
|
||||
http.post('/app/inOrOut/saveBatch', data),
|
||||
},
|
||||
supervise: {
|
||||
/** 协同办公/督查督办/立项发起 立项分页查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/supervise/page', data),
|
||||
/** 协同办公/督查督办/立项发起 立项保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/supervise/save', data),
|
||||
/** 协同办公/督查督办/立项发起 立项删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/supervise/deletes', data),
|
||||
/** 协同办公/督查督办/立项发起 立项提交 */
|
||||
post_audit: (data?: BodyOptions) => http.post('/app/supervise/audit', data),
|
||||
/** 协同办公/督查督办/执行反馈 执行反馈提交 */
|
||||
post_auditFankui: (data?: BodyOptions) =>
|
||||
http.post('/app/supervise/auditFankui', data),
|
||||
/** 协同办公/督查督办/报表汇总 统计 */
|
||||
get_huizong: (data?: QueryOptions) =>
|
||||
http.get('/app/supervise/huizong', data),
|
||||
/** 协同办公/督查督办/立项发起 更新状态 */
|
||||
post_updateStatus: (data?: BodyOptions) =>
|
||||
http.post('/app/supervise/updateStatus', data),
|
||||
},
|
||||
feedback: {
|
||||
/** 协同办公/督查督办/执行反馈 执行反馈待办查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/feedback/page', data),
|
||||
/** 协同办公/督查督办/执行反馈 执行反馈保存,实际修改操作,保存反馈时间,反馈内容,进度 */
|
||||
post_saveUpdate: (data?: BodyOptions) =>
|
||||
http.post('/app/feedback/saveUpdate', data),
|
||||
/** 协同办公/督查督办/执行反馈 查询负责部门列表,返回所有的反馈信息 */
|
||||
get_getDepartment: (data?: QueryOptions) =>
|
||||
http.get('/app/feedback/getDepartment', data),
|
||||
/** 协同办公/督查督办/执行反馈 分发立项任务 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/feedback/save', data),
|
||||
/** 协同办公/督查督办/执行反馈 执行反馈已办查询 */
|
||||
get_pageDone: (data?: QueryOptions) =>
|
||||
http.get('/app/feedback/pageDone', data),
|
||||
/** 协同办公/督查督办/立项发起 查询立项对应的反馈 */
|
||||
get_queryFeedback: (data?: QueryOptions) =>
|
||||
http.get('/app/feedback/queryFeedback', data),
|
||||
},
|
||||
file: {
|
||||
/** 协同办公/文件上传/下载 多文件上传 */
|
||||
post_uploads: (data?: BodyOptions) => http.post('/app/file/uploads', data),
|
||||
},
|
||||
addressor: {
|
||||
/** 协同办公/会议管理/发言人 发言人查询 */
|
||||
get_list: (data?: QueryOptions) => http.get('/app/addressor/list', data),
|
||||
/** 协同办公/会议管理/发言人 发言人批量保存 */
|
||||
post_saveBatch: (data?: BodyOptions) =>
|
||||
http.post('/app/addressor/saveBatch', data),
|
||||
/** 协同办公/会议管理/发言人 发言人保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/addressor/save', data),
|
||||
/** 协同办公/会议管理/发言人 删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/addressor/deletes', data),
|
||||
},
|
||||
officeSuppliesList: {
|
||||
/** 协同办公/办公用品/办公用品清单 分页查询 */
|
||||
get_page: (data?: QueryOptions) =>
|
||||
http.get('/app/officeSuppliesList/page', data),
|
||||
/** 协同办公/办公用品/办公用品清单 批量保存 */
|
||||
post_saveBatch: (data?: BodyOptions) =>
|
||||
http.post('/app/officeSuppliesList/saveBatch', data),
|
||||
/** 协同办公/办公用品/办公用品清单 删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/officeSuppliesList/deletes', data),
|
||||
},
|
||||
officeSuppliesApplySum: {
|
||||
/** 协同办公/办公用品 采购汇总 */
|
||||
get_list: (data?: QueryOptions) =>
|
||||
http.get('/app/officeSuppliesApplySum/list', data),
|
||||
/** 协同办公/办公用品 结算清单 */
|
||||
get_finalStatement: (data?: QueryOptions) =>
|
||||
http.get('/app/officeSuppliesApplySum/finalStatement', data),
|
||||
/** 协同办公/办公用品 单位结算清单 */
|
||||
get_unitFinalStatement: (data?: QueryOptions) =>
|
||||
http.get('/app/officeSuppliesApplySum/unitFinalStatement', data),
|
||||
finalStatement: {
|
||||
/** 协同办公/办公用品 结算清单导出 */
|
||||
get_export: (data?: QueryOptions) =>
|
||||
http.get('/app/officeSuppliesApplySum/finalStatement/export', data),
|
||||
},
|
||||
/** 协同办公/办公用品 结算清单结算操作 */
|
||||
post_balance: (data?: BodyOptions) =>
|
||||
http.post('/app/officeSuppliesApplySum/balance', data),
|
||||
},
|
||||
autoOrderfoodPeoples: {
|
||||
/** 协同办公/订餐管理/自动订餐人员管理 分页查询 */
|
||||
get_page: (data?: QueryOptions) =>
|
||||
http.get('/app/autoOrderfoodPeoples/page', data),
|
||||
/** 协同办公/订餐管理/自动订餐人员管理 批量保存 */
|
||||
post_saveBatch: (data?: BodyOptions) =>
|
||||
http.post('/app/autoOrderfoodPeoples/saveBatch', data),
|
||||
/** 协同办公/订餐管理/自动订餐人员管理 删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/autoOrderfoodPeoples/deletes', data),
|
||||
},
|
||||
usercenter: {
|
||||
/** 协同办公 获取菜单 */
|
||||
get_menus: (data?: QueryOptions) => http.get('/app/usercenter/menus', data),
|
||||
},
|
||||
workflow: {
|
||||
/** 协同办公/工作流 待办 */
|
||||
post_queryMyTodoTask: (data?: BodyOptions) =>
|
||||
http.post('/app/workflow/queryMyTodoTask', data),
|
||||
/** 协同办公/工作流 已办 */
|
||||
post_getHistoricTaskByUserID: (data?: BodyOptions) =>
|
||||
http.post('/app/workflow/getHistoricTaskByUserID', data),
|
||||
},
|
||||
personTask: {
|
||||
/** 合同系统/签订 待办查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/personTask/page', data),
|
||||
/** 合同系统/签订 已办查询 */
|
||||
get_pagePersonTaskOver: (data?: QueryOptions) =>
|
||||
http.get('/app/personTask/pagePersonTaskOver', data),
|
||||
/** 合同系统/履行/履行查询 分页合同履行审批查询 */
|
||||
get_pagePerformanceAudit: (data?: QueryOptions) =>
|
||||
http.get('/app/personTask/pagePerformanceAudit', data),
|
||||
/** 合同系统/履行/履行提示/申请归档 归档保存 */
|
||||
post_applicationFiling: (data?: BodyOptions) =>
|
||||
http.post('/app/personTask/applicationFiling', data),
|
||||
},
|
||||
sbCtrBasePt: {
|
||||
/** 合同系统/申报 合同申报数据查询 */
|
||||
get_QuerySbCtrBase: (data?: QueryOptions) =>
|
||||
http.get('/app/sbCtrBasePt/QuerySbCtrBase', data),
|
||||
/** 合同系统/申报 合同申报基本信息加载 */
|
||||
post_page: (data?: BodyOptions) => http.post('/app/sbCtrBasePt/page', data),
|
||||
/** 合同系统/申报 合同申报基本信息保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/sbCtrBasePt/save', data),
|
||||
/** 合同系统/申报 合同申报基本信息删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/sbCtrBasePt/deletes', data),
|
||||
/** 合同系统/申报 获取资金渠道 */
|
||||
get_getFundingSource: (data?: QueryOptions) =>
|
||||
http.get('/app/sbCtrBasePt/getFundingSource', data),
|
||||
/** 合同系统/申报 提交 */
|
||||
post_submit: (data?: BodyOptions) =>
|
||||
http.post('/app/sbCtrBasePt/submit', data),
|
||||
/** 合同系统/申报 退回 */
|
||||
post_rollback: (data?: BodyOptions) =>
|
||||
http.post('/app/sbCtrBasePt/rollback', data),
|
||||
/** 合同系统/申报 发起废除 */
|
||||
post_repeal: (data?: BodyOptions) =>
|
||||
http.post('/app/sbCtrBasePt/repeal', data),
|
||||
/** 合同系统/申报 发起流程 */
|
||||
post_start: (data?: BodyOptions) =>
|
||||
http.post('/app/sbCtrBasePt/start', data),
|
||||
},
|
||||
contractBaseInfo: {
|
||||
/** 合同系统/立项 合同立项保存 */
|
||||
post_apply: (data?: BodyOptions) =>
|
||||
http.post('/app/contractBaseInfo/apply', data),
|
||||
/** 合同系统/立项 合同立项查询 */
|
||||
get_page: (data?: QueryOptions) =>
|
||||
http.get('/app/contractBaseInfo/page', data),
|
||||
/** 合同系统/立项 删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/contractBaseInfo/deletes', data),
|
||||
/** 合同系统/立项 单条查询 */
|
||||
get_getOne: (data?: QueryOptions) =>
|
||||
http.get('/app/contractBaseInfo/getOne', data),
|
||||
/** 合同系统/立项 提交 */
|
||||
post_submit: (data?: BodyOptions) =>
|
||||
http.post('/app/contractBaseInfo/submit', data),
|
||||
/** 合同系统/立项废除 退回 */
|
||||
post_rollback: (data?: BodyOptions) =>
|
||||
http.post('/app/contractBaseInfo/rollback', data),
|
||||
/** 合同系统/立项废除 提交 */
|
||||
post_abolishSubmit: (data?: BodyOptions) =>
|
||||
http.post('/app/contractBaseInfo/abolishSubmit', data),
|
||||
/** 合同系统/立项 流程启动(非待办提交) */
|
||||
post_applyFlowStart: (data?: BodyOptions) =>
|
||||
http.post('/app/contractBaseInfo/applyFlowStart', data),
|
||||
/** 合同系统/立项废除 流程启动(非待办提交) */
|
||||
post_abolishFlowStart: (data?: BodyOptions) =>
|
||||
http.post('/app/contractBaseInfo/abolishFlowStart', data),
|
||||
},
|
||||
proProviderInfo: {
|
||||
/** 合同系统/相对人管理 合同相对人查询 */
|
||||
get_Query: (data?: QueryOptions) =>
|
||||
http.get('/app/proProviderInfo/Query', data),
|
||||
/** 合同系统/相对人管理 获取币种 */
|
||||
get_getBz: (data?: QueryOptions) =>
|
||||
http.get('/app/proProviderInfo/getBz', data),
|
||||
/** 合同系统/相对人管理 保存 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/proProviderInfo/save', data),
|
||||
/** 合同系统/相对人管理 删除 */
|
||||
get_deletes: (data?: QueryOptions) =>
|
||||
http.get('/app/proProviderInfo/deletes', data),
|
||||
/** 合同系统/相对人管理 加载 */
|
||||
post_page: (data?: BodyOptions) =>
|
||||
http.post('/app/proProviderInfo/page', data),
|
||||
},
|
||||
contractModelInfo: {
|
||||
/** 合同系统/模板管理 保存 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/contractModelInfo/save', data),
|
||||
/** 合同系统/模板管理 删除 */
|
||||
get_deletes: (data?: QueryOptions) =>
|
||||
http.get('/app/contractModelInfo/deletes', data),
|
||||
/** 合同系统/模板管理 加载 */
|
||||
post_page: (data?: BodyOptions) =>
|
||||
http.post('/app/contractModelInfo/page', data),
|
||||
},
|
||||
contractReferType: {
|
||||
/** 合同系统/合同类型参照 查询 */
|
||||
get_list: (data?: QueryOptions) =>
|
||||
http.get('/app/contractReferType/list', data),
|
||||
/** 合同系统/合同类型参照 保存 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/contractReferType/save', data),
|
||||
/** 合同系统/合同类型参照 删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/contractReferType/deletes', data),
|
||||
},
|
||||
attachment: {
|
||||
/** 文件上传/下载(新) 附件加载 */
|
||||
get_list: (data?: QueryOptions) => http.get('/app/attachment/list', data),
|
||||
/** 文件上传/下载(新) 文件下载 */
|
||||
get_download: (data?: QueryOptions) =>
|
||||
http.get('/app/attachment/download/{fileUuid}', data),
|
||||
/** 文件上传/下载(新) 多文件上传 */
|
||||
post_uploads: (data?: BodyOptions) =>
|
||||
http.post('/app/attachment/uploads', data),
|
||||
},
|
||||
contractPayment: {
|
||||
/** 合同系统/履行/履行提示/合同付款 获取合同付款信息 */
|
||||
get_queryPaymentInfo: (data?: QueryOptions) =>
|
||||
http.get('/app/contractPayment/queryPaymentInfo', data),
|
||||
/** 合同系统/归档/合同归档 历史记录 */
|
||||
get_historyPaymentInfo: (data?: QueryOptions) =>
|
||||
http.get('/app/contractPayment/historyPaymentInfo', data),
|
||||
/** 合同系统/履行/履行提示/合同付款 保存付款申请 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/contractPayment/save', data),
|
||||
/** 合同系统/履行/履行提示/合同付款 查询流程未配置人员节点 */
|
||||
get_getFlowNodeUserConfig: (data?: QueryOptions) =>
|
||||
http.get('/app/contractPayment/getFlowNodeUserConfig', data),
|
||||
/** 合同系统/履行/履行提示/合同付款 送审 */
|
||||
post_startWorkFlow: (data?: BodyOptions) =>
|
||||
http.post('/app/contractPayment/startWorkFlow', data),
|
||||
/** 合同系统/履行/履行提示/合同付款 审核通过 */
|
||||
post_submit: (data?: BodyOptions) =>
|
||||
http.post('/app/contractPayment/submit', data),
|
||||
/** 合同系统/履行/履行提示/合同付款 退回 */
|
||||
post_rollback: (data?: BodyOptions) =>
|
||||
http.post('/app/contractPayment/rollback', data),
|
||||
/** 合同系统/履行/履行提示/合同付款 待审核 */
|
||||
get_toDoPage: (data?: QueryOptions) =>
|
||||
http.get('/app/contractPayment/toDoPage', data),
|
||||
/** 合同系统/履行/履行提示/合同付款 已审核 */
|
||||
get_donePage: (data?: QueryOptions) =>
|
||||
http.get('/app/contractPayment/donePage', data),
|
||||
},
|
||||
selectMerchantsBasicInfo: {
|
||||
/** 合同系统/选商 分页查询 */
|
||||
get_page: (data?: QueryOptions) =>
|
||||
http.get('/app/selectMerchantsBasicInfo/page', data),
|
||||
/** 合同系统/选商 选商信息查询(单条) */
|
||||
get_getOne: (data?: QueryOptions) =>
|
||||
http.get('/app/selectMerchantsBasicInfo/getOne', data),
|
||||
/** 合同系统/选商 选商信息保存 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/selectMerchantsBasicInfo/save', data),
|
||||
/** 合同系统/选商 合同选商保存操作(多个对象) */
|
||||
post_saveMultiEntity: (data?: BodyOptions) =>
|
||||
http.post('/app/selectMerchantsBasicInfo/saveMultiEntity', data),
|
||||
/** 合同系统/选商 提交 */
|
||||
post_submit: (data?: BodyOptions) =>
|
||||
http.post('/app/selectMerchantsBasicInfo/submit', data),
|
||||
/** 合同系统/选商 退回 */
|
||||
post_rollback: (data?: BodyOptions) =>
|
||||
http.post('/app/selectMerchantsBasicInfo/rollback', data),
|
||||
/** 合同系统/选商废除 选商废除(弃用) */
|
||||
post_abolish: (data?: BodyOptions) =>
|
||||
http.post('/app/selectMerchantsBasicInfo/abolish', data),
|
||||
/** 合同系统/选商废除 选商废除(开始节点提交,非待办提交) */
|
||||
post_abolishFlowStart: (data?: BodyOptions) =>
|
||||
http.post('/app/selectMerchantsBasicInfo/abolishFlowStart', data),
|
||||
/** 合同系统/选商废除 提交 */
|
||||
post_abolishSubmit: (data?: BodyOptions) =>
|
||||
http.post('/app/selectMerchantsBasicInfo/abolishSubmit', data),
|
||||
/** 合同系统/选商废除 退回 */
|
||||
post_abolishRollback: (data?: BodyOptions) =>
|
||||
http.post('/app/selectMerchantsBasicInfo/abolishRollback', data),
|
||||
/** 合同系统/选商 流程启动(非待办提交) */
|
||||
post_flowStart: (data?: BodyOptions) =>
|
||||
http.post('/app/selectMerchantsBasicInfo/flowStart', data),
|
||||
},
|
||||
lvxChange: {
|
||||
/** 合同系统/履行/履行提示/合同变更 保存合同变更申请 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/lvxChange/save', data),
|
||||
/** 合同系统/履行/履行提示/合同变更 获取合同变更信息 */
|
||||
get_getContractChangeInfo: (data?: QueryOptions) =>
|
||||
http.get('/app/lvxChange/getContractChangeInfo', data),
|
||||
/** 合同系统/履行/履行提示/合同变更 查询流程未配置人员节点 */
|
||||
get_getFlowNodeUserConfig: (data?: QueryOptions) =>
|
||||
http.get('/app/lvxChange/getFlowNodeUserConfig', data),
|
||||
/** 合同系统/履行/履行提示/合同变更 流程启动 */
|
||||
post_startWorkFlow: (data?: BodyOptions) =>
|
||||
http.post('/app/lvxChange/startWorkFlow', data),
|
||||
/** 合同系统/履行/履行提示/合同变更 审核通过 */
|
||||
post_submit: (data?: BodyOptions) =>
|
||||
http.post('/app/lvxChange/submit', data),
|
||||
},
|
||||
contractRelieve: {
|
||||
/** 合同系统/履行/履行提示/合同解除 获取合同解除信息 */
|
||||
get_getContractRelieveInfo: (data?: QueryOptions) =>
|
||||
http.get('/app/contractRelieve/getContractRelieveInfo', data),
|
||||
/** 合同系统/履行/履行提示/合同解除 保存合同解除信息 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/contractRelieve/save', data),
|
||||
},
|
||||
contractBreach: {
|
||||
/** 合同系统/履行/履行提示/合同违约情况 保存合同违约信息 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/contractBreach/save', data),
|
||||
/** 合同系统/履行/履行提示/合同违约情况 获取合同违约信息 */
|
||||
get_getContractBreachInfo: (data?: QueryOptions) =>
|
||||
http.get('/app/contractBreach/getContractBreachInfo', data),
|
||||
/** 合同系统/履行/履行提示/合同违约情况 查询流程未配置人员节点 */
|
||||
get_getFlowNodeUserConfig: (data?: QueryOptions) =>
|
||||
http.get('/app/contractBreach/getFlowNodeUserConfig', data),
|
||||
/** 合同系统/履行/履行提示/合同违约情况 启动流程 */
|
||||
post_startWorkFlow: (data?: BodyOptions) =>
|
||||
http.post('/app/contractBreach/startWorkFlow', data),
|
||||
/** 合同系统/履行/履行提示/合同违约情况 审核 */
|
||||
post_submit: (data?: BodyOptions) =>
|
||||
http.post('/app/contractBreach/submit', data),
|
||||
/** 合同系统/履行/履行提示/合同违约情况 退回 */
|
||||
post_rollback: (data?: BodyOptions) =>
|
||||
http.post('/app/contractBreach/rollback', data),
|
||||
},
|
||||
lvxResult: {
|
||||
/** 合同系统/履行/履行结果 履行结果保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/lvxResult/save', data),
|
||||
/** 合同系统/履行/履行结果 分页履行结果查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/lvxResult/page', data),
|
||||
/** 合同系统/履行/履行结果 已办 */
|
||||
get_pageDone: (data?: QueryOptions) =>
|
||||
http.get('/app/lvxResult/pageDone', data),
|
||||
},
|
||||
contractFiling: {
|
||||
/** 合同系统/履行/履行提示/临时归档 保存临时归档信息 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/contractFiling/save', data),
|
||||
/** 合同系统/履行/履行提示/临时归档 分页查询 */
|
||||
get_pageFillingList: (data?: QueryOptions) =>
|
||||
http.get('/app/contractFiling/pageFillingList', data),
|
||||
/** 合同系统/履行/履行提示/临时归档 回档 */
|
||||
post_update: (data?: BodyOptions) =>
|
||||
http.post('/app/contractFiling/update', data),
|
||||
/** 合同系统/履行/履行提示/临时归档 获取临时归档信息 */
|
||||
get_getLsgd: (data?: QueryOptions) =>
|
||||
http.get('/app/contractFiling/getLsgd', data),
|
||||
},
|
||||
biddingExpert: {
|
||||
/** 合同系统/选商/选商招标专家 招标专家查询 */
|
||||
get_list: (data?: QueryOptions) =>
|
||||
http.get('/app/biddingExpert/list', data),
|
||||
/** 合同系统/选商/选商招标专家 选商招标专家保存 */
|
||||
post_saveBatch: (data?: BodyOptions) =>
|
||||
http.post('/app/biddingExpert/saveBatch', data),
|
||||
/** 合同系统/选商/选商招标专家 选商招标专家删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/biddingExpert/deletes', data),
|
||||
},
|
||||
contractFilingFormal: {
|
||||
/** 合同系统/归档/合同归档 分页查询归档信息 */
|
||||
get_queryContractFiling: (data?: QueryOptions) =>
|
||||
http.get('/app/contractFilingFormal/queryContractFiling', data),
|
||||
/** 合同系统/归档/合同归档 获取合同招标选商申请信息 */
|
||||
get_getContractSupplier: (data?: QueryOptions) =>
|
||||
http.get('/app/contractFilingFormal/getContractSupplier', data),
|
||||
/** 合同系统/归档/合同归档 保存合同归档 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/contractFilingFormal/save', data),
|
||||
/** 合同系统/归档/合同回档 分页查询-已归档 */
|
||||
get_pageArchivedContract: (data?: QueryOptions) =>
|
||||
http.get('/app/contractFilingFormal/pageArchivedContract', data),
|
||||
/** 合同系统/归档/合同回档 回档 */
|
||||
post_saveFilingBack: (data?: BodyOptions) =>
|
||||
http.post('/app/contractFilingFormal/saveFilingBack', data),
|
||||
},
|
||||
lvxProduct: {
|
||||
/** 合同系统/履行/履行提示/产品或服务 获取合同产品信息 */
|
||||
get_getContractProductInfo: (data?: QueryOptions) =>
|
||||
http.get('/app/lvxProduct/getContractProductInfo', data),
|
||||
/** 合同系统/履行/履行提示/产品或服务 累计收款金额 */
|
||||
get_getSumFromProduct: (data?: QueryOptions) =>
|
||||
http.get('/app/lvxProduct/getSumFromProduct', data),
|
||||
/** 合同系统/履行/履行提示/产品或服务 历史记录 */
|
||||
get_getListFromHistoryRecord: (data?: QueryOptions) =>
|
||||
http.get('/app/lvxProduct/getListFromHistoryRecord', data),
|
||||
/** 合同系统/履行/履行提示/产品或服务 保存合同产品服务 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/lvxProduct/save', data),
|
||||
},
|
||||
qdSign: {
|
||||
/** 合同系统/签订 签订查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/qdSign/page', data),
|
||||
/** 合同系统/签订 获取合同签订信息 */
|
||||
get_getContractSignInfo: (data?: QueryOptions) =>
|
||||
http.get('/app/qdSign/getContractSignInfo', data),
|
||||
/** 合同系统/打印 选商打印 */
|
||||
get_printApprove: (data?: QueryOptions) =>
|
||||
http.get('/app/qdSign/printApprove', data),
|
||||
/** 合同系统/签订 打印文本 */
|
||||
get_textPrint: (data?: QueryOptions) =>
|
||||
http.get('/app/qdSign/textPrint', data),
|
||||
/** 合同系统/签订 保存送审 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/qdSign/save', data),
|
||||
/** 合同系统/签订 废除 */
|
||||
post_abolish: (data?: BodyOptions) =>
|
||||
http.post('/app/qdSign/abolish', data),
|
||||
},
|
||||
flowCenter: {
|
||||
/** 流程中心 启动流程 */
|
||||
post_start: (data?: BodyOptions) => http.post('/flowCenter/start', data),
|
||||
/** 流程中心 审核通过 */
|
||||
post_agree: (data?: BodyOptions) => http.post('/flowCenter/agree', data),
|
||||
/** 流程中心 审核退回 */
|
||||
post_rollback: (data?: BodyOptions) =>
|
||||
http.post('/flowCenter/rollback', data),
|
||||
/** 流程中心 获取待办 */
|
||||
post_getTodoList: (data?: BodyOptions) =>
|
||||
http.post('/flowCenter/getTodoList', data),
|
||||
/** 流程中心 获取已办 */
|
||||
post_doneList: (data?: BodyOptions) =>
|
||||
http.post('/flowCenter/doneList', data),
|
||||
/** 流程中心 审核撤回 */
|
||||
get_revoke: (data?: QueryOptions) => http.get('/flowCenter/revoke', data),
|
||||
/** 流程中心 审核记录 */
|
||||
get_history: (data?: QueryOptions) => http.get('/flowCenter/history', data),
|
||||
/** 流程中心 查看流程图 */
|
||||
get_getFlowImg: (data?: QueryOptions) =>
|
||||
http.get('/flowCenter/getFlowImg', data),
|
||||
/** 流程中心 获取可退回节点 */
|
||||
get_getReturnNode: (data?: QueryOptions) =>
|
||||
http.get('/flowCenter/getReturnNode', data),
|
||||
/** 流程中心 获取流程节点人员配置信息 */
|
||||
get_getNextNodeUserConfig: (data?: QueryOptions) =>
|
||||
http.get('/flowCenter/getNextNodeUserConfig', data),
|
||||
/** 流程中心 获取待办数量 */
|
||||
get_getTodoListSize: (data?: QueryOptions) =>
|
||||
http.get('/flowCenter/getTodoListSize', data),
|
||||
/** 流程中心 获取当前审核节点配置信息 */
|
||||
get_getNodeConfigInfo: (data?: QueryOptions) =>
|
||||
http.get('/flowCenter/getNodeConfigInfo', data),
|
||||
/** 流程中心 获取下一节点配置信息 */
|
||||
get_getNextNodeConfig: (data?: QueryOptions) =>
|
||||
http.get('/flowCenter/getNextNodeConfig', data),
|
||||
/** 流程中心 获取流程节点人员配置信息 */
|
||||
post_getFlowNodeUserConfig: (data?: BodyOptions) =>
|
||||
http.post('/flowCenter/getFlowNodeUserConfig', data),
|
||||
/** 流程中心 获取流程变量配置 */
|
||||
get_getFlowVariablesConfig: (data?: QueryOptions) =>
|
||||
http.get('/flowCenter/getFlowVariablesConfig', data),
|
||||
/** 流程中心 获取流程所有人员配置信息 */
|
||||
get_getFlowUserConfig: (data?: QueryOptions) =>
|
||||
http.get('/flowCenter/getFlowUserConfig', data),
|
||||
},
|
||||
rl: {
|
||||
moduleParameter: {
|
||||
/** 流程中心/流程规划 保存 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/rl/moduleParameter/save', data),
|
||||
/** 流程中心/流程规划 查询 */
|
||||
post_page: (data?: BodyOptions) =>
|
||||
http.post('/app/rl/moduleParameter/page', data),
|
||||
/** 流程中心/流程规划 删除 */
|
||||
get_deletes: (data?: QueryOptions) =>
|
||||
http.get('/app/rl/moduleParameter/deletes', data),
|
||||
/** 流程中心/流程规划 获取节点审核人 */
|
||||
get_getNextNodeUser: (data?: QueryOptions) =>
|
||||
http.get('/app/rl/moduleParameter/getNextNodeUser', data),
|
||||
},
|
||||
workFlow: {
|
||||
/** 合同系统 流程待办 */
|
||||
get_queryMyTodoTask: (data?: QueryOptions) =>
|
||||
http.get('/app/rl/workFlow/queryMyTodoTask', data),
|
||||
},
|
||||
},
|
||||
dutyCount: {
|
||||
/** 协同办公/订餐管理/值班天数 分页查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/dutyCount/page', data),
|
||||
/** 协同办公/订餐管理/值班天数 批量保存 */
|
||||
post_saveBatch: (data?: BodyOptions) =>
|
||||
http.post('/app/dutyCount/saveBatch', data),
|
||||
/** 协同办公/订餐管理/值班天数 删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/dutyCount/deletes', data),
|
||||
},
|
||||
common: {
|
||||
/** 公共 获取请求ip */
|
||||
get_getClientIp: (data?: QueryOptions) =>
|
||||
http.get('/app/common/getClientIp', data),
|
||||
/** 公共 获取项目地址 */
|
||||
get_getProjectAddress: (data?: QueryOptions) =>
|
||||
http.get('/app/common/getProjectAddress', data),
|
||||
},
|
||||
address: {
|
||||
/** 协同办公/订餐管理/订餐地址 查询(分页) */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/address/page', data),
|
||||
/** 协同办公/订餐管理/订餐地址 保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/address/save', data),
|
||||
/** 协同办公/订餐管理/订餐地址 删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/address/deletes', data),
|
||||
},
|
||||
superviseFeedbackRecord: {
|
||||
/** 协同办公/督查督办/反馈记录 保存反馈记录 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/superviseFeedbackRecord/save', data),
|
||||
/** 协同办公/督查督办/反馈记录 查询反馈记录 */
|
||||
get_page: (data?: QueryOptions) =>
|
||||
http.get('/app/superviseFeedbackRecord/page', data),
|
||||
/** 协同办公/督查督办/反馈记录 删除反馈记录 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/superviseFeedbackRecord/deletes', data),
|
||||
},
|
||||
lxBasisSale: {
|
||||
/** 合同系统/签约依据 分页保存/修改 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/lxBasisSale/save', data),
|
||||
/** 合同系统/签约依据 查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/lxBasisSale/page', data),
|
||||
/** 合同系统/签约依据 删除测试 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/lxBasisSale/deletes', data),
|
||||
},
|
||||
workFlow: {
|
||||
/** 合同系统 查询下一节点id */
|
||||
get_getNextNodeUserConfig: (data?: QueryOptions) =>
|
||||
http.get('/app/workFlow/getNextNodeUserConfig', data),
|
||||
/** 合同系统 获取可退回节点 */
|
||||
get_getBackNode: (data?: QueryOptions) =>
|
||||
http.get('/app/workFlow/getBackNode', data),
|
||||
/** 合同系统 审核记录 */
|
||||
get_history: (data?: QueryOptions) =>
|
||||
http.get('/app/workFlow/history', data),
|
||||
/** 合同系统 流程已办 */
|
||||
get_getDoneTaskByUserID: (data?: QueryOptions) =>
|
||||
http.get('/app/workFlow/getDoneTaskByUserID', data),
|
||||
/** 合同系统 获取流程图 */
|
||||
get_getFlowImg: (data?: QueryOptions) =>
|
||||
http.get('/app/workFlow/getFlowImg', data),
|
||||
},
|
||||
biddingResult: {
|
||||
/** 合同系统/选商/选商结果 分页查询 */
|
||||
get_page: (data?: QueryOptions) =>
|
||||
http.get('/app/biddingResult/page', data),
|
||||
/** 合同系统/选商/选商结果 保存 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/biddingResult/save', data),
|
||||
/** 合同系统/选商/选商结果 查询流程审核节点 */
|
||||
get_getFlowNodeUserConfig: (data?: QueryOptions) =>
|
||||
http.get('/app/biddingResult/getFlowNodeUserConfig', data),
|
||||
/** 合同系统/选商/选商结果 启动流程 */
|
||||
post_startWorkFlow: (data?: BodyOptions) =>
|
||||
http.post('/app/biddingResult/startWorkFlow', data),
|
||||
/** 合同系统/选商/选商结果 审核通过 */
|
||||
post_submit: (data?: BodyOptions) =>
|
||||
http.post('/app/biddingResult/submit', data),
|
||||
/** 合同系统/选商/选商结果 退回 */
|
||||
post_rollback: (data?: BodyOptions) =>
|
||||
http.post('/app/biddingResult/rollback', data),
|
||||
/** 合同系统/选商/选商结果 待审核 */
|
||||
get_toDoPage: (data?: QueryOptions) =>
|
||||
http.get('/app/biddingResult/toDoPage', data),
|
||||
/** 合同系统/选商/选商结果 查询合同信息 */
|
||||
get_getContractInfo: (data?: QueryOptions) =>
|
||||
http.get('/app/biddingResult/getContractInfo', data),
|
||||
/** 合同系统/选商/选商结果 查询供应商列表 */
|
||||
get_getProviderInfo: (data?: QueryOptions) =>
|
||||
http.get('/app/biddingResult/getProviderInfo', data),
|
||||
/** 合同系统/选商/选商结果 选商专家列表 */
|
||||
get_queryBiddingExpert: (data?: QueryOptions) =>
|
||||
http.get('/app/biddingResult/queryBiddingExpert', data),
|
||||
},
|
||||
home: {
|
||||
/** 合同系统/首页待办/已办 首页待办 */
|
||||
get_todo: (data?: QueryOptions) => http.get('/app/home/todo', data),
|
||||
/** 合同系统/首页待办/已办 首页已办 */
|
||||
get_done: (data?: QueryOptions) => http.get('/app/home/done', data),
|
||||
},
|
||||
sqConsignPt: {
|
||||
/** 合同系统/签约授权 签约授权保存 */
|
||||
post_saveSignMultiEntity: (data?: BodyOptions) =>
|
||||
http.post('/app/sqConsignPt/saveSignMultiEntity', data),
|
||||
/** 合同系统/签约授权 签约授权查询 */
|
||||
get_SigningaAuthorizationSerch: (data?: QueryOptions) =>
|
||||
http.get('/app/sqConsignPt/SigningaAuthorizationSerch', data),
|
||||
/** 合同系统/签约授权 查询单条签约授权数据 */
|
||||
get_getOne: (data?: QueryOptions) =>
|
||||
http.get('/app/sqConsignPt/getOne', data),
|
||||
/** 合同系统/签约授权 签约授权提交(非待办提交) */
|
||||
post_flowStart: (data?: BodyOptions) =>
|
||||
http.post('/app/sqConsignPt/flowStart', data),
|
||||
/** 合同系统/签约授权 删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/sqConsignPt/deletes', data),
|
||||
/** 合同系统/签约授权 签约授权提交 */
|
||||
post_submit: (data?: BodyOptions) =>
|
||||
http.post('/app/sqConsignPt/submit', data),
|
||||
},
|
||||
addressorsort: {
|
||||
/** 协同办公/会议管理/发言人顺序配置 发言人顺序查询 */
|
||||
get_page: (data?: QueryOptions) =>
|
||||
http.get('/app/addressorsort/page', data),
|
||||
/** 协同办公/会议管理/发言人顺序配置 发言人排序保存 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/addressorsort/save', data),
|
||||
/** 协同办公/会议管理/发言人顺序配置 删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/addressorsort/deletes', data),
|
||||
},
|
||||
equInfo: {
|
||||
/** 设备管理/设备静态库管理/ 设备信息维护 设备信息保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/equInfo/save', data),
|
||||
/** 设备管理/设备静态库管理/ 设备信息维护 设备信息(获取/查询) */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/equInfo/page', data),
|
||||
/** 设备管理/设备静态库管理/ 设备信息维护 设备信息删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/equInfo/deletes', data),
|
||||
},
|
||||
equAllot: {
|
||||
/** 设备管理/查询管理/设备调拨查询 查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/equAllot/page', data),
|
||||
/** 设备管理/设备静态库管理/设备调拨 调拨信息保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/equAllot/save', data),
|
||||
/** 设备管理/设备静态库管理/设备调拨 调拨信息删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/equAllot/deletes', data),
|
||||
},
|
||||
bidding: {
|
||||
/** 合同系统/标段信息 标段查询 */
|
||||
get_list: (data?: QueryOptions) => http.get('/app/bidding/list', data),
|
||||
/** 合同系统/标段信息 标段信息保存(弃用,在选商中报错) */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/bidding/save', data),
|
||||
/** 合同系统/标段信息 标段信息删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/bidding/deletes', data),
|
||||
/** 合同系统/选商/选商结果 查询标段列表 */
|
||||
get_getBuddingPtInfoList: (data?: QueryOptions) =>
|
||||
http.get('/app/bidding/getBuddingPtInfoList', data),
|
||||
},
|
||||
equAccident: {
|
||||
/** 设备管理/设备使用管理/事故处理 事故处理(查询/获取) */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/equAccident/page', data),
|
||||
/** 设备管理/设备使用管理/事故处理 保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/equAccident/save', data),
|
||||
/** 设备管理/设备使用管理/事故处理 删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/equAccident/deletes', data),
|
||||
/** 设备管理/查询管理/事故处理查询 查询 */
|
||||
get_query: (data?: QueryOptions) =>
|
||||
http.get('/app/equAccident/query', data),
|
||||
},
|
||||
equStopRepair: {
|
||||
/** 设备管理/设备使用管理/停炉检修处理 查询 */
|
||||
get_page: (data?: QueryOptions) =>
|
||||
http.get('/app/equStopRepair/page', data),
|
||||
/** 设备管理/设备使用管理/停炉检修处理 保存 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/equStopRepair/save', data),
|
||||
/** 设备管理/设备使用管理/停炉检修处理 删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/equStopRepair/deletes', data),
|
||||
/** 设备管理/查询管理/停炉检修处理查询 查询 */
|
||||
get_query: (data?: QueryOptions) =>
|
||||
http.get('/app/equStopRepair/query', data),
|
||||
},
|
||||
equDanger: {
|
||||
/** 设备管理/设备使用管理/隐患排查 查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/equDanger/page', data),
|
||||
/** 设备管理/设备使用管理/隐患排查 保存 */
|
||||
post_save: (data?: BodyOptions) => http.post('/app/equDanger/save', data),
|
||||
/** 设备管理/设备使用管理/隐患排查 删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/equDanger/deletes', data),
|
||||
/** 设备管理/查询管理/隐患排查处理查询 查询 */
|
||||
get_query: (data?: QueryOptions) => http.get('/app/equDanger/query', data),
|
||||
},
|
||||
equDayRepair: {
|
||||
/** 设备管理/设备使用管理/日常维修 查询 */
|
||||
get_page: (data?: QueryOptions) => http.get('/app/equDayRepair/page', data),
|
||||
/** 设备管理/设备使用管理/日常维修 保存 */
|
||||
post_save: (data?: BodyOptions) =>
|
||||
http.post('/app/equDayRepair/save', data),
|
||||
/** 设备管理/设备使用管理/日常维修 删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/equDayRepair/deletes', data),
|
||||
/** 设备管理/查询管理/日常维修查询 查询 */
|
||||
get_query: (data?: QueryOptions) =>
|
||||
http.get('/app/equDayRepair/query', data),
|
||||
},
|
||||
contractRecommendProvider: {
|
||||
/** 合同系统/选商/合同推荐供应商信息 推荐供应商查询 */
|
||||
get_list: (data?: QueryOptions) =>
|
||||
http.get('/app/contractRecommendProvider/list', data),
|
||||
/** 合同系统/选商/合同推荐供应商信息 删除 */
|
||||
post_deletes: (data?: BodyOptions) =>
|
||||
http.post('/app/contractRecommendProvider/deletes', data),
|
||||
},
|
||||
};
|
|
@ -1,19 +0,0 @@
|
|||
|
||||
/** BaseUrl: 基础路径 */
|
||||
const BASE_URL: string = '/api'
|
||||
|
||||
/** AccessTokenField: header 里传accessToken的键名,一般为 Authorization */
|
||||
export const ACCESS_TOKEN_FIELD = 'Token'
|
||||
|
||||
/**
|
||||
* 动态获取baseURL,仅限开发环境
|
||||
* 适用于同时连接多个后端功能开发,通过设置 proxy_type 值实现‘非重启更新’连接的后端
|
||||
*/
|
||||
export function getBaseURL(): string {
|
||||
if (import.meta.env.MODE === 'development') {
|
||||
const proxyType = localStorage.getItem('@@@proxy_type') || '';
|
||||
// return BASE_URL + "/zzz"
|
||||
return BASE_URL + proxyType
|
||||
}
|
||||
return BASE_URL
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
|
||||
/**
|
||||
* 获取RefreshToken
|
||||
* @description: 创建新的请求实例实现
|
||||
*/
|
||||
import { createAlova } from 'alova'
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
import fetchAdapter from 'alova/fetch';
|
||||
import vueHook from 'alova/vue';
|
||||
import { getBaseURL, ACCESS_TOKEN_FIELD } from './config';
|
||||
|
||||
let lock = false
|
||||
let promiseResult: any[] = []
|
||||
|
||||
const alova = createAlova({
|
||||
baseURL: getBaseURL(),
|
||||
cacheFor: null,
|
||||
statesHook: vueHook,
|
||||
requestAdapter: fetchAdapter(),
|
||||
beforeRequest: (method) => {
|
||||
// ...原请求前拦截器
|
||||
const accessStore = useAccessStore();
|
||||
|
||||
// const userStore = useUserStore()
|
||||
// console.log('beforeRequest', userStore.accessToken)
|
||||
// 添加token到请求头
|
||||
// method.config.headers[ACCESS_TOKEN_FIELD] = `${userStore.accessToken}`
|
||||
},
|
||||
responded: async (response, method) => {
|
||||
let json = await response.json();
|
||||
return json.data || null
|
||||
},
|
||||
})
|
||||
|
||||
export function getAccessToken(rToken: string): Promise<any> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
promiseResult.push({
|
||||
resolve,
|
||||
reject
|
||||
})
|
||||
// const userStore = useUserStore();
|
||||
|
||||
if (!lock) {
|
||||
lock = true
|
||||
// 为了让refreshToken请求顺利通过,需要通过元数据标识authRole为refreshToken。参考官方文档
|
||||
const method = alova.Post('/system/auth/refreshToken', { token: rToken }, {
|
||||
meta: {
|
||||
authRole: 'refreshToken'
|
||||
}
|
||||
});
|
||||
method.send()
|
||||
.then((data: any) => {
|
||||
console.log(data)
|
||||
// 如果 refreshToken 请求成功,则将新的token存储到本地
|
||||
if (data && data.accessToken) {
|
||||
// userStore.setToken(data.accessToken);
|
||||
// userStore.setTokenExpiresTime(data.accessExpire)
|
||||
// userStore.setRefreshToken(data.refreshToken);
|
||||
while (promiseResult.length) {
|
||||
// p1.resolve(res.data)
|
||||
promiseResult.shift().resolve(data)
|
||||
}
|
||||
lock = false
|
||||
return
|
||||
}
|
||||
// userStore.resetStore()
|
||||
while (promiseResult.length) {
|
||||
// p1.reject(err)
|
||||
promiseResult.shift().reject("身份认证已失效,请重新登录")
|
||||
}
|
||||
|
||||
})
|
||||
.catch(err => {
|
||||
while (promiseResult.length) {
|
||||
// p1.reject(err)
|
||||
promiseResult.shift().reject(err)
|
||||
}
|
||||
lock = false
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
}
|
|
@ -1,324 +0,0 @@
|
|||
/**
|
||||
* 该文件可自行根据业务逻辑进行调整
|
||||
*/
|
||||
import { preferences } from '@vben/preferences';
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
import { createAlova } from 'alova';
|
||||
import { createServerTokenAuthentication } from 'alova/client';
|
||||
import fetchAdapter from 'alova/fetch';
|
||||
import vueHook from 'alova/vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { merge } from 'lodash-es';
|
||||
|
||||
import { useAuthStore } from '#/store';
|
||||
|
||||
import { type BodyOptions, type QueryOptions } from '../global.d';
|
||||
import { ACCESS_TOKEN_FIELD, getBaseURL } from './config';
|
||||
import { transferResponse } from './transferResponse';
|
||||
|
||||
/** 储存过期的token */
|
||||
const expireTokenCache = [];
|
||||
|
||||
/** 服务端 Token 校验 */
|
||||
const { onAuthRequired, onResponseRefreshToken } =
|
||||
createServerTokenAuthentication({
|
||||
refreshTokenOnSuccess: {
|
||||
/**
|
||||
* 判断 Token 是否过期
|
||||
* 响应时触发,可获取到response和method,并返回boolean表示token是否过期
|
||||
*/
|
||||
isExpired: async (response, method) => {
|
||||
// 文件下载操作
|
||||
if (method.meta?.responseType === 'blob') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const responseClone = response.clone();
|
||||
const data = await responseClone.json();
|
||||
|
||||
// 当服务端返回401时,表示token过期
|
||||
const isExpired = ['401'].includes(data.code);
|
||||
if (isExpired) {
|
||||
console.log('AccessToken已过期', data.code);
|
||||
expireTokenCache.push(method.config.headers[ACCESS_TOKEN_FIELD]);
|
||||
}
|
||||
|
||||
return isExpired;
|
||||
},
|
||||
/** 当token过期时触发,在此函数中触发刷新token */
|
||||
handler: async (_response, _method) => {
|
||||
console.warn('Access token or refresh token is invalid or expired. ');
|
||||
const accessStore = useAccessStore();
|
||||
const authStore = useAuthStore();
|
||||
accessStore.setAccessToken(null);
|
||||
if (
|
||||
preferences.app.loginExpiredMode === 'modal' &&
|
||||
accessStore.isAccessChecked
|
||||
) {
|
||||
accessStore.setLoginExpired(true);
|
||||
} else {
|
||||
await authStore.logout(false);
|
||||
}
|
||||
throw new Error('登录已过期,请重新登录');
|
||||
|
||||
// const userStore = useUserStore();
|
||||
// try {
|
||||
// let rToken = userStore.refreshToken;
|
||||
// // 如果没有refreshToken,则跳转登录页
|
||||
// if (!rToken) {
|
||||
// throw new Error('登录已过期,请重新登录');
|
||||
// }
|
||||
// await getAccessToken(rToken)
|
||||
// expireTokenCache = []
|
||||
// } catch (error: any) {
|
||||
// window.$message?.error(error.message);
|
||||
// userStore.resetStore()
|
||||
// throw error;
|
||||
// }
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const alovaInstance = createAlova({
|
||||
/** 动态代理配置 */
|
||||
baseURL: getBaseURL(),
|
||||
/** 框架请求适配器 */
|
||||
statesHook: vueHook,
|
||||
requestAdapter: fetchAdapter(),
|
||||
/** 设置缓存状态:不开启 */
|
||||
cacheFor: null,
|
||||
// cacheFor: {
|
||||
// // 统一设置POST的缓存模式
|
||||
// GET: {
|
||||
// mode: 'restore',
|
||||
// expire: 60 * 10 * 1000,
|
||||
// },
|
||||
// // POST: {
|
||||
// // mode: 'restore',
|
||||
// // expire: 60 * 10 * 1000
|
||||
// // },
|
||||
// // // 统一设置HEAD请求的缓存模式
|
||||
// // HEAD: 60 * 10 * 1000
|
||||
// },
|
||||
/** 请求拦截器 */
|
||||
beforeRequest: onAuthRequired((method) => {
|
||||
const accessStore = useAccessStore();
|
||||
|
||||
if (accessStore.accessToken) {
|
||||
method.config.headers.Token = accessStore.accessToken;
|
||||
// 统一授权的这个接口需要以Authorization传参,无语 /sys/user/functiontree/XTBGXT
|
||||
method.config.headers.Authorization = `Bearer ${accessStore.accessToken}`;
|
||||
}
|
||||
method.config.headers['Accept-Language'] = preferences.app.locale;
|
||||
|
||||
// const userStore = useUserStore()
|
||||
// // 添加token到请求头
|
||||
// if (userStore.accessToken) {
|
||||
// method.config.headers[ACCESS_TOKEN_FIELD] = `Bearer ${userStore.accessToken}`
|
||||
|
||||
// method.config.headers["Authorization"] = `Bearer ${userStore.accessToken}`
|
||||
// }
|
||||
|
||||
// method.config.cacheFor = {
|
||||
// // 设置缓存模式为内存模式
|
||||
// mode: 'restore',
|
||||
// // 单位为毫秒
|
||||
// // 当设置为`Infinity`,表示数据永不过期,设置为0或负数时表示不缓存
|
||||
// expire: 60 * 10 * 1000
|
||||
// }
|
||||
// method.config.transform = (rawData, headers) => {
|
||||
// console.log('接口响应', rawData)
|
||||
// return transferResponse(rawData)
|
||||
// }
|
||||
}),
|
||||
/** 响应拦截器 */
|
||||
responded: onResponseRefreshToken(async (response, method) => {
|
||||
if (method.meta?.responseType === 'blob') {
|
||||
const blob = await response.blob();
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
const contentDisposition = response.headers.get('content-disposition');
|
||||
let fileName = 'downloaded-file';
|
||||
if (contentDisposition) {
|
||||
const matches = /filename="?([^"]+)"?/.exec(contentDisposition);
|
||||
if (matches != null && matches[1]) {
|
||||
fileName = decodeURIComponent(matches[1]);
|
||||
}
|
||||
}
|
||||
a.download = fileName;
|
||||
// 触发下载
|
||||
document.body.append(a);
|
||||
a.click();
|
||||
// 移除链接
|
||||
a.remove();
|
||||
window.URL.revokeObjectURL(url);
|
||||
return {
|
||||
blob,
|
||||
url,
|
||||
filename: fileName,
|
||||
};
|
||||
}
|
||||
|
||||
// if (response.status >= 400) {
|
||||
// throw new Error(response.statusText);
|
||||
// }
|
||||
|
||||
let json = await response.json();
|
||||
console.log('【接口】', method.url);
|
||||
console.log('原始响应', JSON.parse(JSON.stringify(json)));
|
||||
|
||||
json = transferResponse(json);
|
||||
console.log('改造响应', JSON.parse(JSON.stringify(json)));
|
||||
|
||||
const accessStore = useAccessStore();
|
||||
|
||||
if (json.code != 0) {
|
||||
if (json.code == '401') {
|
||||
message.error('用户身份过期,请重新登录');
|
||||
|
||||
const authStore = useAuthStore();
|
||||
accessStore.setAccessToken(null);
|
||||
await authStore.logout();
|
||||
// const userStore = useUserStore();
|
||||
// userStore.resetStore();
|
||||
} else {
|
||||
message.error(json.msg || '服务器开小差,请稍后再试');
|
||||
}
|
||||
// 抛出错误或返回reject状态的Promise实例时,此请求将抛出错误
|
||||
throw new Error((json && json.msg) || '出错了');
|
||||
}
|
||||
|
||||
// 解析的响应数据将传给method实例的transformData钩子函数,这些函数将在后续讲解
|
||||
return json.data;
|
||||
}),
|
||||
});
|
||||
|
||||
// 请求配置处理中间件
|
||||
function requestConfigMiddleware(method: string, url: string) {}
|
||||
|
||||
class Http {
|
||||
private appendParamsToUrl(url: string, params: any): string {
|
||||
let queryString = '';
|
||||
for (const key in params) {
|
||||
if (Object.prototype.hasOwnProperty.call(params, key)) {
|
||||
queryString += `${queryString ? '&' : '?'}${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`;
|
||||
}
|
||||
}
|
||||
return url + queryString;
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局默认配置
|
||||
* @param customConfig
|
||||
* @returns
|
||||
*/
|
||||
private getConfig(customConfig?: any): any {
|
||||
// 递归属性拷贝
|
||||
return merge(
|
||||
{},
|
||||
{
|
||||
meta: {
|
||||
showLoading: false,
|
||||
showError: false,
|
||||
},
|
||||
},
|
||||
customConfig,
|
||||
);
|
||||
}
|
||||
|
||||
private isBodyOptions(
|
||||
options: BodyOptions | QueryOptions,
|
||||
): options is BodyOptions {
|
||||
return (options as BodyOptions).data !== undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* 适配swagger路径参数,针对于pathParams
|
||||
* 输入参数 "/api/v1/user/{id}",{ pathParams:{ id :1 },params:{ id:2 } }
|
||||
* 输出请求 /api/v1/user/1?id=2
|
||||
*/
|
||||
private replacePathParams(url: string, pathParams?: any): string {
|
||||
if (!pathParams) return url;
|
||||
return url.replaceAll(
|
||||
/\{(\w+)\}/g,
|
||||
(_, key) => pathParams[key] || `{${key}}`,
|
||||
);
|
||||
}
|
||||
|
||||
private request(
|
||||
method: string,
|
||||
url: string,
|
||||
data?: BodyOptions | QueryOptions,
|
||||
): Promise<any> {
|
||||
let finalUrl = this.replacePathParams(url, data?.pathParams);
|
||||
const config = this.getConfig(data?.config);
|
||||
|
||||
// 当组件使用allowClear属性时,会将数据置为null,导致数据查询失败
|
||||
if (data && data.params) {
|
||||
Object.keys(data.params).forEach((key) => {
|
||||
if (data.params[key] === null || data.params[key] === undefined) {
|
||||
delete data.params[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
if (data && this.isBodyOptions(data)) {
|
||||
Object.keys(data.data).forEach((key) => {
|
||||
if (data.data[key] === null || data.data[key] === undefined) {
|
||||
delete data.data[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let alovaMethod: 'Delete' | 'Get' | 'Post' | 'Put' = 'Get';
|
||||
|
||||
if (method === 'get' || method === 'delete') {
|
||||
if (method === 'get') {
|
||||
alovaMethod = 'Get';
|
||||
}
|
||||
if (method === 'delete') {
|
||||
alovaMethod = 'Delete';
|
||||
}
|
||||
return alovaInstance[alovaMethod](finalUrl, {
|
||||
...config,
|
||||
params: data?.params,
|
||||
});
|
||||
} else {
|
||||
// 处理 params 到 url 的逻辑
|
||||
if (data?.params) {
|
||||
finalUrl = this.appendParamsToUrl(finalUrl, data.params);
|
||||
}
|
||||
if (method === 'post') {
|
||||
alovaMethod = 'Post';
|
||||
}
|
||||
if (method === 'put') {
|
||||
alovaMethod = 'Put';
|
||||
}
|
||||
|
||||
return alovaInstance[alovaMethod](finalUrl, data?.data, { ...config });
|
||||
}
|
||||
}
|
||||
|
||||
delete(url: string, data?: QueryOptions) {
|
||||
return this.request('delete', url, data);
|
||||
}
|
||||
|
||||
get(url: string, data?: QueryOptions) {
|
||||
return this.request('get', url, data);
|
||||
}
|
||||
|
||||
patch(url: string, data?: BodyOptions) {
|
||||
return this.request('patch', url, data);
|
||||
}
|
||||
|
||||
post(url: string, data?: BodyOptions) {
|
||||
return this.request('post', url, data);
|
||||
}
|
||||
|
||||
put(url: string, data?: BodyOptions) {
|
||||
return this.request('put', url, data);
|
||||
}
|
||||
}
|
||||
|
||||
export const http = new Http();
|
|
@ -1,89 +0,0 @@
|
|||
const SUCCESS_CODE = 0;
|
||||
|
||||
/**
|
||||
* 统一相应处理,伪BFF层 很多接口返回的响应信息不统一,防止因后端规范问题导致前端工作量增加!!!!!!!故在此做统一处理
|
||||
* 目前项目后端会返回的几种响应情况,xxx代指需要的数据:[xxx]、{xxx}、{data:{xxx}}、{records:xxx}、{content:xxx}.........................沉默
|
||||
* 数据总条数涉及字段:total、totalElements
|
||||
*
|
||||
* @param response
|
||||
*/
|
||||
export function transferResponse(response: any) {
|
||||
// 如果后端直接返回数组,如[xxx]
|
||||
if (Array.isArray(response)) {
|
||||
return {
|
||||
code: SUCCESS_CODE,
|
||||
data: {
|
||||
rows: response,
|
||||
},
|
||||
msg: 'Ok',
|
||||
};
|
||||
}
|
||||
|
||||
// 如果后端直接返回数据内容对象,如{xxx},则先进行统一响应包装
|
||||
if (response.code == undefined) {
|
||||
response = {
|
||||
code: SUCCESS_CODE,
|
||||
data: response,
|
||||
msg: 'Ok',
|
||||
};
|
||||
}
|
||||
|
||||
let { code, data = {}, msg, ...rest } = response;
|
||||
|
||||
if (!data) {
|
||||
data = {};
|
||||
}
|
||||
if (typeof data === 'string') {
|
||||
data = {
|
||||
value: data,
|
||||
};
|
||||
}
|
||||
// eslint-disable-next-line eqeqeq
|
||||
if (code == 'success') {
|
||||
code = 0;
|
||||
}
|
||||
|
||||
if (code == 'failure' && msg && msg.includes('token无效')) {
|
||||
code = 401;
|
||||
}
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
data = {
|
||||
rows: data,
|
||||
};
|
||||
}
|
||||
|
||||
if (!data.total && data.totalElements) {
|
||||
data.total = data.totalElements;
|
||||
}
|
||||
|
||||
if (data.records && Array.isArray(data.records)) {
|
||||
data.rows = data.records;
|
||||
delete data.records;
|
||||
}
|
||||
|
||||
if (data.content && Array.isArray(data.content)) {
|
||||
data.rows = data.content;
|
||||
delete data.content;
|
||||
}
|
||||
|
||||
if (data.content && Array.isArray(data.records)) {
|
||||
data.rows = data.records;
|
||||
delete data.records;
|
||||
}
|
||||
|
||||
if (response.code == 200 && response.flag === false) {
|
||||
code = 500;
|
||||
} else if (response.code == '200') {
|
||||
code = 0;
|
||||
}
|
||||
|
||||
return {
|
||||
code,
|
||||
data: {
|
||||
...data,
|
||||
...rest,
|
||||
},
|
||||
msg,
|
||||
};
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
import { http } from '../request/index';
|
||||
|
||||
import { useAccessStore } from '@vben/stores';
|
||||
|
||||
export namespace AuthApi {
|
||||
/** 登录接口参数 */
|
||||
export interface LoginParams {
|
||||
password: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
/** 登录接口返回值 */
|
||||
export interface LoginResult {
|
||||
accessToken: string;
|
||||
desc: string;
|
||||
realName: string;
|
||||
userId: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface RefreshTokenResult {
|
||||
data: string;
|
||||
status: number;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
export async function loginApi(data: AuthApi.LoginParams) {
|
||||
return http.post('/uc/uaa/validateAccount', {
|
||||
data,
|
||||
config: {
|
||||
transform(rawData) {
|
||||
if (rawData.access_token) {
|
||||
rawData.accessToken = rawData.access_token;
|
||||
rawData.realName = rawData.display_name;
|
||||
return rawData;
|
||||
}
|
||||
return rawData;
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新accessToken
|
||||
*/
|
||||
export async function refreshTokenApi() {
|
||||
return http.post('/auth/refresh');
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
export async function logoutApi() {
|
||||
return http.post('/uc/uaa/logout');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户权限码
|
||||
*/
|
||||
export async function getAccessCodesApi() {
|
||||
return http.post('/auth/codes');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*/
|
||||
export async function getUserInfoApi() {
|
||||
const accessStore = useAccessStore();
|
||||
return http.post('/uc/sys/user/checkToken', {
|
||||
data: {
|
||||
token: accessStore.accessToken,
|
||||
},
|
||||
});
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import { http } from '../request/index';
|
||||
|
||||
/**
|
||||
* 获取用户所有菜单
|
||||
*/
|
||||
export async function getAllMenusApi() {
|
||||
return http.get('/menu/all');
|
||||
}
|
|
@ -1,115 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { useAntdDesignTokens } from '@vben/hooks';
|
||||
import { preferences, usePreferences } from '@vben/preferences';
|
||||
|
||||
import { App, ConfigProvider, theme } from 'ant-design-vue';
|
||||
|
||||
import { antdLocale } from '#/locales';
|
||||
|
||||
import { useDictStore } from './store/dict';
|
||||
|
||||
defineOptions({ name: 'App' });
|
||||
|
||||
const { isDark } = usePreferences();
|
||||
const { tokens } = useAntdDesignTokens();
|
||||
|
||||
const tokenTheme = computed(() => {
|
||||
const algorithm = isDark.value
|
||||
? [theme.darkAlgorithm]
|
||||
: [theme.defaultAlgorithm];
|
||||
|
||||
// antd 紧凑模式算法
|
||||
if (preferences.app.compact) {
|
||||
algorithm.push(theme.compactAlgorithm);
|
||||
}
|
||||
|
||||
return {
|
||||
algorithm,
|
||||
token: tokens,
|
||||
};
|
||||
});
|
||||
|
||||
const dictStore = useDictStore();
|
||||
if (dictStore.initDict) {
|
||||
dictStore.setDictMap();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ConfigProvider :locale="antdLocale" :theme="tokenTheme">
|
||||
<App>
|
||||
<RouterView />
|
||||
</App>
|
||||
</ConfigProvider>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.vxebasic-table-container {
|
||||
flex: auto;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.ant-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ant-modal-confirm-btns {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.ant-btn__warning {
|
||||
@apply bg-warning text-warning-foreground hover:bg-warning/90 shadow;
|
||||
}
|
||||
|
||||
.ant-checkbox-disabled .ant-checkbox-inner {
|
||||
background: #fafafa;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.ant-input-number-disabled {
|
||||
background: #fafafa;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.ant-input-affix-wrapper-disabled,
|
||||
.ant-input-affix-wrapper[disabled] {
|
||||
background: #fafafa;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.ant-radio-wrapper-disabled {
|
||||
background: #fafafa;
|
||||
color: #333;
|
||||
}
|
||||
.ant-radio-wrapper .ant-radio-disabled .ant-radio-inner {
|
||||
background-color: rgba(50, 54, 57, 0.04);
|
||||
border-color: hsl(240 5.9% 90%);
|
||||
}
|
||||
|
||||
.ant-picker.ant-picker-disabled {
|
||||
background: #fafafa;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.ant-select-disabled.ant-select:not(.ant-select-customize-input)
|
||||
.ant-select-selector {
|
||||
background: #fafafa;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.ant-picker .ant-picker-input > input-disabled,
|
||||
.ant-picker .ant-picker-input > input[disabled] {
|
||||
background: #fafafa;
|
||||
color: #333 !important;
|
||||
}
|
||||
|
||||
.ant-input-disabled,
|
||||
.ant-input[disabled] {
|
||||
background: #fafafa;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
Binary file not shown.
Before Width: | Height: | Size: 4.3 KiB |
|
@ -1,41 +0,0 @@
|
|||
import { createApp } from 'vue';
|
||||
|
||||
import { registerAccessDirective } from '@vben/access';
|
||||
import { initStores } from '@vben/stores';
|
||||
import '@vben/styles';
|
||||
import '@vben/styles/antd';
|
||||
import { VbenButton } from '@vben-core/shadcn-ui';
|
||||
|
||||
import { setupI18n } from '#/locales';
|
||||
|
||||
import App from './app.vue';
|
||||
import { registerFastCrud } from './plugins/fastCrud';
|
||||
import { registerVxeTable } from './plugins/vxeTable';
|
||||
import { router } from './router';
|
||||
|
||||
async function bootstrap(namespace: string) {
|
||||
const app = createApp(App);
|
||||
|
||||
// 国际化 i18n 配置
|
||||
await setupI18n(app);
|
||||
|
||||
// 配置 pinia-tore
|
||||
await initStores(app, { namespace });
|
||||
|
||||
// 安装权限指令
|
||||
registerAccessDirective(app);
|
||||
|
||||
// 配置路由及路由守卫
|
||||
app.use(router);
|
||||
|
||||
// 引入 fast-crud 相关组件
|
||||
registerFastCrud(app);
|
||||
|
||||
registerVxeTable(app);
|
||||
|
||||
app.component('vben-button', VbenButton);
|
||||
|
||||
app.mount('#app');
|
||||
}
|
||||
|
||||
export { bootstrap };
|
|
@ -1,97 +0,0 @@
|
|||
import { dict } from '@fast-crud/fast-crud';
|
||||
|
||||
import Apis from '#/api';
|
||||
|
||||
export const unitComponentProps = {
|
||||
name: 'fs-dict-tree',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
class: 'min-w-[180px]',
|
||||
showCheckedStrategy: 'SHOW_CHILD',
|
||||
showSearch: true,
|
||||
'tree-node-filter-prop': 'label',
|
||||
dict: dict({
|
||||
isTree: true,
|
||||
async getData(_context) {
|
||||
const data: any = await Apis.api.core.orgemplbc.organization.post_paging({
|
||||
params: {
|
||||
page: 1,
|
||||
size: 1000,
|
||||
},
|
||||
data: {
|
||||
subFilter: [
|
||||
{
|
||||
symbol: 'like',
|
||||
singleValue: '0001%',
|
||||
key: 'ORG_ID',
|
||||
logic: 'AND',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
data.rows.forEach((item: any) => {
|
||||
item.label = item.ORG_NAME;
|
||||
item.value = item.ORG_ID;
|
||||
});
|
||||
const treeData = transTree(data.rows);
|
||||
return treeData;
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
export async function getUnitData(_params?: any) {
|
||||
const data: any = await Apis.api.core.orgemplbc.organization.post_paging({
|
||||
params: {
|
||||
page: 1,
|
||||
size: 1000,
|
||||
},
|
||||
data: {
|
||||
subFilter: [
|
||||
{
|
||||
symbol: 'like',
|
||||
singleValue: '0001%',
|
||||
key: 'ORG_ID',
|
||||
logic: 'AND',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
data.rows.forEach((item: any) => {
|
||||
item.label = item.ORG_NAME;
|
||||
item.value = item.ORG_ID;
|
||||
});
|
||||
const treeData = transTree(data.rows);
|
||||
return treeData;
|
||||
}
|
||||
|
||||
// 转换树行数据的方法
|
||||
function transTree(list) {
|
||||
// 最终生成的树行结构
|
||||
const _treeData: any[] = [];
|
||||
|
||||
// 对传入进来的 数据进行遍历,查找对应的子级
|
||||
list.forEach((item) => {
|
||||
// 给每一项添加子节点
|
||||
// item.children = []
|
||||
item.key = item.ORG_ID;
|
||||
item.label = item.ORG_NAME;
|
||||
// 如果 pid 为空,说明是最顶级,直接放到 _treeData 中即可
|
||||
if (item.ORG_LEVEL === 1) {
|
||||
item.selectable = false;
|
||||
_treeData.push(item);
|
||||
}
|
||||
|
||||
// 根据前面的分析,pid 代表的是父级的 id,从而可以进行筛选子级
|
||||
// filter 方法会把满足条件到的每一项,组成一个数组进行返回
|
||||
const children = list.filter((data) => data.PARENT_ID === item.ORG_ID);
|
||||
|
||||
// 如果没有子节点,直接 return 不做任何处理
|
||||
if (children.length === 0) return;
|
||||
|
||||
// 将返回的子级进行赋值给父级(item)的 children 属性
|
||||
item.children = children;
|
||||
});
|
||||
|
||||
// 将最终生成的数据返回出去
|
||||
return _treeData;
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
<template>
|
||||
<template v-if="props.selectable">
|
||||
<div
|
||||
v-for="(dict, index) in dicts"
|
||||
:key="index"
|
||||
@click="handleClick(dict)"
|
||||
:class="{ 'cursor-pointer': selectable }"
|
||||
>
|
||||
<a-tag :color="getTagColor(dict)" :round="!multiple">
|
||||
{{ dict[labelField] }}
|
||||
</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
<div v-else-if="Array.isArray(value)" class="flex flex-row flex-wrap">
|
||||
<template v-for="(dict, index) in dicts" :key="index">
|
||||
<div v-if="selectedValues.includes(dict.value)" class="mb-1">
|
||||
<a-tag>
|
||||
{{ dict[labelField] }}
|
||||
</a-tag>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<template v-else>
|
||||
<a-tag :color="dict?.colorType || ''">
|
||||
{{ (dict && dict[labelField]) || value }}
|
||||
</a-tag>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { Tag, Space } from 'ant-design-vue';
|
||||
import { getDictOpts, getDictObj } from '#/utils/dict';
|
||||
import type { DictDataType } from '#/utils/dict';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
type?: string;
|
||||
options: DictDataType[];
|
||||
value?: string | number | boolean | Array<string | number | boolean>;
|
||||
icon?: string;
|
||||
multiple?: boolean;
|
||||
selectable?: boolean;
|
||||
labelField?: string;
|
||||
valueField?: string;
|
||||
}>(),
|
||||
{
|
||||
type: '',
|
||||
options: () => [],
|
||||
multiple: false,
|
||||
selectable: false,
|
||||
labelField: 'label',
|
||||
valueField: 'value',
|
||||
value: '',
|
||||
icon: '',
|
||||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits(['update:value', 'tag-click']);
|
||||
|
||||
const dictData = ref<DictDataType | null>(null);
|
||||
const selectedValues = ref<Array<string | number>>(
|
||||
Array.isArray(props.value) ? props.value : [],
|
||||
);
|
||||
|
||||
const dicts = computed(() => {
|
||||
return props.type ? getDictOpts(props.type) : props.options;
|
||||
});
|
||||
|
||||
const dict = computed(() => {
|
||||
for (const item of props.options) {
|
||||
if (item[props.valueField] == props.value) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
});
|
||||
|
||||
const handleClick = (dict: DictDataType) => {
|
||||
emit('tag-click', dict);
|
||||
if (props.selectable) {
|
||||
if (props.multiple) {
|
||||
const index = selectedValues.value.indexOf(dict.value);
|
||||
if (index === -1) {
|
||||
selectedValues.value.push(dict.value);
|
||||
} else {
|
||||
selectedValues.value.splice(index, 1);
|
||||
}
|
||||
emit('update:value', selectedValues.value);
|
||||
} else {
|
||||
emit('update:value', dict.value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getTagColor = (dict: DictDataType) => {
|
||||
return (props.multiple && selectedValues.value.includes(dict.value)) ||
|
||||
(!props.multiple && props.value == dict.value)
|
||||
? 'blue'
|
||||
: '';
|
||||
};
|
||||
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
|
@ -1 +0,0 @@
|
|||
export { default as DictTag } from './dict-tag.vue';
|
|
@ -1,13 +0,0 @@
|
|||
import type { VxeGridPropTypes } from 'vxe-table';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
import { useRender } from '#/hooks/useRender';
|
||||
|
||||
export const PrimaryKey = 'guid';
|
||||
|
||||
export function getColumns(_params: any = {}): VxeGridPropTypes.Columns {
|
||||
return [
|
||||
|
||||
];
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import { nextTick, ref, watch } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { logger } from 'common-utils';
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
loading?: boolean;
|
||||
}>(),
|
||||
{
|
||||
loading: false,
|
||||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'confirm', data: any): void;
|
||||
(e: 'update:loading', data: any): void;
|
||||
}>();
|
||||
|
||||
const isConfirmLoading = ref(false);
|
||||
|
||||
const data = ref({
|
||||
title: '',
|
||||
schema: {},
|
||||
});
|
||||
const formRef = ref();
|
||||
|
||||
const formBinding = ref();
|
||||
|
||||
const [Modal, modalApi] = useVbenModal({
|
||||
async onOpenChange(isOpen: boolean) {
|
||||
if (isOpen) {
|
||||
data.value = modalApi.getData<Record<string, any>>() || {};
|
||||
|
||||
formBinding.value = data.value.schema || {};
|
||||
|
||||
nextTick(() => {});
|
||||
}
|
||||
isConfirmLoading.value = false;
|
||||
},
|
||||
async onConfirm() {
|
||||
isConfirmLoading.value = true;
|
||||
|
||||
try {
|
||||
await formRef.value?.submit();
|
||||
emit('confirm', formRef.value.form);
|
||||
} catch (error) {
|
||||
logger.error('', error);
|
||||
} finally {
|
||||
isConfirmLoading.value = false;
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<Modal :confirm-loading="loading" :loading="loading" :title="data.title">
|
||||
<fs-form v-if="formBinding.columns" ref="formRef" v-bind="formBinding" />
|
||||
</Modal>
|
||||
</template>
|
|
@ -1,28 +0,0 @@
|
|||
import type { RouteMeta as IRouteMeta } from '@vben-core/typings';
|
||||
|
||||
import 'vue-router';
|
||||
|
||||
declare module 'vue-router' {
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
interface RouteMeta extends IRouteMeta {}
|
||||
}
|
||||
|
||||
export interface VbenAdminProAppConfigRaw {
|
||||
VITE_GLOB_API_URL: string;
|
||||
}
|
||||
|
||||
export interface ApplicationConfig {
|
||||
apiURL: string;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
_VBEN_ADMIN_PRO_APP_CONF_: VbenAdminProAppConfigRaw;
|
||||
}
|
||||
}
|
||||
|
||||
export interface PageVo {
|
||||
code: number;
|
||||
data: any;
|
||||
message: string;
|
||||
}
|
|
@ -1,149 +0,0 @@
|
|||
import { h } from 'vue';
|
||||
import dayjs from 'dayjs';
|
||||
import { Button, Tag } from 'ant-design-vue';
|
||||
import { isArray, isString } from 'lodash-es';
|
||||
import { DictTag } from '#/components/dict-tag';
|
||||
// import { Icon } from '@/components/Icon';
|
||||
import { Tooltip } from 'ant-design-vue'
|
||||
import { getDictOpts } from '#/utils/dict';
|
||||
export const useRender = {
|
||||
/**
|
||||
* 渲染图片
|
||||
* @param text 图片地址
|
||||
* @returns image标签
|
||||
*/
|
||||
// renderImg: (text: string) => {
|
||||
// if (text) {
|
||||
// if (isArray(text)) return h(TableImg, { imgList: text });
|
||||
// else if (isString(text)) return h(TableImg, { imgList: [text] });
|
||||
// }
|
||||
// return '';
|
||||
// },
|
||||
/**
|
||||
* 渲染链接
|
||||
* @param url 链接地址
|
||||
* @param text 文字说明
|
||||
* @returns link 按钮
|
||||
*/
|
||||
renderLink: (url: string, text?: string) => {
|
||||
if (url) return h(Button, { type: 'link', href: url, target: '_blank' }, () => text || '');
|
||||
|
||||
return '';
|
||||
},
|
||||
/**
|
||||
* 渲染文本,将text与val 拼接到一起
|
||||
* @param text 文本1
|
||||
* @param val 文本2
|
||||
* @returns 文本1 + 文本2
|
||||
*/
|
||||
renderText: (text: string, val: string) => {
|
||||
if (text) return `${text} ${val}`;
|
||||
else return '';
|
||||
},
|
||||
/**
|
||||
* 渲染多行文本
|
||||
* @param text
|
||||
* @param val
|
||||
*/
|
||||
renderMultiLineText: (text: string, params?: any) => {
|
||||
if (text) {
|
||||
params = params || {}
|
||||
let classArr: string[] = params.class || [];
|
||||
if (params?.maxLine && params?.maxLine > 0) {
|
||||
classArr.push('line-clamp-' + params?.maxLine)
|
||||
}
|
||||
return h(
|
||||
Tooltip,
|
||||
{ trigger: 'hover' },
|
||||
{
|
||||
trigger: () => h('span', { class: classArr.join(' ') }, text),
|
||||
default: () => text
|
||||
}
|
||||
)
|
||||
}
|
||||
return '';
|
||||
},
|
||||
/**
|
||||
* 渲染标签
|
||||
* @param text 标签文本
|
||||
* @param color 标签颜色
|
||||
* @returns 标签
|
||||
*/
|
||||
renderTag: (text: string | number, color?: string) => {
|
||||
if (color) return h(Tag, { color }, () => text);
|
||||
else return h(Tag, {}, () => text);
|
||||
},
|
||||
/**
|
||||
* 渲染多标签
|
||||
* @param texts 文本
|
||||
* @returns 多标签
|
||||
*/
|
||||
renderTags: (texts: string[]) => {
|
||||
if (texts) {
|
||||
return h('div', null, [
|
||||
texts.map((text) => {
|
||||
return h(Tag, null, () => text);
|
||||
}),
|
||||
]);
|
||||
}
|
||||
return '';
|
||||
},
|
||||
/**
|
||||
* 渲染日期
|
||||
* @param text 日期
|
||||
* @param format 格式化
|
||||
* @returns 格式化后日期
|
||||
*/
|
||||
renderDate: (text: string, format?: string) => {
|
||||
if (!text) return '';
|
||||
|
||||
if (!format) return dayjs(text).format('YYYY-MM-DD HH:mm:ss');
|
||||
else return dayjs(text).format(format);
|
||||
},
|
||||
/**
|
||||
* 渲染字典
|
||||
* @param text 字典值
|
||||
* @param dictType 字典类型
|
||||
* @returns 字典标签
|
||||
*/
|
||||
renderDict: (text: string, dictType: string, params?: any) => {
|
||||
if (!dictType && !params.options) {
|
||||
console.warn('请传入字典类型')
|
||||
return '';
|
||||
}
|
||||
let dict: any[] = [];
|
||||
if (dictType) {
|
||||
dict = getDictOpts(dictType)
|
||||
}
|
||||
if (params && params.options) {
|
||||
dict = params.options;
|
||||
}
|
||||
return h(DictTag, { options: dict, value: text, ...params });
|
||||
}
|
||||
// /**
|
||||
// * 渲染图标icon
|
||||
// * @param text icon
|
||||
// * @returns icon
|
||||
// */
|
||||
// renderIcon: (text: string) => {
|
||||
// if (text) return h(Icon, { icon: text });
|
||||
// },
|
||||
/**
|
||||
* 使用JsonPreview组件 方便预览JSON
|
||||
* @param json json字符串/obj
|
||||
* @returns 能转为json返回JsonPreview 否则返回自身
|
||||
*/
|
||||
// renderJsonPreview: (json: any) => {
|
||||
// if (!json) return '';
|
||||
// if (typeof json === 'object') return h(JsonPreview, { data: json });
|
||||
|
||||
// if (typeof json === 'string') {
|
||||
// try {
|
||||
// const data = JSON.parse(json);
|
||||
// return h(JsonPreview, { data });
|
||||
// } catch (e) {
|
||||
// return json;
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
};
|
|
@ -1,76 +0,0 @@
|
|||
import { ref } from 'vue';
|
||||
|
||||
import { merge } from 'lodash-es';
|
||||
import { type VxeGridInstance, type VxeGridProps } from 'vxe-table';
|
||||
|
||||
export function useVxeTable(props: { ref: string }) {
|
||||
const xGridRef = ref<VxeGridInstance<any>>();
|
||||
|
||||
return {
|
||||
xGridRef,
|
||||
gridProps: (props: VxeGridProps) => {
|
||||
// 设置默认属性
|
||||
const defaultProps: VxeGridProps = {
|
||||
// 保持原始值的状态,被某些功能所依赖,比如编辑状态、还原数据等(开启后影响性能,具体取决于数据量)
|
||||
keepSource: false,
|
||||
height: 'auto',
|
||||
border: true,
|
||||
editConfig: {
|
||||
mode: 'row',
|
||||
},
|
||||
rowConfig: {
|
||||
isCurrent: true,
|
||||
},
|
||||
// 斑马条纹
|
||||
stripe: false,
|
||||
pagerConfig: {
|
||||
enabled: true,
|
||||
size: 'mini',
|
||||
pageSize: 50,
|
||||
autoHidden: false,
|
||||
},
|
||||
// 列设置
|
||||
columnConfig: {
|
||||
// 取消列选中效果
|
||||
isCurrent: false,
|
||||
isHover: false,
|
||||
// 取消列宽拖动功能
|
||||
resizable: false,
|
||||
},
|
||||
toolbarConfig: {
|
||||
enabled: true,
|
||||
export: false,
|
||||
// print: true,
|
||||
zoom: true,
|
||||
custom: true,
|
||||
refresh: true,
|
||||
slots: {
|
||||
buttons: 'toolbar_buttons',
|
||||
},
|
||||
},
|
||||
headerAlign: 'left',
|
||||
align: 'left',
|
||||
};
|
||||
|
||||
// 如果mergedProps.proxyConfig是空对象,则删除该字段,不然 vxetable 可能会误判断
|
||||
if (props.proxyConfig && JSON.stringify(props.proxyConfig) != '{}') {
|
||||
defaultProps.proxyConfig = {
|
||||
props: {
|
||||
list: 'rows',
|
||||
result: 'rows',
|
||||
total: 'total',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return merge({}, defaultProps, props);
|
||||
},
|
||||
|
||||
triggerProxy: (code: string) => {
|
||||
const $grid = xGridRef.value;
|
||||
if ($grid) {
|
||||
$grid.commitProxy(code);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,121 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { usePreferences } from '@vben/preferences';
|
||||
|
||||
import AuthenticationFormView from './form.vue';
|
||||
import SloganIcon from './icons/slogan.vue';
|
||||
|
||||
interface Props {
|
||||
appName?: string;
|
||||
logo?: string;
|
||||
pageTitle?: string;
|
||||
pageDescription?: string;
|
||||
sloganImage?: string;
|
||||
copyright?: boolean;
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
appName: '',
|
||||
copyright: true,
|
||||
logo: '',
|
||||
pageDescription: '',
|
||||
pageTitle: '',
|
||||
sloganImage: '',
|
||||
});
|
||||
|
||||
const { authPanelCenter, authPanelLeft, authPanelRight, isDark } =
|
||||
usePreferences();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:class="[isDark]"
|
||||
class="flex min-h-full flex-1 select-none overflow-x-hidden"
|
||||
>
|
||||
<!-- <template v-if="toolbar">
|
||||
<slot name="toolbar">
|
||||
<Toolbar :toolbar-list="toolbarList" />
|
||||
</slot>
|
||||
</template> -->
|
||||
<!-- 左侧认证面板 -->
|
||||
<AuthenticationFormView
|
||||
v-if="authPanelLeft"
|
||||
class="min-h-full w-2/5 flex-1"
|
||||
transition-name="slide-left"
|
||||
/>
|
||||
|
||||
<!-- 头部 Logo 和应用名称 -->
|
||||
<div class="absolute left-0 top-0 z-10 flex flex-1">
|
||||
<div
|
||||
class="text-foreground lg:text-foreground ml-4 mt-4 flex flex-1 items-center sm:left-6 sm:top-6"
|
||||
>
|
||||
<img :alt="appName" :src="logo" class="mr-2" width="42" />
|
||||
<p class="text-xl font-medium">
|
||||
{{ appName }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 系统介绍 -->
|
||||
<div v-if="!authPanelCenter" class="relative hidden w-0 flex-1 lg:block">
|
||||
<div
|
||||
class="bg-background-deep absolute inset-0 h-full w-full dark:bg-[#070709]"
|
||||
>
|
||||
<div class="login-background absolute left-0 top-0 size-full"></div>
|
||||
<div class="flex-col-center -enter-x mr-20 h-full">
|
||||
<template v-if="sloganImage">
|
||||
<img
|
||||
:alt="appName"
|
||||
:src="sloganImage"
|
||||
class="animate-float h-64 w-2/5"
|
||||
/>
|
||||
</template>
|
||||
<SloganIcon v-else :alt="appName" class="animate-float h-70 w-1/2" />
|
||||
<div class="text-1xl text-foreground mt-6 font-sans lg:text-2xl">
|
||||
{{ pageTitle }}
|
||||
</div>
|
||||
<div class="dark:text-muted-foreground mt-2">
|
||||
{{ pageDescription }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 中心认证面板 -->
|
||||
<!-- <div v-if="authPanelCenter" class="flex-center relative w-full">
|
||||
<div class="login-background absolute left-0 top-0 size-full"></div>
|
||||
<AuthenticationFormView
|
||||
class="md:bg-background shadow-primary/5 shadow-float w-full rounded-3xl pb-20 md:w-2/3 lg:w-1/2 xl:w-[36%]"
|
||||
/>
|
||||
</div> -->
|
||||
|
||||
<!-- 右侧认证面板 -->
|
||||
<AuthenticationFormView
|
||||
v-if="authPanelRight"
|
||||
class="min-h-full w-[34%] flex-1"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.login-background {
|
||||
background: linear-gradient(
|
||||
154deg,
|
||||
#07070915 30%,
|
||||
hsl(var(--primary) / 30%) 48%,
|
||||
#07070915 64%
|
||||
);
|
||||
filter: blur(100px);
|
||||
}
|
||||
|
||||
.dark {
|
||||
.login-background {
|
||||
background: linear-gradient(
|
||||
154deg,
|
||||
#07070915 30%,
|
||||
hsl(var(--primary) / 20%) 48%,
|
||||
#07070915 64%
|
||||
);
|
||||
filter: blur(100px);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,33 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
defineOptions({
|
||||
name: 'AuthenticationFormView',
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="flex-col-center dark:bg-background-deep bg-background relative px-6 py-10 lg:flex-initial lg:px-8"
|
||||
>
|
||||
<slot></slot>
|
||||
<!-- Router View with Transition and KeepAlive -->
|
||||
<RouterView v-slot="{ Component, route }">
|
||||
<Transition appear mode="out-in" name="slide-right">
|
||||
<KeepAlive :include="['Login']">
|
||||
<component
|
||||
:is="Component"
|
||||
:key="route.fullPath"
|
||||
class="enter-x mt-6 w-full sm:mx-auto md:max-w-md"
|
||||
/>
|
||||
</KeepAlive>
|
||||
</Transition>
|
||||
</RouterView>
|
||||
|
||||
<!-- Footer Copyright -->
|
||||
|
||||
<div
|
||||
class="text-muted-foreground absolute bottom-3 flex text-center text-xs"
|
||||
>
|
||||
<slot name="copyright"> </slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
File diff suppressed because one or more lines are too long
|
@ -1 +0,0 @@
|
|||
export { default as AuthPageLayout } from './authentication.vue';
|
|
@ -1,201 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import type { NotificationItem } from './notification';
|
||||
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
|
||||
import { storeToRefs, useAccessStore, useUserStore } from '@vben/stores';
|
||||
// import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
|
||||
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { AuthenticationLoginExpiredModal } from '@vben/common-ui';
|
||||
import { PhUserCircle } from '@vben/icons';
|
||||
import { BasicLayout, LockScreen, UserDropdown } from '@vben/layouts';
|
||||
import { preferences } from '@vben/preferences';
|
||||
|
||||
import Apis from '#/api';
|
||||
import { useAuthStore } from '#/store';
|
||||
import { DICT_TYPE, getDictObj } from '#/utils/dict';
|
||||
|
||||
import { Notification } from './notification';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const notifications = ref<NotificationItem[]>([
|
||||
// {
|
||||
// avatar: "https://avatar.vercel.sh/vercel.svg?text=VB",
|
||||
// date: "3小时前",
|
||||
// isRead: true,
|
||||
// message: "描述信息描述信息描述信息",
|
||||
// title: "收到了 14 份新周报",
|
||||
// },
|
||||
// {
|
||||
// avatar: "https://avatar.vercel.sh/1",
|
||||
// date: "刚刚",
|
||||
// isRead: false,
|
||||
// message: "描述信息描述信息描述信息",
|
||||
// title: "朱偏右 回复了你",
|
||||
// },
|
||||
// {
|
||||
// avatar: "https://avatar.vercel.sh/1",
|
||||
// date: "2024-01-01",
|
||||
// isRead: false,
|
||||
// message: "描述信息描述信息描述信息",
|
||||
// title: "曲丽丽 评论了你",
|
||||
// },
|
||||
// {
|
||||
// avatar: "https://avatar.vercel.sh/satori",
|
||||
// date: "1天前",
|
||||
// isRead: false,
|
||||
// message: "描述信息描述信息描述信息",
|
||||
// title: "代办提醒",
|
||||
// },
|
||||
]);
|
||||
|
||||
const userStore = useUserStore();
|
||||
const authStore = useAuthStore();
|
||||
const accessStore = useAccessStore();
|
||||
const showDot = computed(() =>
|
||||
notifications.value.some((item) => !item.isRead),
|
||||
);
|
||||
|
||||
const menus = computed(() => [
|
||||
{
|
||||
handler: () => {
|
||||
router.push('/user/center');
|
||||
},
|
||||
icon: PhUserCircle,
|
||||
text: '个人中心',
|
||||
},
|
||||
// {
|
||||
// handler: () => {
|
||||
// openWindow(VBEN_GITHUB_URL, {
|
||||
// target: '_blank',
|
||||
// });
|
||||
// },
|
||||
// icon: MdiGithub,
|
||||
// text: 'GitHub',
|
||||
// },
|
||||
// {
|
||||
// handler: () => {
|
||||
// openWindow(`${VBEN_GITHUB_URL}/issues`, {
|
||||
// target: '_blank',
|
||||
// });
|
||||
// },
|
||||
// icon: CircleHelp,
|
||||
// text: $t('widgets.qa'),
|
||||
// },
|
||||
]);
|
||||
|
||||
const { loginLoading } = storeToRefs(authStore);
|
||||
|
||||
const avatar = computed(() => {
|
||||
return userStore.userInfo?.avatar ?? preferences.app.defaultAvatar;
|
||||
});
|
||||
|
||||
async function handleLogout() {
|
||||
await authStore.logout(false);
|
||||
}
|
||||
|
||||
function handleNoticeClear() {
|
||||
notifications.value = [];
|
||||
}
|
||||
|
||||
function handleMakeAll() {
|
||||
notifications.value.forEach((item) => (item.isRead = true));
|
||||
}
|
||||
|
||||
function handleViewAll() {
|
||||
router.push('/user/todo');
|
||||
}
|
||||
|
||||
const isDev = import.meta.env.MODE === 'development';
|
||||
const value = ref(localStorage.getItem('@@@proxy_type') || ''); // /zp
|
||||
function handleMenuClick(e) {
|
||||
if (e.key === 'pro') {
|
||||
localStorage.setItem('@@@proxy_type', '');
|
||||
} else {
|
||||
localStorage.setItem('@@@proxy_type', `/${e.key}`);
|
||||
}
|
||||
location.reload();
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
// const data = await Apis.home.get_todo({
|
||||
// params: { pageNum: 1, pageSize: 20 },
|
||||
// });
|
||||
|
||||
// notifications.value = data.rows.map((item) => {
|
||||
// let module =
|
||||
// getDictObj(DICT_TYPE.contract_todo_type, item.module)?.label || '';
|
||||
// module = module.slice(-4);
|
||||
// let moduleTextArr = [...module];
|
||||
// moduleTextArr =
|
||||
// moduleTextArr.length <= 3 ? moduleTextArr : moduleTextArr.slice(-4);
|
||||
// return {
|
||||
// moduleTextArr,
|
||||
// avatar: '',
|
||||
// date: item.createTime,
|
||||
// isRead: true,
|
||||
// message: item.contractName,
|
||||
// title: item.taskName,
|
||||
// };
|
||||
// });
|
||||
// console.log(notifications);
|
||||
// resetAllStores();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BasicLayout @clear-preferences-and-logout="handleLogout">
|
||||
<template #user-dropdown>
|
||||
<UserDropdown
|
||||
:avatar
|
||||
:description="userStore.userInfo?.belongOrgName"
|
||||
:menus
|
||||
:tag-text="userStore.userInfo?.gwmc"
|
||||
:text="userStore.userInfo?.displayName"
|
||||
@logout="handleLogout"
|
||||
/>
|
||||
</template>
|
||||
<template #notification>
|
||||
<a-dropdown v-if="isDev">
|
||||
<template #overlay>
|
||||
<a-menu selectable @click="handleMenuClick">
|
||||
<a-menu-item key="pro"> 正式 </a-menu-item>
|
||||
<a-menu-item key="czg"> czg </a-menu-item>
|
||||
<a-menu-item key="zp"> zp </a-menu-item>
|
||||
<a-menu-item key="zzz"> zzz </a-menu-item>
|
||||
<a-menu-item key="xmh"> xmh </a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button> {{ value ? `代理${value}` : '代理切换' }} </a-button>
|
||||
</a-dropdown>
|
||||
|
||||
<!-- <Notification
|
||||
:dot="showDot"
|
||||
:notifications="notifications"
|
||||
@clear="handleNoticeClear"
|
||||
@make-all="handleMakeAll"
|
||||
@view-all="handleViewAll"
|
||||
/> -->
|
||||
</template>
|
||||
<template #extra>
|
||||
<AuthenticationLoginExpiredModal
|
||||
v-model:open="accessStore.loginExpired"
|
||||
:avatar
|
||||
:loading="loginLoading"
|
||||
password-placeholder=""
|
||||
username-placeholder=""
|
||||
@submit="authStore.authLogin"
|
||||
/>
|
||||
</template>
|
||||
<template #lock-screen>
|
||||
<LockScreen
|
||||
:avatar
|
||||
:text="userStore.userInfo?.displayName"
|
||||
@to-login="handleLogout"
|
||||
/>
|
||||
</template>
|
||||
</BasicLayout>
|
||||
</template>
|
|
@ -1,8 +0,0 @@
|
|||
const BasicLayout = () => import('./basic.vue');
|
||||
|
||||
const IFrameView = () => import('@vben/layouts').then((m) => m.IFrameView);
|
||||
|
||||
const AuthPageLayout = () =>
|
||||
import('#/layouts/authentication').then((m) => m.AuthPageLayout);
|
||||
|
||||
export { AuthPageLayout, BasicLayout, IFrameView };
|
|
@ -1,3 +0,0 @@
|
|||
export { default as Notification } from './notification.vue';
|
||||
|
||||
export type * from './types';
|
|
@ -1,187 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import type { NotificationItem } from './types';
|
||||
|
||||
import { Bell, MailCheck } from '@vben/icons';
|
||||
import { $t } from '@vben/locales';
|
||||
import {
|
||||
VbenButton,
|
||||
VbenIconButton,
|
||||
VbenPopover,
|
||||
VbenScrollbar,
|
||||
} from '@vben-core/shadcn-ui';
|
||||
|
||||
import { useToggle } from '@vueuse/core';
|
||||
|
||||
interface Props {
|
||||
/**
|
||||
* 显示圆点
|
||||
*/
|
||||
dot?: boolean;
|
||||
/**
|
||||
* 消息列表
|
||||
*/
|
||||
notifications?: NotificationItem[];
|
||||
}
|
||||
|
||||
defineOptions({ name: 'NotificationPopup' });
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
dot: false,
|
||||
notifications: () => [],
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
clear: [];
|
||||
makeAll: [];
|
||||
read: [NotificationItem];
|
||||
viewAll: [];
|
||||
}>();
|
||||
|
||||
const [open, toggle] = useToggle();
|
||||
|
||||
function close() {
|
||||
open.value = false;
|
||||
}
|
||||
|
||||
function handleViewAll() {
|
||||
emit('viewAll');
|
||||
close();
|
||||
}
|
||||
|
||||
function handleMakeAll() {
|
||||
emit('makeAll');
|
||||
}
|
||||
|
||||
function handleClear() {
|
||||
emit('clear');
|
||||
}
|
||||
|
||||
function handleClick(item: NotificationItem) {
|
||||
emit('read', item);
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<VbenPopover
|
||||
v-model:open="open"
|
||||
content-class="relative right-2 w-[360px] p-0"
|
||||
>
|
||||
<template #trigger>
|
||||
<div class="flex-center mr-2 h-full" @click.stop="toggle()">
|
||||
<VbenIconButton class="bell-button text-foreground relative">
|
||||
<span
|
||||
v-if="dot"
|
||||
class="bg-primary absolute right-0.5 top-0.5 h-2 w-2 rounded"
|
||||
></span>
|
||||
<Bell class="size-4" />
|
||||
</VbenIconButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="relative">
|
||||
<div class="flex items-center justify-between p-4 py-3">
|
||||
<div class="text-foreground">{{ $t('widgets.notifications') }}</div>
|
||||
<VbenIconButton
|
||||
:tooltip="$t('widgets.markAllAsRead')"
|
||||
@click="handleMakeAll"
|
||||
>
|
||||
<MailCheck class="size-4" />
|
||||
</VbenIconButton>
|
||||
</div>
|
||||
<VbenScrollbar v-if="notifications.length > 0">
|
||||
<ul class="!flex max-h-[360px] w-full flex-col">
|
||||
<template v-for="item in notifications" :key="item.title">
|
||||
<li
|
||||
class="hover:bg-accent border-border relative flex w-full cursor-pointer items-start gap-5 border-t px-3 py-3"
|
||||
@click="handleClick(item)"
|
||||
>
|
||||
<span
|
||||
v-if="!item.isRead"
|
||||
class="bg-primary absolute right-2 top-2 h-2 w-2 rounded"
|
||||
></span>
|
||||
|
||||
<span
|
||||
class="relative flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-blue-500 text-sm font-bold text-white"
|
||||
>
|
||||
<div
|
||||
class="flex flex-wrap justify-center text-center leading-none"
|
||||
>
|
||||
<span
|
||||
v-for="(char, index) in item.moduleTextArr"
|
||||
:key="index"
|
||||
class="w-1/2 p-0.5"
|
||||
>
|
||||
{{ char }}
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
<div class="flex flex-col gap-1 leading-none">
|
||||
<p class="font-semibold">{{ item.title }}</p>
|
||||
<p class="text-muted-foreground my-1 line-clamp-2 text-xs">
|
||||
{{ item.message }}
|
||||
</p>
|
||||
<p class="text-muted-foreground line-clamp-2 text-xs">
|
||||
{{ item.date }}
|
||||
</p>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</VbenScrollbar>
|
||||
|
||||
<template v-else>
|
||||
<div class="flex-center text-muted-foreground min-h-[150px] w-full">
|
||||
{{ $t('common.noData') }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div
|
||||
class="border-border flex items-center justify-between border-t px-4 py-3"
|
||||
>
|
||||
<!-- <VbenButton size="sm" variant="ghost" @click="handleClear">
|
||||
{{ $t('widgets.clearNotifications') }}
|
||||
</VbenButton> -->
|
||||
<div></div>
|
||||
<VbenButton size="sm" @click="handleViewAll">
|
||||
{{ $t('widgets.viewAll') }}
|
||||
</VbenButton>
|
||||
</div>
|
||||
</div>
|
||||
</VbenPopover>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
:deep(.bell-button) {
|
||||
&:hover {
|
||||
svg {
|
||||
animation: bell-ring 1s both;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes bell-ring {
|
||||
0%,
|
||||
100% {
|
||||
transform-origin: top;
|
||||
}
|
||||
|
||||
15% {
|
||||
transform: rotateZ(10deg);
|
||||
}
|
||||
|
||||
30% {
|
||||
transform: rotateZ(-10deg);
|
||||
}
|
||||
|
||||
45% {
|
||||
transform: rotateZ(5deg);
|
||||
}
|
||||
|
||||
60% {
|
||||
transform: rotateZ(-5deg);
|
||||
}
|
||||
|
||||
75% {
|
||||
transform: rotateZ(2deg);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,9 +0,0 @@
|
|||
interface NotificationItem {
|
||||
avatar: string;
|
||||
date: string;
|
||||
isRead?: boolean;
|
||||
message: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export type { NotificationItem };
|
|
@ -1,3 +0,0 @@
|
|||
# locale
|
||||
|
||||
每个app使用的国际化可能不同,这里用于扩展国际化的功能,例如扩展 dayjs、antd组件库的多语言切换,以及app本身的国际化文件。
|
|
@ -1,94 +0,0 @@
|
|||
import type { LocaleSetupOptions, SupportedLanguagesType } from '@vben/locales';
|
||||
import type { Locale } from 'ant-design-vue/es/locale';
|
||||
|
||||
import type { App } from 'vue';
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { $t, setupI18n as coreSetup, loadLocalesMap } from '@vben/locales';
|
||||
import { preferences } from '@vben/preferences';
|
||||
|
||||
import antdEnLocale from 'ant-design-vue/es/locale/en_US';
|
||||
import antdDefaultLocale from 'ant-design-vue/es/locale/zh_CN';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
const antdLocale = ref<Locale>(antdDefaultLocale);
|
||||
|
||||
const modules = import.meta.glob('./langs/*.json');
|
||||
|
||||
const localesMap = loadLocalesMap(modules);
|
||||
|
||||
/**
|
||||
* 加载应用特有的语言包
|
||||
* 这里也可以改造为从服务端获取翻译数据
|
||||
* @param lang
|
||||
*/
|
||||
async function loadMessages(lang: SupportedLanguagesType) {
|
||||
const [appLocaleMessages] = await Promise.all([
|
||||
localesMap[lang]?.(),
|
||||
loadThirdPartyMessage(lang),
|
||||
]);
|
||||
return appLocaleMessages?.default;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载第三方组件库的语言包
|
||||
* @param lang
|
||||
*/
|
||||
async function loadThirdPartyMessage(lang: SupportedLanguagesType) {
|
||||
await Promise.all([loadAntdLocale(lang), loadDayjsLocale(lang)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载dayjs的语言包
|
||||
* @param lang
|
||||
*/
|
||||
async function loadDayjsLocale(lang: SupportedLanguagesType) {
|
||||
let locale;
|
||||
switch (lang) {
|
||||
case 'zh-CN': {
|
||||
locale = await import('dayjs/locale/zh-cn');
|
||||
break;
|
||||
}
|
||||
case 'en-US': {
|
||||
locale = await import('dayjs/locale/en');
|
||||
break;
|
||||
}
|
||||
// 默认使用英语
|
||||
default: {
|
||||
locale = await import('dayjs/locale/en');
|
||||
}
|
||||
}
|
||||
if (locale) {
|
||||
dayjs.locale(locale);
|
||||
} else {
|
||||
console.error(`Failed to load dayjs locale for ${lang}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载antd的语言包
|
||||
* @param lang
|
||||
*/
|
||||
async function loadAntdLocale(lang: SupportedLanguagesType) {
|
||||
switch (lang) {
|
||||
case 'zh-CN': {
|
||||
antdLocale.value = antdDefaultLocale;
|
||||
break;
|
||||
}
|
||||
case 'en-US': {
|
||||
antdLocale.value = antdEnLocale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function setupI18n(app: App, options: LocaleSetupOptions = {}) {
|
||||
await coreSetup(app, {
|
||||
defaultLocale: preferences.app.locale,
|
||||
loadMessages,
|
||||
missingWarn: !import.meta.env.PROD,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
export { $t, antdLocale, setupI18n };
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"page": {
|
||||
"demos": {
|
||||
"title": "Demos",
|
||||
"antd": "Ant Design Vue"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"page": {
|
||||
"demos": {
|
||||
"title": "演示",
|
||||
"antd": "Ant Design Vue"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
import { initPreferences } from '@vben/preferences';
|
||||
import { unmountGlobalLoading } from '@vben/utils';
|
||||
|
||||
import { overridesPreferences } from './preferences';
|
||||
|
||||
/**
|
||||
* 应用初始化完成之后再进行页面加载渲染
|
||||
*/
|
||||
async function initApplication() {
|
||||
// name用于指定项目唯一标识
|
||||
// 用于区分不同项目的偏好设置以及存储数据的key前缀以及其他一些需要隔离的数据
|
||||
const env = import.meta.env.PROD ? 'prod' : 'dev';
|
||||
const appVersion = import.meta.env.VITE_APP_VERSION;
|
||||
const namespace = `${import.meta.env.VITE_APP_NAMESPACE}-${appVersion}-${env}`;
|
||||
|
||||
// app偏好设置初始化
|
||||
await initPreferences({
|
||||
namespace,
|
||||
overrides: overridesPreferences,
|
||||
});
|
||||
|
||||
// 启动应用并挂载
|
||||
// vue应用主要逻辑及视图
|
||||
const { bootstrap } = await import('./bootstrap');
|
||||
await bootstrap(namespace);
|
||||
|
||||
// 移除并销毁loading
|
||||
unmountGlobalLoading();
|
||||
}
|
||||
|
||||
initApplication();
|
|
@ -1,14 +0,0 @@
|
|||
import type { App } from 'vue';
|
||||
|
||||
import FastCrud from '@fast-crud/fast-crud';
|
||||
import ui from '@fast-crud/ui-antdv4';
|
||||
import Antdv from 'ant-design-vue';
|
||||
import '@fast-crud/fast-crud/dist/style.css';
|
||||
import '@fast-crud/ui-antdv4/dist/style.css';
|
||||
|
||||
export function registerFastCrud(app: App) {
|
||||
app.use(Antdv);
|
||||
app.use(ui);
|
||||
app.use(FastCrud, {
|
||||
});
|
||||
}
|
|
@ -1,202 +0,0 @@
|
|||
import type { App } from 'vue';
|
||||
|
||||
import VXETable from 'vxe-table'
|
||||
|
||||
import {
|
||||
VxeTable,
|
||||
VxeColumn,
|
||||
VxeColgroup,
|
||||
VxeGrid,
|
||||
VxeToolbar
|
||||
} from 'vxe-table'
|
||||
|
||||
import VxeUI from 'vxe-pc-ui'
|
||||
|
||||
import {
|
||||
|
||||
VxeAlert,
|
||||
VxeAnchor,
|
||||
VxeAnchorLink,
|
||||
VxeBreadcrumb,
|
||||
VxeBreadcrumbItem,
|
||||
VxeButton,
|
||||
VxeButtonGroup,
|
||||
VxeCalendar,
|
||||
VxeCard,
|
||||
VxeCarousel,
|
||||
VxeCheckbox,
|
||||
VxeCheckboxGroup,
|
||||
VxeCol,
|
||||
VxeCollapse,
|
||||
VxeCollapsePane,
|
||||
VxeDatePicker,
|
||||
VxeDrawer,
|
||||
VxeForm,
|
||||
VxeFormDesign,
|
||||
VxeFormGather,
|
||||
VxeFormItem,
|
||||
VxeFormView,
|
||||
VxeIcon,
|
||||
VxeIconPicker,
|
||||
VxeImage,
|
||||
VxeImageGroup,
|
||||
VxeImagePreview,
|
||||
VxeInput,
|
||||
VxeLayoutAside,
|
||||
VxeLayoutBody,
|
||||
VxeLayoutContainer,
|
||||
VxeLayoutFooter,
|
||||
VxeLayoutHeader,
|
||||
VxeLink,
|
||||
VxeListDesign,
|
||||
VxeListView,
|
||||
VxeList,
|
||||
VxeLoading,
|
||||
VxeMenu,
|
||||
VxeModal,
|
||||
VxeNumberInput,
|
||||
VxeOptgroup,
|
||||
VxeOption,
|
||||
VxePager,
|
||||
VxePasswordInput,
|
||||
VxePrintPageBreak,
|
||||
VxePrint,
|
||||
VxePulldown,
|
||||
VxeRadio,
|
||||
VxeRadioButton,
|
||||
VxeRadioGroup,
|
||||
VxeRow,
|
||||
VxeSelect,
|
||||
VxeSwitch,
|
||||
VxeTabPane,
|
||||
VxeTabs,
|
||||
VxeTag,
|
||||
VxeText,
|
||||
VxeTextarea,
|
||||
VxeTip,
|
||||
VxeTooltip,
|
||||
VxeTree,
|
||||
VxeTreeSelect,
|
||||
VxeUpload
|
||||
} from 'vxe-pc-ui'
|
||||
|
||||
import VXETablePluginExportXLSX from 'vxe-table-plugin-export-xlsx'
|
||||
import ExcelJS from 'exceljs'
|
||||
|
||||
import VXETablePluginAntd from 'vxe-table-plugin-antd'
|
||||
|
||||
// 导入主题变量,也可以重写主题变量
|
||||
import 'vxe-pc-ui/lib/style.css'
|
||||
import 'vxe-table/lib/style.css'
|
||||
import 'vxe-table/styles/cssvar.scss'
|
||||
import 'vxe-pc-ui/styles/cssvar.scss'
|
||||
|
||||
// VxeUI.setTheme('dark')
|
||||
|
||||
VxeUI.component(VxeAlert)
|
||||
VxeUI.component(VxeAnchor)
|
||||
VxeUI.component(VxeAnchorLink)
|
||||
VxeUI.component(VxeBreadcrumb)
|
||||
VxeUI.component(VxeBreadcrumbItem)
|
||||
VxeUI.component(VxeButton)
|
||||
VxeUI.component(VxeButtonGroup)
|
||||
VxeUI.component(VxeCalendar)
|
||||
VxeUI.component(VxeCard)
|
||||
VxeUI.component(VxeCarousel)
|
||||
VxeUI.component(VxeCheckbox)
|
||||
VxeUI.component(VxeCheckboxGroup)
|
||||
VxeUI.component(VxeCol)
|
||||
VxeUI.component(VxeCollapse)
|
||||
VxeUI.component(VxeCollapsePane)
|
||||
VxeUI.component(VxeDatePicker)
|
||||
VxeUI.component(VxeDrawer)
|
||||
VxeUI.component(VxeForm)
|
||||
VxeUI.component(VxeFormDesign)
|
||||
VxeUI.component(VxeFormGather)
|
||||
VxeUI.component(VxeFormItem)
|
||||
VxeUI.component(VxeFormView)
|
||||
VxeUI.component(VxeIcon)
|
||||
VxeUI.component(VxeIconPicker)
|
||||
VxeUI.component(VxeImage)
|
||||
VxeUI.component(VxeImageGroup)
|
||||
VxeUI.component(VxeImagePreview)
|
||||
VxeUI.component(VxeInput)
|
||||
VxeUI.component(VxeLayoutAside)
|
||||
VxeUI.component(VxeLayoutBody)
|
||||
VxeUI.component(VxeLayoutContainer)
|
||||
VxeUI.component(VxeLayoutFooter)
|
||||
VxeUI.component(VxeLayoutHeader)
|
||||
VxeUI.component(VxeLink)
|
||||
VxeUI.component(VxeListDesign)
|
||||
VxeUI.component(VxeListView)
|
||||
VxeUI.component(VxeList)
|
||||
VxeUI.component(VxeLoading)
|
||||
VxeUI.component(VxeMenu)
|
||||
VxeUI.component(VxeModal)
|
||||
VxeUI.component(VxeNumberInput)
|
||||
VxeUI.component(VxeOptgroup)
|
||||
VxeUI.component(VxeOption)
|
||||
VxeUI.component(VxePager)
|
||||
VxeUI.component(VxePasswordInput)
|
||||
VxeUI.component(VxePrintPageBreak)
|
||||
VxeUI.component(VxePrint)
|
||||
VxeUI.component(VxePulldown)
|
||||
VxeUI.component(VxeRadio)
|
||||
VxeUI.component(VxeRadioButton)
|
||||
VxeUI.component(VxeRadioGroup)
|
||||
VxeUI.component(VxeRow)
|
||||
VxeUI.component(VxeSelect)
|
||||
VxeUI.component(VxeSwitch)
|
||||
VxeUI.component(VxeTabPane)
|
||||
VxeUI.component(VxeTabs)
|
||||
VxeUI.component(VxeTag)
|
||||
VxeUI.component(VxeText)
|
||||
VxeUI.component(VxeTextarea)
|
||||
VxeUI.component(VxeTip)
|
||||
VxeUI.component(VxeTooltip)
|
||||
VxeUI.component(VxeTree)
|
||||
VxeUI.component(VxeTreeSelect)
|
||||
VxeUI.component(VxeUpload)
|
||||
|
||||
VxeUI.component(VxeTable)
|
||||
VxeUI.component(VxeColumn)
|
||||
VxeUI.component(VxeColgroup)
|
||||
VxeUI.component(VxeGrid)
|
||||
VxeUI.component(VxeToolbar)
|
||||
|
||||
VXETable.use(VXETablePluginAntd)
|
||||
|
||||
VXETable.use(VXETablePluginExportXLSX, {
|
||||
ExcelJS
|
||||
})
|
||||
|
||||
VXETable.setConfig({
|
||||
// zIndex: 9999,
|
||||
grid: {
|
||||
size: 'mini',
|
||||
proxyConfig: {
|
||||
props: {
|
||||
result: 'data.rows',
|
||||
total: 'data.total',
|
||||
},
|
||||
},
|
||||
toolbarConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
|
||||
pager: {
|
||||
background: true,
|
||||
pageSize: 50,
|
||||
pageSizes: [50, 100, 300, 500, 1000],
|
||||
layouts: ['PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'Sizes', 'FullJump', 'Total'],
|
||||
},
|
||||
})
|
||||
export function registerVxeTable(app: App) {
|
||||
app.use(VxeUI)
|
||||
app.use(VxeTable)
|
||||
app.use(VxeColumn)
|
||||
app.use(VxeColgroup)
|
||||
app.use(VxeGrid)
|
||||
app.use(VxeToolbar)
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
import { defineOverridesPreferences } from '@vben/preferences';
|
||||
|
||||
/**
|
||||
* @description 项目配置文件
|
||||
* 只需要覆盖项目中的一部分配置,不需要的配置不用覆盖,会自动使用默认配置
|
||||
*/
|
||||
export const overridesPreferences = defineOverridesPreferences({
|
||||
// overrides
|
||||
app: {
|
||||
name: import.meta.env.VITE_APP_TITLE,
|
||||
authPageLayout: 'panel-right',
|
||||
},
|
||||
});
|
|
@ -1,42 +0,0 @@
|
|||
import type {
|
||||
ComponentRecordType,
|
||||
GenerateMenuAndRoutesOptions,
|
||||
} from '@vben/types';
|
||||
|
||||
import { generateAccessible } from '@vben/access';
|
||||
import { preferences } from '@vben/preferences';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import { getAllMenusApi } from '#/api/system/menu';
|
||||
import { BasicLayout, IFrameView } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
const forbiddenComponent = () => import('#/views/_core/fallback/forbidden.vue');
|
||||
|
||||
async function generateAccess(options: GenerateMenuAndRoutesOptions) {
|
||||
const pageMap: ComponentRecordType = import.meta.glob('../views/**/*.vue');
|
||||
|
||||
const layoutMap: ComponentRecordType = {
|
||||
BasicLayout,
|
||||
IFrameView,
|
||||
};
|
||||
|
||||
return await generateAccessible(preferences.app.accessMode, {
|
||||
...options,
|
||||
fetchMenuListAsync: async () => {
|
||||
message.loading({
|
||||
content: `${$t('common.loadingMenu')}...`,
|
||||
duration: 1.5,
|
||||
});
|
||||
return await getAllMenusApi();
|
||||
},
|
||||
// 可以指定没有权限跳转403页面
|
||||
forbiddenComponent,
|
||||
// 如果 route.meta.menuVisibleWithForbidden = true
|
||||
layoutMap,
|
||||
pageMap,
|
||||
});
|
||||
}
|
||||
|
||||
export { generateAccess };
|
|
@ -1,262 +0,0 @@
|
|||
import type { Router } from 'vue-router';
|
||||
|
||||
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
|
||||
import { preferences } from '@vben/preferences';
|
||||
import { useAccessStore, useUserStore } from '@vben/stores';
|
||||
import { startProgress, stopProgress } from '@vben/utils';
|
||||
|
||||
import { useTitle } from '@vueuse/core';
|
||||
|
||||
import Apis from '#/api';
|
||||
import { $t } from '#/locales';
|
||||
import { coreRouteNames, dynamicRoutes } from '#/router/routes';
|
||||
import { useAuthStore } from '#/store';
|
||||
|
||||
import { generateAccess } from './access';
|
||||
|
||||
/**
|
||||
* 通用守卫配置
|
||||
* @param router
|
||||
*/
|
||||
function setupCommonGuard(router: Router) {
|
||||
// 记录已经加载的页面
|
||||
const loadedPaths = new Set<string>();
|
||||
|
||||
router.beforeEach(async (to) => {
|
||||
to.meta.loaded = loadedPaths.has(to.path);
|
||||
|
||||
// 页面加载进度条
|
||||
if (!to.meta.loaded && preferences.transition.progress) {
|
||||
startProgress();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
router.afterEach((to) => {
|
||||
// 记录页面是否加载,如果已经加载,后续的页面切换动画等效果不在重复执行
|
||||
|
||||
if (preferences.tabbar.enable) {
|
||||
loadedPaths.add(to.path);
|
||||
}
|
||||
|
||||
// 关闭页面加载进度条
|
||||
if (preferences.transition.progress) {
|
||||
stopProgress();
|
||||
}
|
||||
|
||||
// 动态修改标题
|
||||
if (preferences.app.dynamicTitle) {
|
||||
const { title } = to.meta;
|
||||
// useTitle(`${$t(title)} - ${preferences.app.name}`);
|
||||
useTitle(`${$t(title)} - ${preferences.app.name}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 匹配路径
|
||||
* permission.path = "/xx/edit" 但route.path = "/xx/edit/:id?" 这种情况,其中id可以为任意值,如meetingId roleId等,
|
||||
*/
|
||||
function matchPaths(routePath, permissionPath) {
|
||||
const routeParts = routePath.path.split('/');
|
||||
const permissionParts = permissionPath.path.split('/');
|
||||
|
||||
if (routePath.name === permissionPath.id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (permissionParts.length > routeParts.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return routeParts.every((part, index) => {
|
||||
return part === permissionParts[index] || part.startsWith(':');
|
||||
});
|
||||
}
|
||||
|
||||
// 过滤路由,只保留第三个数据源配置的路由
|
||||
function filterRoutesByPermissions(routes, permissions, staticRouteKeys) {
|
||||
const filteredRoutes = [];
|
||||
for (const route of routes) {
|
||||
// console.log('[ route ] >', route)
|
||||
// console.log('[ permission.path ] >', permissions)
|
||||
|
||||
const permission = permissions.find((permission) =>
|
||||
matchPaths(route, permission),
|
||||
);
|
||||
|
||||
const isStaticRoute = staticRouteKeys.includes(route.name);
|
||||
|
||||
if (permission || isStaticRoute) {
|
||||
const newRoute = { ...route };
|
||||
if (permission) {
|
||||
newRoute.meta = {
|
||||
...newRoute.meta,
|
||||
title: permission.name,
|
||||
};
|
||||
if (permission.order) {
|
||||
newRoute.meta.order = permission.order;
|
||||
}
|
||||
}
|
||||
if (route.children) {
|
||||
newRoute.children = filterRoutesByPermissions(
|
||||
route.children,
|
||||
permissions,
|
||||
staticRouteKeys,
|
||||
);
|
||||
}
|
||||
filteredRoutes.push(newRoute);
|
||||
// console.log(JSON.parse(JSON.stringify(filteredRoutes)));
|
||||
}
|
||||
}
|
||||
|
||||
return filteredRoutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限访问守卫配置
|
||||
* @param router
|
||||
*/
|
||||
function setupAccessGuard(router: Router) {
|
||||
router.beforeEach(async (to, from) => {
|
||||
const accessStore = useAccessStore();
|
||||
const userStore = useUserStore();
|
||||
const authStore = useAuthStore();
|
||||
|
||||
// 基本路由,这些路由不需要进入权限拦截
|
||||
if (coreRouteNames.includes(to.name as string)) {
|
||||
if (to.path === LOGIN_PATH && accessStore.accessToken) {
|
||||
return decodeURIComponent(
|
||||
(to.query?.redirect as string) || DEFAULT_HOME_PATH,
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// accessToken 检查
|
||||
if (!accessStore.accessToken) {
|
||||
// 明确声明忽略权限访问权限,则可以访问
|
||||
if (to.meta.ignoreAccess) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 没有访问权限,跳转登录页面
|
||||
if (to.fullPath !== LOGIN_PATH) {
|
||||
return {
|
||||
path: LOGIN_PATH,
|
||||
// 如不需要,直接删除 query
|
||||
query: { redirect: encodeURIComponent(to.fullPath) },
|
||||
// 携带当前跳转的页面,登录后重新跳转该页面
|
||||
replace: true,
|
||||
};
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
// 是否已经生成过动态路由
|
||||
if (accessStore.isAccessChecked) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 生成路由表
|
||||
// 当前登录用户拥有的角色标识列表
|
||||
const userInfo = userStore.userInfo || (await authStore.fetchUserInfo());
|
||||
const userRoles = userInfo.roles ?? [];
|
||||
|
||||
// debugger
|
||||
|
||||
// 二开,从统一授权获取菜单key值,遍历本地所有菜单进行添加
|
||||
|
||||
const staticRouteKeys = [
|
||||
'Dashboard',
|
||||
'home',
|
||||
'User',
|
||||
'UserCenter',
|
||||
'UserTodo',
|
||||
'IFrame',
|
||||
'MeetingStandingBook',
|
||||
'MeetingStart',
|
||||
'DutyStandingBook',
|
||||
'ContractInfo',
|
||||
];
|
||||
|
||||
const r = await Apis.sys.user.functiontree.get_XTBGXT();
|
||||
let originRouters = r.rows[0].children;
|
||||
// 提取数据的函数
|
||||
const extractData = (input: any[]) => {
|
||||
const result: any[] = [];
|
||||
function traverse(node: any) {
|
||||
if (node.id && node.name) {
|
||||
result.push({
|
||||
id: node.id,
|
||||
path: node.remark,
|
||||
name: node.name,
|
||||
order: node.showOrder || 0,
|
||||
});
|
||||
}
|
||||
if (node.children && node.children.length > 0) {
|
||||
for (const child of node.children) {
|
||||
traverse(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const node of input) {
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
// console.log('originRouters', originRouters)
|
||||
originRouters = extractData(originRouters);
|
||||
// console.log('originRouters', originRouters)
|
||||
|
||||
let finalRoutes = filterRoutesByPermissions(
|
||||
dynamicRoutes,
|
||||
originRouters,
|
||||
staticRouteKeys,
|
||||
);
|
||||
console.log(originRouters);
|
||||
// console.log('finalRoutes', finalRoutes)
|
||||
|
||||
// console.log('dynamicRoutes', dynamicRoutes)
|
||||
// console.log('userInfo', userInfo)
|
||||
|
||||
if (userInfo.accountId == 'Admin.itl' || userInfo._isSkip) {
|
||||
finalRoutes = dynamicRoutes;
|
||||
}
|
||||
|
||||
// console.log(userInfo)
|
||||
|
||||
// 生成菜单和路由
|
||||
const { accessibleMenus, accessibleRoutes } = await generateAccess({
|
||||
roles: userRoles,
|
||||
router,
|
||||
// 则会在菜单中显示,但是访问会被重定向到403
|
||||
routes: finalRoutes,
|
||||
});
|
||||
// 保存菜单信息和路由信息
|
||||
accessStore.setAccessMenus(accessibleMenus);
|
||||
accessStore.setAccessRoutes(accessibleRoutes);
|
||||
accessStore.setIsAccessChecked(true);
|
||||
const redirectPath = (from.query.redirect ?? to.fullPath) as string;
|
||||
|
||||
return {
|
||||
...router.resolve(decodeURIComponent(redirectPath)),
|
||||
replace: true,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 项目守卫配置
|
||||
* @param router
|
||||
*/
|
||||
function createRouterGuard(router: Router) {
|
||||
/** 通用 */
|
||||
setupCommonGuard(router);
|
||||
/** 权限访问 */
|
||||
setupAccessGuard(router);
|
||||
}
|
||||
|
||||
export { createRouterGuard };
|
|
@ -1,32 +0,0 @@
|
|||
import {
|
||||
createRouter,
|
||||
createWebHashHistory,
|
||||
createWebHistory,
|
||||
} from 'vue-router';
|
||||
|
||||
import { resetStaticRoutes } from '@vben/utils';
|
||||
|
||||
import { createRouterGuard } from './guard';
|
||||
import { routes } from './routes';
|
||||
|
||||
/**
|
||||
* @zh_CN 创建vue-router实例
|
||||
*/
|
||||
const router = createRouter({
|
||||
history:
|
||||
import.meta.env.VITE_ROUTER_HISTORY === 'hash'
|
||||
? createWebHashHistory(import.meta.env.VITE_BASE)
|
||||
: createWebHistory(import.meta.env.VITE_BASE),
|
||||
// 应该添加到路由的初始路由列表。
|
||||
routes,
|
||||
scrollBehavior: () => ({ left: 0, top: 0 }),
|
||||
// 是否应该禁止尾部斜杠。
|
||||
// strict: true,
|
||||
});
|
||||
|
||||
const resetRoutes = () => resetStaticRoutes(router, routes);
|
||||
|
||||
// 创建路由守卫
|
||||
createRouterGuard(router);
|
||||
|
||||
export { resetRoutes, router };
|
|
@ -1,114 +0,0 @@
|
|||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { DEFAULT_HOME_PATH } from '@vben/constants';
|
||||
|
||||
import { AuthPageLayout, BasicLayout, IFrameView } from '#/layouts';
|
||||
import { $t } from '#/locales';
|
||||
import Login from '#/views/_core/authentication/login.vue';
|
||||
|
||||
/** 全局404页面 */
|
||||
const fallbackNotFoundRoute: RouteRecordRaw = {
|
||||
component: () => import('#/views/_core/fallback/not-found.vue'),
|
||||
meta: {
|
||||
hideInBreadcrumb: true,
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
title: '404',
|
||||
},
|
||||
name: 'FallbackNotFound',
|
||||
path: '/:path(.*)*',
|
||||
};
|
||||
|
||||
/** 基本路由,这些路由是必须存在的 */
|
||||
const coreRoutes: RouteRecordRaw[] = [
|
||||
{
|
||||
meta: {
|
||||
title: 'Root',
|
||||
},
|
||||
name: 'Root',
|
||||
path: '/',
|
||||
redirect: DEFAULT_HOME_PATH,
|
||||
},
|
||||
{
|
||||
component: AuthPageLayout,
|
||||
props: {
|
||||
toolbar: false,
|
||||
},
|
||||
meta: {
|
||||
title: 'Authentication',
|
||||
},
|
||||
name: 'Authentication',
|
||||
path: '/auth',
|
||||
children: [
|
||||
{
|
||||
name: 'Login',
|
||||
path: 'login',
|
||||
component: Login,
|
||||
meta: {
|
||||
title: $t('page.core.login'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'CodeLogin',
|
||||
path: 'code-login',
|
||||
component: () => import('#/views/_core/authentication/code-login.vue'),
|
||||
meta: {
|
||||
title: $t('page.core.codeLogin'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'QrCodeLogin',
|
||||
path: 'qrcode-login',
|
||||
component: () =>
|
||||
import('#/views/_core/authentication/qrcode-login.vue'),
|
||||
meta: {
|
||||
title: $t('page.core.qrcodeLogin'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ForgetPassword',
|
||||
path: 'forget-password',
|
||||
component: () =>
|
||||
import('#/views/_core/authentication/forget-password.vue'),
|
||||
meta: {
|
||||
title: $t('page.core.forgetPassword'),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Register',
|
||||
path: 'register',
|
||||
component: () => import('#/views/_core/authentication/register.vue'),
|
||||
meta: {
|
||||
title: $t('page.core.register'),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
component: IFrameView,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: 210,
|
||||
title: 'iframe',
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
},
|
||||
name: 'IFrame',
|
||||
path: '/iframe',
|
||||
children: [
|
||||
{
|
||||
name: 'ContractInfo',
|
||||
path: '/iframe/contract/info',
|
||||
component: () => import('#/views/contract/iframe-info/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同明细信息',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export { coreRoutes, fallbackNotFoundRoute };
|
|
@ -1,31 +0,0 @@
|
|||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { mergeRouteModules, traverseTreeValues } from '@vben/utils';
|
||||
|
||||
import { coreRoutes, fallbackNotFoundRoute } from './core';
|
||||
|
||||
const dynamicRouteFiles = import.meta.glob('./modules/**/*.ts', {
|
||||
eager: true,
|
||||
});
|
||||
|
||||
// 有需要可以自行打开注释,并创建文件夹
|
||||
// const externalRouteFiles = import.meta.glob('./external/**/*.ts', { eager: true });
|
||||
|
||||
/** 动态路由 */
|
||||
const dynamicRoutes: RouteRecordRaw[] = mergeRouteModules(dynamicRouteFiles);
|
||||
|
||||
/** 外部路由列表,访问这些页面可以不需要Layout,可能用于内嵌在别的系统 */
|
||||
// const externalRoutes: RouteRecordRaw[] = mergeRouteModules(externalRouteFiles);
|
||||
const externalRoutes: RouteRecordRaw[] = [];
|
||||
|
||||
/** 路由列表,由基本路由+静态路由组成 */
|
||||
const routes: RouteRecordRaw[] = [
|
||||
...coreRoutes,
|
||||
...externalRoutes,
|
||||
fallbackNotFoundRoute,
|
||||
];
|
||||
|
||||
/** 基本路由列表,这些路由不需要进入权限拦截 */
|
||||
const coreRouteNames = traverseTreeValues(coreRoutes, (route) => route.name);
|
||||
|
||||
export { coreRouteNames, dynamicRoutes, routes };
|
|
@ -1,537 +0,0 @@
|
|||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
title: '合同配置',
|
||||
},
|
||||
name: 'HTGLHTPZ',
|
||||
path: '/contract/config',
|
||||
children: [
|
||||
{
|
||||
name: 'ContractConfigIndex',
|
||||
path: '/contract/config',
|
||||
component: () => import('#/views/contract/config/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同配置',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'HTGLHTLX',
|
||||
path: '/contract/approval',
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同立项',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractApprovalEdit',
|
||||
path: '/contract/approval/edit/:id?',
|
||||
beforeEnter: (e) => {
|
||||
console.log('e', e);
|
||||
if (e.params.id && e.params.id === ':id') {
|
||||
e.params.id = '';
|
||||
e.fullPath = '/contract/approval/edit';
|
||||
}
|
||||
},
|
||||
component: () => import('#/views/contract/approval/edit/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '立项申报',
|
||||
activePath: '/contract/approval/edit/:id?',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractApprovalList',
|
||||
path: '/contract/approval/list',
|
||||
component: () => import('#/views/contract/approval/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '立项编制',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractApprovalTodo',
|
||||
path: '/contract/approval/todo',
|
||||
component: () => import('#/views/contract/approval/todo/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '立项提示',
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: 'ContractApprovalSigningBasis',
|
||||
path: '/contract/approval/signing-basis',
|
||||
component: () =>
|
||||
import('#/views/contract/approval/signing-basis/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '签约依据维护',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'HTGLHTXS',
|
||||
path: '/contract/business',
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同选商',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractBusinessEdit',
|
||||
path: '/contract/business/edit/:id?',
|
||||
component: () => import('#/views/contract/business/edit/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '选商填报',
|
||||
activePath: '/contract/business/todo',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractBusinessResult',
|
||||
path: '/contract/business/result/:id?',
|
||||
component: () => import('#/views/contract/business/result/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '选商结果填报',
|
||||
activePath: '/contract/business/todo',
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: 'ContractBusinessList',
|
||||
path: '/contract/business/list',
|
||||
component: () => import('#/views/contract/business/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '选商编制',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractBusinessResultList',
|
||||
path: '/contract/business/result-list',
|
||||
component: () =>
|
||||
import('#/views/contract/business/result-list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '选商结果编制',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractBusinessTodo',
|
||||
path: '/contract/business/todo',
|
||||
component: () => import('#/views/contract/business/todo/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '选商提示',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'HTGLHTSB',
|
||||
path: '/contract/declaration',
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同申报',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractDeclarationEdit',
|
||||
path: '/contract/declaration/edit/:id?',
|
||||
beforeEnter: (e) => {
|
||||
if (e.params.id && e.params.id === ':id') {
|
||||
e.params.id = '';
|
||||
e.fullPath = '/contract/declaration/edit';
|
||||
}
|
||||
},
|
||||
component: () => import('#/views/contract/declaration/edit/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '申报填报',
|
||||
activePath: '/contract/declaration/todo',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractDeclarationList',
|
||||
path: '/contract/declaration/list',
|
||||
component: () => import('#/views/contract/declaration/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '申报编制',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractDeclarationTodo',
|
||||
path: '/contract/declaration/todo',
|
||||
component: () => import('#/views/contract/declaration/todo/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '申报提示',
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: 'ContractDeclarationPrint',
|
||||
path: '/contract/declaration/print',
|
||||
component: () => import('#/views/contract/declaration/print/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同打印',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// {
|
||||
// name: 'ContractAudit',
|
||||
// path: '/contract/audit',
|
||||
// component: BasicLayout,
|
||||
// meta: {
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: '合同审批',
|
||||
// },
|
||||
// children: [
|
||||
// {
|
||||
// name: 'ContractAuditTodo',
|
||||
// path: '/contract/audit/todo',
|
||||
// component: () => import('#/views/contract/audit/todo/index.vue'),
|
||||
// meta: {
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: '审批提示',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: 'ContractAuditList',
|
||||
// path: '/contract/audit/list',
|
||||
// component: () => import('#/views/contract/audit/list/index.vue'),
|
||||
// meta: {
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: '审批查询',
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
name: 'HTGLHTQD',
|
||||
path: '/contract/sign',
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同签订',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractSignEdit',
|
||||
path: '/contract/sign/edit/:id?',
|
||||
beforeEnter: (e) => {
|
||||
if (e.params.id && e.params.id === ':id') {
|
||||
e.params.id = '';
|
||||
e.fullPath = '/contract/sign/edit';
|
||||
}
|
||||
},
|
||||
component: () => import('#/views/contract/sign/edit/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '签订填报',
|
||||
activePath: '/contract/sign/todo',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractSignList',
|
||||
path: '/contract/sign/list',
|
||||
component: () => import('#/views/contract/sign/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '签订编制',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractSignTodo',
|
||||
path: '/contract/sign/todo',
|
||||
component: () => import('#/views/contract/sign/todo/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '签订提示',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'HTGLHTLVX',
|
||||
path: '/contract/perform',
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同履行',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractPerformEdit',
|
||||
path: '/contract/perform/edit/:id?',
|
||||
beforeEnter: (e) => {
|
||||
if (e.params.id && e.params.id === ':id') {
|
||||
e.params.id = '';
|
||||
e.fullPath = '/contract/perform/edit';
|
||||
}
|
||||
},
|
||||
component: () => import('#/views/contract/perform/edit/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
hideInTab: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '履行填报',
|
||||
activePath: '/contract/perform/todo',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractPerformList',
|
||||
path: '/contract/perform/list',
|
||||
component: () => import('#/views/contract/perform/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '履行编制',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractPerformTodo',
|
||||
path: '/contract/perform/todo',
|
||||
component: () => import('#/views/contract/perform/todo/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '履行提示',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractPerformResult',
|
||||
path: '/contract/perform/result',
|
||||
component: () => import('#/views/contract/perform/result/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '履行结果填报',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractPerformResultList',
|
||||
path: '/contract/perform/resultList',
|
||||
component: () =>
|
||||
import('#/views/contract/perform/result-list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '履行结果编制',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractPerformTemporaryArchive',
|
||||
path: '/contract/perform/temporary-archive',
|
||||
component: () =>
|
||||
import('#/views/contract/perform/temporary-archive/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '临时归档',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'HTGLHTGD',
|
||||
path: '/contract/archive',
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同归档',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractArchiveTodoArchive',
|
||||
path: '/contract/archive/todo/archive',
|
||||
component: () =>
|
||||
import('#/views/contract/archive/todo/archive/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同归档',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractArchiveTodoRetracement',
|
||||
path: '/contract/archive/todo/retracement',
|
||||
component: () =>
|
||||
import('#/views/contract/archive/todo/retracement/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同回档',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractArchiveList',
|
||||
path: '/contract/archive/list',
|
||||
component: () => import('#/views/contract/archive/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '归档查询',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'HTGLHTQYSQ',
|
||||
path: '/contract/sign-authorization',
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '签约授权管理',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractSignAuthorizationEdit',
|
||||
path: '/contract/sign-authorization/edit/:id?',
|
||||
beforeEnter: (e) => {
|
||||
if (e.params.id && e.params.id === ':id') {
|
||||
e.params.id = '';
|
||||
e.fullPath = '/contract/sign-authorization/edit';
|
||||
}
|
||||
},
|
||||
component: () =>
|
||||
import('#/views/contract/sign-authorization/edit/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '签约授权申报',
|
||||
activePath: '/contract/sign-authorization/edit/:id?',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractSignAuthorizationList',
|
||||
path: '/contract/sign-authorization/list',
|
||||
component: () =>
|
||||
import('#/views/contract/sign-authorization/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '签约授权查询',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'HTGLHTXDR',
|
||||
path: '/contract/company',
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '合同相对人',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'ContractCompanyEdit',
|
||||
path: '/contract/company/edit/:id?',
|
||||
beforeEnter: (e) => {
|
||||
if (e.params.id && e.params.id === ':id') {
|
||||
e.params.id = '';
|
||||
e.fullPath = '/contract/company/edit';
|
||||
}
|
||||
},
|
||||
component: () => import('#/views/contract/company/edit/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '相对人录入维护',
|
||||
activePath: '/contract/company/edit/:id?',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'ContractCompanyList',
|
||||
path: '/contract/company/list',
|
||||
component: () => import('#/views/contract/company/list/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '相对人查询',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// {
|
||||
// name: 'ContractStatistic',
|
||||
// path: '/contract/statistic',
|
||||
// meta: {
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: '统计分析',
|
||||
// },
|
||||
// children: [
|
||||
// {
|
||||
// name: 'ContractStatisticAnalysis',
|
||||
// path: '/contract/statistic/analysis',
|
||||
// beforeEnter: (e) => {
|
||||
// if (e.params.id && e.params.id === ':id') {
|
||||
// e.params.id = ''
|
||||
// e.fullPath = '/contract/company/edit'
|
||||
// }
|
||||
// },
|
||||
// component: () => import('#/views/contract/company/edit/index.vue'),
|
||||
// meta: {
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: '统计分析',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: 'ContractStatisticAbrogateList',
|
||||
// path: '/contract/statistic/abrogate-list',
|
||||
// component: () => import('#/views/contract/company/list/index.vue'),
|
||||
// meta: {
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: '废除查询',
|
||||
// },
|
||||
// },
|
||||
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// name: 'ContractPrint',
|
||||
// path: '/contract/statistic',
|
||||
// meta: {
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: '统计分析',
|
||||
// },
|
||||
// children: [
|
||||
// {
|
||||
// name: 'ContractPrintBusiness',
|
||||
// path: '/contract/print/business',
|
||||
// component: () => import('#/views/contract/company/edit/index.vue'),
|
||||
// meta: {
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: '统计分析',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: 'ContractPrintAbrogateList',
|
||||
// path: '/contract/print/abrogate-list',
|
||||
// component: () => import('#/views/contract/company/list/index.vue'),
|
||||
// meta: {
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: '废除查询',
|
||||
// },
|
||||
// },
|
||||
|
||||
// ],
|
||||
// },
|
||||
];
|
||||
|
||||
export default routes;
|
|
@ -1,49 +0,0 @@
|
|||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: -1,
|
||||
title: '首页',
|
||||
},
|
||||
name: 'Dashboard',
|
||||
path: '/home',
|
||||
children: [
|
||||
{
|
||||
name: 'home',
|
||||
path: '/home',
|
||||
component: () => import('#/views/dashboard/home/index.vue'),
|
||||
meta: {
|
||||
affixTab: true,
|
||||
hideInMenu: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '首页',
|
||||
},
|
||||
},
|
||||
// {
|
||||
// name: 'Analytics',
|
||||
// path: '/analytics',
|
||||
// component: () => import('#/views/dashboard/analytics/index.vue'),
|
||||
// meta: {
|
||||
// affixTab: true,
|
||||
// icon: 'lucide:area-chart',
|
||||
// title: $t('page.dashboard.analytics'),
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: 'Workspace',
|
||||
// path: '/workspace',
|
||||
// component: () => import('#/views/dashboard/workspace/index.vue'),
|
||||
// meta: {
|
||||
// title: $t('page.dashboard.workspace'),
|
||||
// },
|
||||
// },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default routes;
|
|
@ -1,29 +0,0 @@
|
|||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: 10,
|
||||
title: '系统管理',
|
||||
},
|
||||
name: 'System',
|
||||
path: '/system',
|
||||
children: [
|
||||
{
|
||||
name: 'Dict',
|
||||
path: '/system/dict',
|
||||
component: () => import('#/views/system/dict/index.vue'),
|
||||
meta: {
|
||||
icon: 'lucide:area-chart',
|
||||
title: '字典管理',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default routes;
|
|
@ -1,51 +0,0 @@
|
|||
import type { RouteRecordRaw } from 'vue-router';
|
||||
|
||||
import { BasicLayout } from '#/layouts';
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
component: BasicLayout,
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
icon: 'lucide:layout-dashboard',
|
||||
order: -1,
|
||||
title: '用户中心',
|
||||
},
|
||||
name: 'User',
|
||||
path: '/user',
|
||||
children: [
|
||||
{
|
||||
name: 'UserTodo',
|
||||
path: '/user/todo',
|
||||
component: () => import('#/views/user-center/todo/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '消息通知',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'UserCenter',
|
||||
path: '/user/center',
|
||||
component: () => import('#/views/user-center/center/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '个人中心',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'About',
|
||||
path: '/about',
|
||||
component: () => import('#/views/_core/about/index.vue'),
|
||||
meta: {
|
||||
hideInMenu: true,
|
||||
icon: 'lucide:area-chart',
|
||||
title: '关于',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export default routes;
|
|
@ -1,130 +0,0 @@
|
|||
import type { LoginAndRegisterParams } from '@vben/common-ui';
|
||||
import type { UserInfo } from '@vben/types';
|
||||
|
||||
import { ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@vben/constants';
|
||||
import { resetAllStores, useAccessStore, useUserStore } from '@vben/stores';
|
||||
|
||||
import { notification } from 'ant-design-vue';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
import { getUserInfoApi, loginApi } from '#/api/system/auth';
|
||||
import { $t } from '#/locales';
|
||||
|
||||
export const useAuthStore = defineStore('auth', () => {
|
||||
const accessStore = useAccessStore();
|
||||
const userStore = useUserStore();
|
||||
const router = useRouter();
|
||||
|
||||
const loginLoading = ref(false);
|
||||
let loginInfo = localStorage.getItem('loginInfo') || '{}';
|
||||
/**
|
||||
* 异步处理登录操作
|
||||
* Asynchronously handle the login process
|
||||
* @param params 登录表单数据
|
||||
*/
|
||||
async function authLogin(
|
||||
params: LoginAndRegisterParams,
|
||||
onSuccess?: () => Promise<void> | void,
|
||||
) {
|
||||
// 异步处理用户登录操作并获取 accessToken
|
||||
let userInfo: null | UserInfo = null;
|
||||
try {
|
||||
loginLoading.value = true;
|
||||
if (params.username == 'Admin.itl' || params._isSkip) {
|
||||
} else {
|
||||
params.username = `${params.username}.RL`;
|
||||
}
|
||||
|
||||
const loginRes = await loginApi({
|
||||
...params,
|
||||
appId: 'HTGL',
|
||||
appName: '合同管理系统',
|
||||
appSecret: 'r1og4wiyrrvr4qvw2aafhgvy',
|
||||
});
|
||||
console.log(loginRes);
|
||||
if (params._isSkip) {
|
||||
loginRes._isSkip = params._isSkip;
|
||||
}
|
||||
|
||||
loginInfo = JSON.stringify(loginRes);
|
||||
localStorage.setItem('loginInfo', loginInfo);
|
||||
|
||||
const { accessToken } = loginRes;
|
||||
// 如果成功获取到 accessToken
|
||||
if (accessToken) {
|
||||
accessStore.setAccessToken(accessToken);
|
||||
|
||||
// 获取用户信息并存储到 accessStore 中
|
||||
const [fetchUserInfoResult] = await Promise.all([fetchUserInfo()]);
|
||||
|
||||
userInfo = fetchUserInfoResult;
|
||||
if (params._isSkip) {
|
||||
userInfo._isSkip = params._isSkip;
|
||||
}
|
||||
userStore.setUserInfo(userInfo);
|
||||
|
||||
if (accessStore.loginExpired) {
|
||||
accessStore.setLoginExpired(false);
|
||||
} else {
|
||||
onSuccess
|
||||
? await onSuccess?.()
|
||||
: await router.push(userInfo.homePath || DEFAULT_HOME_PATH);
|
||||
}
|
||||
|
||||
if (userInfo?.realName) {
|
||||
notification.success({
|
||||
description: `${$t('authentication.loginSuccessDesc')}:${userInfo?.realName}`,
|
||||
duration: 3,
|
||||
message: $t('authentication.loginSuccess'),
|
||||
});
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
loginLoading.value = false;
|
||||
}
|
||||
|
||||
return {
|
||||
userInfo,
|
||||
};
|
||||
}
|
||||
|
||||
async function logout(redirect: boolean = true) {
|
||||
// await logoutApi();
|
||||
resetAllStores();
|
||||
accessStore.setLoginExpired(false);
|
||||
|
||||
// 回登陆页带上当前路由地址
|
||||
await router.replace({
|
||||
path: LOGIN_PATH,
|
||||
query: redirect
|
||||
? {
|
||||
redirect: encodeURIComponent(router.currentRoute.value.fullPath),
|
||||
}
|
||||
: {},
|
||||
});
|
||||
}
|
||||
|
||||
async function fetchUserInfo() {
|
||||
let userInfo: null | UserInfo = null;
|
||||
userInfo = await getUserInfoApi();
|
||||
userInfo = { ...JSON.parse(loginInfo), ...userInfo };
|
||||
userStore.setUserInfo(userInfo);
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
function $reset() {
|
||||
localStorage.removeItem('loginInfo');
|
||||
loginLoading.value = false;
|
||||
}
|
||||
|
||||
return {
|
||||
$reset,
|
||||
authLogin,
|
||||
fetchUserInfo,
|
||||
loginLoading,
|
||||
logout,
|
||||
};
|
||||
});
|
|
@ -1,202 +0,0 @@
|
|||
import { computed, ref } from 'vue';
|
||||
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
// import { getDictDataList } from '@/api/system/dict';
|
||||
import Apis from '#/api';
|
||||
import dataModule from '#/utils/dict/static.data';
|
||||
|
||||
const DICT_STORAGE_KEY = 'DICT_KEY';
|
||||
|
||||
interface DictDataVO {
|
||||
dictType: string;
|
||||
label: string;
|
||||
value: null | number | string;
|
||||
colorType: string;
|
||||
cssClass: string;
|
||||
}
|
||||
|
||||
export const useDictStore = defineStore('app-dict', () => {
|
||||
/** 是否初始化字典,是的话每次应用自动加载,后续走缓存,否的话每次请求 */
|
||||
const initDict = ref(true);
|
||||
/** 字典合集,仅initDict为true时生效 */
|
||||
const dictMap = ref<Record<string, DictDataVO[]>>({});
|
||||
/** 是否已设置字典合集,仅initDict为true时生效 */
|
||||
const isSetDict = ref(false);
|
||||
/** 每次新查询字典时的查询缓存,单位:秒 主要用于循环获取数据显示label的场景,建议不低于10s */
|
||||
const expireAfterSeconds = ref(30);
|
||||
|
||||
/** 获取所有字典数据 */
|
||||
const getDictMap = computed(() => dictMap.value);
|
||||
/** 判断是否已设置字典表 */
|
||||
const getIsSetDict = computed(() => isSetDict.value);
|
||||
|
||||
/**
|
||||
* 设置字典信息
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
const setDictMap = async (): Promise<boolean> => {
|
||||
try {
|
||||
// 模拟网络请求
|
||||
// await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
|
||||
const data = await Apis.dictData.get_page({
|
||||
params: { pageNum: 1, pageSize: 10_000 },
|
||||
});
|
||||
const dictDataMap: Record<string, DictDataVO[]> = {};
|
||||
// 处理静态字典数据
|
||||
Object.keys(dataModule).forEach((dictType) => {
|
||||
const dictEntries = dataModule[dictType];
|
||||
dictEntries.data.forEach((dictData) => {
|
||||
dictData.type = dictType;
|
||||
|
||||
if (!dictDataMap[dictType]) {
|
||||
dictDataMap[dictType] = [];
|
||||
}
|
||||
dictDataMap[dictType].push({
|
||||
value: dictData.value,
|
||||
label: dictData.name,
|
||||
colorType: dictData.colorType,
|
||||
cssClass: dictData.cssClass,
|
||||
...dictData,
|
||||
} as DictDataVO);
|
||||
});
|
||||
});
|
||||
|
||||
// 处理动态字典数据
|
||||
data?.rows.forEach((dictData: any) => {
|
||||
if (!dictDataMap[dictData.type]) dictDataMap[dictData.type] = [];
|
||||
dictDataMap[dictData.type].push({
|
||||
value: dictData.value,
|
||||
label: dictData.name,
|
||||
colorType: dictData.colorType,
|
||||
cssClass: dictData.cssClass,
|
||||
...dictData,
|
||||
} as DictDataVO);
|
||||
});
|
||||
|
||||
console.log('[ dictDataMap ] >', dictDataMap);
|
||||
dictMap.value = dictDataMap;
|
||||
isSetDict.value = true;
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('字典数据获取失败:', error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/** 获取字典数据 输入字典数组,输出包含对应类型的字典对象 */
|
||||
const getDictData = async (
|
||||
dictTypeArr: string[],
|
||||
): Promise<Record<string, DictDataVO[]>> => {
|
||||
const newDictMap: Record<string, DictDataVO[]> = {};
|
||||
|
||||
return await new Promise((resolve) => {
|
||||
if (
|
||||
initDict.value &&
|
||||
isSetDict.value &&
|
||||
Object.keys(dictMap.value).length > 0
|
||||
) {
|
||||
dictTypeArr.forEach((dictType) => {
|
||||
newDictMap[dictType] = dictMap.value[dictType] || [];
|
||||
});
|
||||
resolve(newDictMap);
|
||||
}
|
||||
|
||||
// if (!isSetDict.value) {
|
||||
// console.warn('字典数据尚未加载,正在等待...');
|
||||
|
||||
// const checkInterval = setInterval(() => {
|
||||
// console.warn('字典数据加载中...');
|
||||
|
||||
// if (isSetDict.value) {
|
||||
// console.warn('字典数据完成.');
|
||||
// clearInterval(checkInterval);
|
||||
// dictTypeArr.forEach((dictType) => {
|
||||
// newDictMap[dictType] = dictMap.value[dictType] || [];
|
||||
// });
|
||||
// resolve(newDictMap);
|
||||
// }
|
||||
// }, 45);
|
||||
// }
|
||||
|
||||
// try {
|
||||
// return {};
|
||||
// } catch (error) {
|
||||
// console.error('getDictMap 函数报错:', error);
|
||||
// return {};
|
||||
// }
|
||||
resolve(newDictMap);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取指定类型的具体的某个字典数据信息,数据默认会存在30秒缓存,以备快速使用
|
||||
*
|
||||
* @returns Array
|
||||
*/
|
||||
const getDictInfo = async (dictType: string): Promise<DictDataVO[]> => {
|
||||
const StorageKey = `${DICT_STORAGE_KEY}:${dictType}`;
|
||||
try {
|
||||
localStorage.setItem(StorageKey, JSON.stringify(dictMap.value));
|
||||
const dictDataMap = (await getDictData([dictType])) || {};
|
||||
setTimeout(() => {
|
||||
localStorage.removeItem(StorageKey);
|
||||
}, expireAfterSeconds.value * 1000);
|
||||
return JSON.parse(JSON.stringify(dictDataMap[dictType])) || [];
|
||||
} catch (error) {
|
||||
console.error('getDictInfo函数报错:', error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取指定类型的具体的某个字典数据名称,数据默认会存在30秒缓存,以备快速使用
|
||||
*
|
||||
* @returns DictDataVO
|
||||
*/
|
||||
const getDictDataInfo = async (
|
||||
dictType: string,
|
||||
value: string,
|
||||
): Promise<DictDataVO> => {
|
||||
const dictDataMap = (await getDictInfo(dictType)) || [];
|
||||
return (
|
||||
dictDataMap.find((item) => item.value === value) || ({} as DictDataVO)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取指定类型的具体的某个字典数据名称,数据默认会存在30秒缓存,以备快速使用
|
||||
*
|
||||
* @returns DictDataVO
|
||||
*/
|
||||
const getDictDataLabel = async (
|
||||
dictType: string,
|
||||
value: string,
|
||||
): Promise<string> => {
|
||||
const dictDataMap = (await getDictInfo(dictType)) || [];
|
||||
const info =
|
||||
dictDataMap.find((item) => item.value === value) || ({} as DictDataVO);
|
||||
return info.label;
|
||||
};
|
||||
|
||||
function $reset() {
|
||||
// loginLoading.value = false;
|
||||
}
|
||||
|
||||
return {
|
||||
initDict,
|
||||
dictMap,
|
||||
isSetDict,
|
||||
expireAfterSeconds,
|
||||
getDictMap,
|
||||
getIsSetDict,
|
||||
setDictMap,
|
||||
getDictData,
|
||||
getDictInfo,
|
||||
getDictDataInfo,
|
||||
getDictDataLabel,
|
||||
$reset,
|
||||
};
|
||||
});
|
|
@ -1,2 +0,0 @@
|
|||
export * from './auth';
|
||||
export * from './dict'
|
|
@ -1,226 +0,0 @@
|
|||
/** 数据字典工具类 */
|
||||
import { computed } from 'vue';
|
||||
|
||||
import Apis from '#/api';
|
||||
import { useDictStore } from '#/store/dict';
|
||||
import dataModule from '#/utils/dict/static.data';
|
||||
|
||||
export * from './shared';
|
||||
|
||||
const dictStore = useDictStore();
|
||||
|
||||
const dictData = computed(() => {
|
||||
return dictStore.dictMap;
|
||||
});
|
||||
|
||||
/**
|
||||
* 获取 dictType 对应的数据字典数组
|
||||
*
|
||||
* @param dictType 数据类型
|
||||
* @returns {any | Array} 数据字典数组
|
||||
*/
|
||||
export interface DictDataType {
|
||||
dictType?: string;
|
||||
label: string;
|
||||
value: boolean | null | number | string;
|
||||
key?: any;
|
||||
colorType?: string;
|
||||
cssClass?: string;
|
||||
isDefault?: boolean;
|
||||
}
|
||||
|
||||
export interface DictDataOptions {
|
||||
label?: any;
|
||||
value?: null | number | string;
|
||||
}
|
||||
|
||||
export function getDictDatas(dictType: string) {
|
||||
return dictData.value[dictType] || [];
|
||||
}
|
||||
|
||||
export function getDictOpts(dictType: string) {
|
||||
/**
|
||||
* 这里原来是转换类型 转换类型后反而显示不出来正确的Tag 实际类型转换交给下面的getDictOptions来处理
|
||||
*
|
||||
* bugfix: dictOption.push({ ...dict, value: parseInt(dict.value + '') }) 原来的这种写法是造成页面卡死的原因
|
||||
*/
|
||||
return getDictDatas(dictType);
|
||||
}
|
||||
|
||||
export async function getDictDatasAsync(
|
||||
dictTypeParams: { type: string; valueType?: string }[],
|
||||
) {
|
||||
const dictDataMap: Record<string, DictDataType[]> = {};
|
||||
const foundTypes = new Set<string>();
|
||||
|
||||
// 处理静态字典数据
|
||||
for (const dictType of Object.keys(dataModule)) {
|
||||
const dictParam = dictTypeParams.find((d) => d.type === dictType);
|
||||
if (dictParam) {
|
||||
const dictEntries = dataModule[dictType];
|
||||
if (dictEntries && dictEntries.data && dictEntries.data.length > 0) {
|
||||
dictEntries.data.forEach((dictData) => {
|
||||
dictData.type = dictType;
|
||||
|
||||
if (!dictDataMap[dictType]) {
|
||||
dictDataMap[dictType] = [];
|
||||
}
|
||||
dictDataMap[dictType].push({
|
||||
...dictData,
|
||||
value: dictData.value,
|
||||
label: dictData.label,
|
||||
colorType: dictData.colorType,
|
||||
cssClass: dictData.cssClass,
|
||||
} as DictDataType);
|
||||
});
|
||||
foundTypes.add(dictType);
|
||||
}
|
||||
// 如果所有类型都已找到,提前返回
|
||||
if (foundTypes.size === dictTypeParams.length) {
|
||||
return dictDataMap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 并行获取远程字典数据
|
||||
const promises = dictTypeParams.map(async ({ type, valueType }) => {
|
||||
if (!foundTypes.has(type)) {
|
||||
try {
|
||||
const data = await Apis.dictData.get_page({
|
||||
params: { type },
|
||||
});
|
||||
dictDataMap[type] = (data.rows || []).map((dictData: any) => ({
|
||||
value: convertValue(dictData.value, valueType),
|
||||
label: dictData.name,
|
||||
colorType: dictData.colorType,
|
||||
cssClass: dictData.cssClass,
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch data for type ${type}:`, error);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await Promise.all(promises);
|
||||
return dictDataMap;
|
||||
}
|
||||
|
||||
export function getDictOptions(
|
||||
dictType: string,
|
||||
valueType?: 'boolean' | 'number' | 'string',
|
||||
): any[] {
|
||||
const dictOption: DictDataType[] = [];
|
||||
valueType ||= 'string';
|
||||
|
||||
const dictOptions: DictDataType[] = dictData.value[dictType] || [];
|
||||
if (dictOptions && dictOptions.length > 0) {
|
||||
dictOptions.forEach((dict: DictDataType) => {
|
||||
dictOption.push({
|
||||
...dict,
|
||||
key: dict.value,
|
||||
value: convertValue(dict.value, valueType),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return dictOption;
|
||||
}
|
||||
|
||||
function convertValue(value, type) {
|
||||
switch (type) {
|
||||
case 'boolean': {
|
||||
return value === 'true';
|
||||
}
|
||||
case 'number': {
|
||||
return Number.parseInt(value, 10);
|
||||
}
|
||||
case 'string': {
|
||||
return String(value);
|
||||
}
|
||||
default: {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
export async function getDictOptionsAsync(
|
||||
dictType: string,
|
||||
valueType: 'boolean' | 'number' | 'string' = 'string',
|
||||
): Promise<DictDataType[]> {
|
||||
try {
|
||||
const response = await getDictDatasAsync([
|
||||
{ type: dictType, valueType: valueType },
|
||||
]);
|
||||
const dictOptions: DictDataType[] = response[dictType] || [];
|
||||
|
||||
return dictOptions.map((dict: DictDataType) => ({
|
||||
...dict,
|
||||
key: dict.value,
|
||||
value: convertValue(dict.value, valueType),
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error('Error fetching dictionary data:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取指定 value 的字典数据 */
|
||||
export function getDictObj(dictType: string, value: any): DictDataType | null {
|
||||
const dictOptions: DictDataType[] = getDictDatas(dictType);
|
||||
if (dictOptions) {
|
||||
if (value) {
|
||||
return (
|
||||
dictOptions.find(
|
||||
(dict: DictDataType) => dict.value === value.toString(),
|
||||
) || null
|
||||
);
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取指定 value 的字典数据 */
|
||||
export function getDictObjByOptions(
|
||||
options: DictDataType[],
|
||||
value: any,
|
||||
): DictDataType | null {
|
||||
if (options) {
|
||||
if (value) {
|
||||
const result = options.find((dict: DictDataType) => dict.value === value);
|
||||
return result || null;
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取指定 value 的字典数据 */
|
||||
export async function getDictObjAsync(
|
||||
dictType: string,
|
||||
value: any,
|
||||
): Promise<DictDataType | null> {
|
||||
const dictOptions = await getDictOptionsAsync(dictType);
|
||||
if (dictOptions) {
|
||||
if (value) {
|
||||
return (
|
||||
dictOptions.find(
|
||||
(dict: DictDataType) => dict.value === value.toString(),
|
||||
) || null
|
||||
);
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取字典默认数据 */
|
||||
export function getDictDefaultObj(dictType: string): DictDataType | null {
|
||||
const dictOptions: DictDataType[] = getDictDatas(dictType);
|
||||
return dictOptions
|
||||
? dictOptions.find((dict: DictDataType) => dict.isDefault == '1') ||
|
||||
dictOptions[0]
|
||||
: null;
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
export enum DICT_TYPE {
|
||||
/** 系统通用状态 */
|
||||
sys_normal_disable = 'sys_normal_disable',
|
||||
/** 合同管理-资金流向 */
|
||||
contract_fund_flow = 'contract_fund_flow',
|
||||
/** 合同管理-资金渠道 */
|
||||
contract_funding_source = 'contract_funding_source',
|
||||
/** 合同管理-组织形式 */
|
||||
contract_organization_form = 'contract_organization_form',
|
||||
/** 合同管理-币种单位 */
|
||||
contract_currency_unit = 'contract_currency_unit',
|
||||
/** 合同管理-合同模块 */
|
||||
contract_module = 'contract_module',
|
||||
/** 合同管理-选商方式 */
|
||||
contract_selection_method = 'contract_selection_method',
|
||||
/** 合同管理-合同审批 */
|
||||
contract_approval = 'contract_approval',
|
||||
/** 合同管理-履行状态 */
|
||||
contract_performance_status = 'contract_performance_status',
|
||||
/** 合同管理-授权类型 */
|
||||
contract_authorization_type = 'contract_authorization_type',
|
||||
/** 合同管理-项目类型 */
|
||||
contract_project_type = 'contract_project_type',
|
||||
/** 合同管理-商务计价方式 */
|
||||
contract_price_style = 'contract_price_style',
|
||||
/** 综合管理-项目管理 */
|
||||
comprehensive_project = 'comprehensive_project',
|
||||
/** 综合管理-项目名称管理 */
|
||||
comprehensive_project_name = 'comprehensive_project_name',
|
||||
comprehensive_config = 'comprehensive_config',
|
||||
/** 合同管理-签约依据类型 */
|
||||
contract_basis_type = 'contract_basis_type',
|
||||
/** 合同管理-合同相对人性质 */
|
||||
counterparty_nature = 'counterparty_nature',
|
||||
/** 变更原因 */
|
||||
cancel_reson = 'cancel_reson',
|
||||
/** 划分标段 */
|
||||
section_type = 'section_type',
|
||||
/** 标段数 */
|
||||
section_num = 'section_num',
|
||||
/** 常用是否 */
|
||||
common_whether = 'common_whether',
|
||||
/** 履行期限 */
|
||||
deadline_for_performance = 'deadline_for_performance',
|
||||
/** 纠纷解决方式 */
|
||||
dispute_settlement_methods = 'dispute_settlement_methods',
|
||||
/** 付款性质 */
|
||||
payment_nature = 'payment_nature',
|
||||
/** 合同立项节点流程 */
|
||||
contract_approval_flow_node = 'contract_approval_flow_node',
|
||||
/** 合同选商节点流程 */
|
||||
contract_business_flow_node = 'contract_business_flow_node',
|
||||
/** 合同立项节点流程 */
|
||||
contract_abolish_flow_node = 'contract_abolish_flow_node',
|
||||
/** 合同授权类型 */
|
||||
contract_authorization_type2 = 'contract_authorization_type2',
|
||||
/** 合同授权期限 */
|
||||
contract_authorization_period = 'contract_authorization_period',
|
||||
/** 合同待办类型 */
|
||||
contract_todo_type = 'contract_todo_type'
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
const createEntry = (annotation = '', data = []) => ({
|
||||
annotation,
|
||||
data,
|
||||
});
|
||||
|
||||
export default {
|
||||
sys_normal_disable: createEntry('系统通用状态'),
|
||||
contract_fund_flow: createEntry('合同管理-资金流向'),
|
||||
contract_funding_source: createEntry('合同管理-资金渠道'),
|
||||
contract_organization_form: createEntry('合同管理-组织形式'),
|
||||
contract_currency_unit: createEntry('合同管理-币种单位'),
|
||||
contract_module: createEntry('合同管理-合同模块'),
|
||||
contract_selection_method: createEntry('合同管理-选商方式'),
|
||||
contract_approval: createEntry('合同管理-合同审批'),
|
||||
contract_performance_status: createEntry('合同管理-履行状态'),
|
||||
contract_authorization_type: createEntry('合同管理-授权类型'),
|
||||
contract_project_type: createEntry('合同管理-项目类型'),
|
||||
contract_price_style: createEntry('合同管理-商务计价方式'),
|
||||
|
||||
comprehensive_project: createEntry('综合管理-项目管理'),
|
||||
comprehensive_project_name: createEntry('综合管理-项目名称管理'),
|
||||
comprehensive_config: createEntry(),
|
||||
|
||||
contract_basis_type: createEntry('合同管理-签约依据类型'),
|
||||
|
||||
counterparty_nature: createEntry('合同管理-合同相对人性质'),
|
||||
|
||||
cancel_reson: createEntry('变更原因', [
|
||||
{ label: '未填写原因', value: '0' },
|
||||
{ label: '用户取消', value: '1' },
|
||||
{ label: '系统取消', value: '2' },
|
||||
{ label: '其他原因', value: '3' },
|
||||
]),
|
||||
|
||||
section_type: createEntry('划分标段', [
|
||||
{ label: '是', value: '1' },
|
||||
{ label: '否', value: '0' },
|
||||
]),
|
||||
|
||||
section_num: createEntry('标段数', [
|
||||
{ label: '1', value: '1' },
|
||||
{ label: '2', value: '2' },
|
||||
{ label: '3', value: '3' },
|
||||
{ label: '4', value: '4' },
|
||||
{ label: '5', value: '5' },
|
||||
{ label: '6', value: '6' },
|
||||
{ label: '7', value: '7' },
|
||||
{ label: '8', value: '8' },
|
||||
]),
|
||||
|
||||
common_whether: createEntry('常用是否', [
|
||||
{ label: '是', value: '1' },
|
||||
{ label: '否', value: '0' },
|
||||
]),
|
||||
|
||||
deadline_for_performance: createEntry('履行期限', [
|
||||
{ label: '确定', value: '1' },
|
||||
{ label: '不确定', value: '0' },
|
||||
]),
|
||||
|
||||
dispute_settlement_methods: createEntry('纠纷解决方式', [
|
||||
{ label: '诉讼', value: '1' },
|
||||
{ label: '仲裁', value: '2' },
|
||||
{ label: '其它', value: '3' },
|
||||
]),
|
||||
|
||||
payment_nature: createEntry('付款性质', [
|
||||
{ label: '结算款', value: '1' },
|
||||
{ label: '其它', value: '3' },
|
||||
]),
|
||||
|
||||
contract_approval_flow_node: createEntry('合同立项节点流程', [
|
||||
{ label: '开始节点', value: 'paStart' },
|
||||
{ label: '立项编制', value: 'paEdit' },
|
||||
{ label: '立项审批中', value: 'paApproval' },
|
||||
{ label: '选商编制', value: 'smEdit' },
|
||||
{ label: '选商审批中', value: 'smApproval' },
|
||||
{ label: '选商结果编制', value: 'smrEdit' },
|
||||
{ label: '结束', value: 'end' },
|
||||
]),
|
||||
|
||||
contract_business_flow_node: createEntry('合同选商节点流程', [
|
||||
{ label: '开始节点', value: 'smStart' },
|
||||
{ label: '待编制', value: 'smEdit' },
|
||||
{ label: '待部门自审', value: 'smDepartmentAudit' },
|
||||
{ label: '待计划规划部审查', value: 'smPlanningDepartment' },
|
||||
{ label: '待财务资产部审查', value: 'smFinancialDepartment' },
|
||||
{ label: '待合规审查(企管法规部)', value: 'smRegulationDepartment' },
|
||||
{ label: '待主管领导审批', value: 'smManager' },
|
||||
{ label: '待公司领导审核', value: 'smLeaders' },
|
||||
{ label: '选商结果填报', value: 'smrEdit' },
|
||||
{ label: '结束', value: 'end' },
|
||||
]),
|
||||
|
||||
contract_abolish_flow_node: createEntry('合同立项节点流程', [
|
||||
{ label: '待提交', value: 'edit' },
|
||||
{ label: '待部门审核', value: 'departmentAudit' },
|
||||
{ label: '已结束', value: 'end' },
|
||||
{ label: '废除', value: 'abolishEdit' },
|
||||
]),
|
||||
|
||||
// 授权类型
|
||||
contract_authorization_type2: createEntry('合同授权类型', [
|
||||
{ label: '长期授权', value: '0' },
|
||||
{ label: '单项授权', value: '1' },
|
||||
]),
|
||||
|
||||
// 授权期限
|
||||
contract_authorization_period: createEntry('合同授权期限', [
|
||||
{ label: '确定', value: '0' },
|
||||
{ label: '不确定', value: '1' },
|
||||
]),
|
||||
|
||||
// 合同待办类型
|
||||
contract_todo_type: createEntry('合同待办类型', [
|
||||
{ label: '合同立项', value: 'contractSetup' },
|
||||
{ label: '合同选商', value: 'selectMerchant' },
|
||||
{ label: '合同申报', value: 'contractDeclare' },
|
||||
{ label: '合同签订', value: 'contractSign' },
|
||||
{ label: '合同履行', value: 'contractPerform' },
|
||||
{ label: '合同归档', value: 'contractFile' },
|
||||
]),
|
||||
};
|
|
@ -1,101 +0,0 @@
|
|||
import { message, type UploadProps } from "ant-design-vue";
|
||||
import Apis from '#/api';
|
||||
|
||||
export class FileUploader {
|
||||
|
||||
|
||||
fileList = [] as UploadProps['fileList'];
|
||||
uploading = false;
|
||||
constructor(params: any) {
|
||||
|
||||
}
|
||||
|
||||
select = async (fileUuids: string) => {
|
||||
return new Promise<void>(async (resolve, reject) => {
|
||||
Apis.attachment.get_list({
|
||||
params: { uuid: fileUuids }
|
||||
}).then((data) => {
|
||||
let files = [] as UploadProps['fileList'];
|
||||
for (const element of data.rows) {
|
||||
files?.push({
|
||||
uid: element.fileUuid,
|
||||
name: element.fileName,
|
||||
status: 'done',
|
||||
url: element.fileUrl,
|
||||
})
|
||||
}
|
||||
resolve(files)
|
||||
}).catch(e => {
|
||||
reject()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
remove: UploadProps['onRemove'] = file => {
|
||||
if (this.fileList) {
|
||||
const index = this.fileList.indexOf(file);
|
||||
const newFileList = this.fileList.slice();
|
||||
newFileList.splice(index, 1);
|
||||
this.fileList = newFileList;
|
||||
}
|
||||
};
|
||||
|
||||
upload = async (files?: UploadProps['fileList'], data?: any) => {
|
||||
return new Promise<void>(async (resolve, reject) => {
|
||||
if (this.fileList) {
|
||||
const formData = new FormData();
|
||||
|
||||
if (data && Object.keys(data).length) {
|
||||
Object.keys(data).forEach((key) => {
|
||||
formData.append(key, data[key]);
|
||||
});
|
||||
}
|
||||
|
||||
let file = files ? files : this.fileList;
|
||||
let alreadyUploaded = [] as string[];
|
||||
file.forEach((file: UploadProps['fileList'][number]) => {
|
||||
if (file.originFileObj) {
|
||||
formData.append('files', file.originFileObj as any);
|
||||
} else {
|
||||
alreadyUploaded.push(file.uid)
|
||||
}
|
||||
});
|
||||
this.uploading = true;
|
||||
|
||||
// You can use any AJAX library you like
|
||||
try {
|
||||
|
||||
this.fileList = [];
|
||||
this.uploading = false;
|
||||
let files = []
|
||||
for (const element of alreadyUploaded) {
|
||||
files.push({
|
||||
fileUuid: element,
|
||||
})
|
||||
}
|
||||
|
||||
const filesCount = formData.getAll('files').length;
|
||||
if (filesCount > 0) {
|
||||
let data = await Apis.attachment.post_uploads({
|
||||
data: formData,
|
||||
})
|
||||
files = files.concat(data.rows)
|
||||
message.success('上传成功.');
|
||||
}
|
||||
resolve(files || [])
|
||||
|
||||
} catch (error) {
|
||||
this.uploading = false;
|
||||
reject()
|
||||
message.error('上传失败.');
|
||||
} finally {
|
||||
this.uploading = false;
|
||||
}
|
||||
|
||||
}
|
||||
reject()
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,220 +0,0 @@
|
|||
import { h, unref } from 'vue';
|
||||
import type { App, Component, Plugin } from 'vue';
|
||||
import { cloneDeep, isObject } from 'lodash-es';
|
||||
|
||||
|
||||
/** 递归组装菜单格式 */
|
||||
export function generatorMenu(routerMap: Array<any>) {
|
||||
return filterRouter(routerMap).map(item => {
|
||||
const isRoot = isRootRouter(item);
|
||||
const info = isRoot ? item.children[0] : item;
|
||||
const currentMenu = {
|
||||
...info,
|
||||
...info.meta,
|
||||
label: info.meta?.title,
|
||||
key: info.name,
|
||||
icon: isRoot ? item.meta?.icon : info.meta?.icon
|
||||
};
|
||||
// 是否有子菜单,并递归处理
|
||||
if (info.children && info.children.length > 0) {
|
||||
// Recursion
|
||||
currentMenu.children = generatorMenu(info.children);
|
||||
}
|
||||
return currentMenu;
|
||||
});
|
||||
}
|
||||
|
||||
/** 混合菜单 */
|
||||
export function generatorMenuMix(routerMap: Array<any>, routerName: string, location: string) {
|
||||
const cloneRouterMap = cloneDeep(routerMap);
|
||||
const newRouter = filterRouter(cloneRouterMap);
|
||||
if (location === 'header') {
|
||||
const firstRouter: any[] = [];
|
||||
newRouter.forEach(item => {
|
||||
const isRoot = isRootRouter(item);
|
||||
const info = isRoot ? item.children[0] : item;
|
||||
info.children = undefined;
|
||||
const currentMenu = {
|
||||
...info,
|
||||
...info.meta,
|
||||
label: info.meta?.title,
|
||||
key: info.name
|
||||
};
|
||||
firstRouter.push(currentMenu);
|
||||
});
|
||||
return firstRouter;
|
||||
}
|
||||
return getChildrenRouter(newRouter.filter(item => item.name === routerName));
|
||||
}
|
||||
|
||||
/** 递归组装子菜单 */
|
||||
export function getChildrenRouter(routerMap: Array<any>) {
|
||||
return filterRouter(routerMap).map(item => {
|
||||
const isRoot = isRootRouter(item);
|
||||
const info = isRoot ? item.children[0] : item;
|
||||
const currentMenu = {
|
||||
...info,
|
||||
...info.meta,
|
||||
label: info.meta?.title,
|
||||
key: info.name
|
||||
};
|
||||
// 是否有子菜单,并递归处理
|
||||
if (info.children && info.children.length > 0) {
|
||||
// Recursion
|
||||
currentMenu.children = getChildrenRouter(info.children);
|
||||
}
|
||||
return currentMenu;
|
||||
});
|
||||
}
|
||||
|
||||
/** 判断根路由 Router */
|
||||
export function isRootRouter(item) {
|
||||
return item.meta?.alwaysShow != true && item?.children?.filter(item => !item?.meta?.hidden)?.length === 1;
|
||||
}
|
||||
|
||||
export const withInstall = <T extends Component>(component: T, alias?: string) => {
|
||||
const comp = component as any;
|
||||
comp.install = (app: App) => {
|
||||
app.component(comp.name || comp.displayName, component);
|
||||
if (alias) {
|
||||
app.config.globalProperties[alias] = component;
|
||||
}
|
||||
};
|
||||
return component as T & Plugin;
|
||||
};
|
||||
|
||||
/** 找到对应的节点 */
|
||||
let result = null;
|
||||
export function getTreeItem(data: any[], key?: string | number): any {
|
||||
data.map(item => {
|
||||
if (item.key === key) {
|
||||
result = item;
|
||||
} else if (item.children && item.children.length) {
|
||||
getTreeItem(item.children, key);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/** 找到所有节点 */
|
||||
const treeAll: any[] = [];
|
||||
export function getTreeAll(data: any[]): any[] {
|
||||
data.map(item => {
|
||||
treeAll.push(item.key);
|
||||
if (item.children && item.children.length) {
|
||||
getTreeAll(item.children);
|
||||
}
|
||||
});
|
||||
return treeAll;
|
||||
}
|
||||
|
||||
// dynamic use hook props
|
||||
export function getDynamicProps<T extends {}, U>(props: T): Partial<U> {
|
||||
const ret: Recordable = {};
|
||||
|
||||
Object.keys(props).map(key => {
|
||||
ret[key] = unref((props as Recordable)[key]);
|
||||
});
|
||||
|
||||
return ret as Partial<U>;
|
||||
}
|
||||
|
||||
export function deepMerge<T = any>(src: any = {}, target: any = {}): T {
|
||||
let key: string;
|
||||
for (key in target) {
|
||||
src[key] = isObject(src[key]) ? deepMerge(src[key], target[key]) : (src[key] = target[key]);
|
||||
}
|
||||
return src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sums the passed percentage to the R, G or B of a HEX color
|
||||
*
|
||||
* @param {string} color The color to change
|
||||
* @param {number} amount The amount to change the color by
|
||||
* @returns {string} The processed part of the color
|
||||
*/
|
||||
function addLight(color: string, amount: number) {
|
||||
const cc = Number.parseInt(color, 16) + amount;
|
||||
const c = cc > 255 ? 255 : cc;
|
||||
return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lightens a 6 char HEX color according to the passed percentage
|
||||
*
|
||||
* @param {string} color The color to change
|
||||
* @param {number} amount The amount to change the color by
|
||||
* @returns {string} The processed color represented as HEX
|
||||
*/
|
||||
export function lighten(color: string, amount: number) {
|
||||
color = color.includes('#') ? color.substring(1, color.length) : color;
|
||||
amount = Math.trunc((255 * amount) / 100);
|
||||
return `#${addLight(color.substring(0, 2), amount)}${addLight(
|
||||
color.substring(2, 4),
|
||||
amount
|
||||
)}${addLight(color.substring(4, 6), amount)}`;
|
||||
}
|
||||
|
||||
/** 判断是否 url */
|
||||
export function isUrl(url: string) {
|
||||
return /^(http|https):\/\//g.test(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数组结构转树形结构
|
||||
*
|
||||
* @param {Array} arrayData 数据源
|
||||
* @param {Object} treeProps 树结构配置 { id:"_id", parent_id:"parent_id",
|
||||
* children:"children",need_field:["_id","name"],deleteParentId:true }
|
||||
* @returns {Array} treeData 树形结构
|
||||
*/
|
||||
export function arrayToTree(originalArrayData, treeProps) {
|
||||
const arrayData = cloneDeep(originalArrayData);
|
||||
let { id = '_id', parent_id = 'parent_id', children = 'children', deleteParentId = false, need_field } = treeProps;
|
||||
const result = [];
|
||||
const temp = {};
|
||||
for (let i = 0; i < arrayData.length; i++) {
|
||||
temp[arrayData[i][id]] = arrayData[i]; // 以id作为索引存储元素,可以无需遍历直接定位元素
|
||||
}
|
||||
for (let j = 0; j < arrayData.length; j++) {
|
||||
const currentElement = arrayData[j];
|
||||
const newCurrentElement = {};
|
||||
if (need_field) {
|
||||
need_field = uniqueArr(need_field.concat([id, parent_id, children]));
|
||||
for (const keyName in currentElement) {
|
||||
if (!need_field.includes(keyName)) {
|
||||
delete currentElement[keyName];
|
||||
}
|
||||
}
|
||||
}
|
||||
const tempCurrentElementParent = temp[currentElement[parent_id]]; // 临时变量里面的当前元素的父元素
|
||||
if (tempCurrentElementParent) {
|
||||
// 如果存在父元素
|
||||
if (!tempCurrentElementParent[children]) {
|
||||
// 如果父元素没有chindren键
|
||||
tempCurrentElementParent[children] = []; // 设上父元素的children键
|
||||
}
|
||||
if (deleteParentId) {
|
||||
delete currentElement[parent_id];
|
||||
}
|
||||
tempCurrentElementParent[children].push(currentElement); // 给父元素加上当前元素作为子元素
|
||||
} else {
|
||||
// 不存在父元素,意味着当前元素是一级元素
|
||||
result.push(currentElement);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// 最简单数组去重法
|
||||
export function uniqueArr(array) {
|
||||
const n = []; // 一个新的临时数组
|
||||
// 遍历当前数组
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
// 如果当前数组的第i已经保存进了临时数组,那么跳过,
|
||||
// 否则把当前项push到临时数组里面
|
||||
if (!n.includes(array[i])) n.push(array[i]);
|
||||
}
|
||||
return n;
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
export const logger = {
|
||||
log(level: string, message: any, error?: any) {
|
||||
const timestamp = new Date().toISOString();
|
||||
const stack = error ? error.stack : '';
|
||||
const formattedMessage = `[${timestamp}] [${level}] ${message} ${stack}`;
|
||||
switch (level) {
|
||||
case 'DEBUG': {
|
||||
console.debug(formattedMessage);
|
||||
break;
|
||||
}
|
||||
case 'ERROR':
|
||||
case 'FATAL': {
|
||||
console.error(formattedMessage);
|
||||
break;
|
||||
}
|
||||
case 'INFO': {
|
||||
console.info(formattedMessage);
|
||||
break;
|
||||
}
|
||||
case 'WARN': {
|
||||
console.warn(formattedMessage);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
console.log(formattedMessage);
|
||||
}
|
||||
}
|
||||
},
|
||||
debug(message: any) {
|
||||
this.log('DEBUG', message);
|
||||
},
|
||||
info(message: any) {
|
||||
this.log('INFO', message);
|
||||
},
|
||||
warn(message: any) {
|
||||
this.log('WARN', message);
|
||||
},
|
||||
error(message: any, error: any) {
|
||||
this.log('ERROR', message, error);
|
||||
},
|
||||
fatal(message: any, error: any) {
|
||||
this.log('FATAL', message, error);
|
||||
},
|
||||
};
|
|
@ -1,68 +0,0 @@
|
|||
import dayjs from 'dayjs';
|
||||
|
||||
/**
|
||||
* 通过传入年月获取对应月份的起止时间
|
||||
* @param dateStr YYYY-MM 的日期格式,如2024-06,不传默认当月
|
||||
*/
|
||||
export function getMonthStartAndEnd(dateStr?: string) {
|
||||
if (!dateStr) {
|
||||
dateStr = dayjs().format('YYYY-MM');
|
||||
}
|
||||
|
||||
// 验证输入格式是否正确
|
||||
const regex = /^\d{4}-\d{2}$/;
|
||||
if (!regex.test(dateStr)) {
|
||||
throw new Error('日期字符串格式不正确,应为 YYYY-MM');
|
||||
}
|
||||
|
||||
// 使用 split 方法分割字符串
|
||||
const [year, month] = dateStr.split('-').map(Number);
|
||||
|
||||
// 获取指定月份的第一天
|
||||
const firstDayOfMonth = dayjs(new Date(year, month - 1, 1))
|
||||
.startOf('month')
|
||||
.format('YYYY-MM-DD');
|
||||
|
||||
// 获取指定月份的最后一天
|
||||
const lastDayOfMonth = dayjs(new Date(year, month - 1, 1))
|
||||
.endOf('month')
|
||||
.format('YYYY-MM-DD');
|
||||
|
||||
return [firstDayOfMonth, lastDayOfMonth];
|
||||
}
|
||||
|
||||
export function shortcuts(params?: any) {
|
||||
return {
|
||||
当前月: () => {
|
||||
const now = dayjs().valueOf();
|
||||
return [
|
||||
dayjs(now).startOf('month').valueOf(),
|
||||
dayjs(now).endOf('month').valueOf(),
|
||||
] as const;
|
||||
},
|
||||
最近一周: () => {
|
||||
const now = dayjs().valueOf();
|
||||
return [dayjs(now).subtract(7, 'day').valueOf(), now] as const;
|
||||
},
|
||||
最近一个月: () => {
|
||||
const now = dayjs().valueOf();
|
||||
return [dayjs(now).subtract(1, 'month').valueOf(), now] as const;
|
||||
},
|
||||
最近三个月: () => {
|
||||
const now = dayjs().valueOf();
|
||||
return [dayjs(now).subtract(3, 'month').valueOf(), now] as const;
|
||||
},
|
||||
最近半年: () => {
|
||||
const now = dayjs().valueOf();
|
||||
return [dayjs(now).subtract(6, 'month').valueOf(), now] as const;
|
||||
},
|
||||
最近一年: () => {
|
||||
const now = dayjs().valueOf();
|
||||
return [dayjs(now).subtract(1, 'year').valueOf(), now] as const;
|
||||
},
|
||||
当前年: () => {
|
||||
const now = dayjs().valueOf();
|
||||
return [dayjs(now).startOf('year').valueOf(), now] as const;
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
# \_core
|
||||
|
||||
此目录包含应用程序正常运行所需的基本视图。这些视图是应用程序布局中使用的视图。
|
|
@ -1,9 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import { About } from '@vben/common-ui';
|
||||
|
||||
defineOptions({ name: 'About' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<About />
|
||||
</template>
|
|
@ -1,30 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import type { LoginCodeParams } from '@vben/common-ui';
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { AuthenticationCodeLogin } from '@vben/common-ui';
|
||||
import { LOGIN_PATH } from '@vben/constants';
|
||||
|
||||
defineOptions({ name: 'CodeLogin' });
|
||||
|
||||
const loading = ref(false);
|
||||
|
||||
/**
|
||||
* 异步处理登录操作
|
||||
* Asynchronously handle the login process
|
||||
* @param values 登录表单数据
|
||||
*/
|
||||
async function handleLogin(values: LoginCodeParams) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(values);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthenticationCodeLogin
|
||||
:loading="loading"
|
||||
:login-path="LOGIN_PATH"
|
||||
@submit="handleLogin"
|
||||
/>
|
||||
</template>
|
|
@ -1,23 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { AuthenticationForgetPassword } from '@vben/common-ui';
|
||||
import { LOGIN_PATH } from '@vben/constants';
|
||||
|
||||
defineOptions({ name: 'ForgetPassword' });
|
||||
|
||||
const loading = ref(false);
|
||||
|
||||
function handleSubmit(value: string) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('reset email:', value);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthenticationForgetPassword
|
||||
:loading="loading"
|
||||
:login-path="LOGIN_PATH"
|
||||
@submit="handleSubmit"
|
||||
/>
|
||||
</template>
|
|
@ -1,101 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import type { VbenFormSchema } from '@vben/common-ui';
|
||||
import type { BasicOption } from '@vben/types';
|
||||
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { AuthenticationLogin, z } from '@vben/common-ui';
|
||||
import { $t } from '@vben/locales';
|
||||
|
||||
import { useAuthStore } from '#/store';
|
||||
|
||||
defineOptions({ name: 'Login' });
|
||||
|
||||
const authStore = useAuthStore();
|
||||
|
||||
const MOCK_USER_OPTIONS: BasicOption[] = [
|
||||
{
|
||||
label: '超级管理员',
|
||||
value: 'vben',
|
||||
},
|
||||
{
|
||||
label: '管理员',
|
||||
value: 'admin',
|
||||
},
|
||||
{
|
||||
label: '用户',
|
||||
value: 'jack',
|
||||
},
|
||||
];
|
||||
|
||||
const formSchema = computed((): VbenFormSchema[] => {
|
||||
return [
|
||||
{
|
||||
component: 'VbenInput',
|
||||
componentProps: {
|
||||
class: 'w-full',
|
||||
placeholder: $t('authentication.usernameTip'),
|
||||
},
|
||||
dependencies: {
|
||||
trigger(values, form) {
|
||||
if (values.selectAccount) {
|
||||
const findUser = MOCK_USER_OPTIONS.find(
|
||||
(item) => item.value === values.selectAccount,
|
||||
);
|
||||
if (findUser) {
|
||||
form.setValues({
|
||||
password: '123456',
|
||||
username: findUser.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
triggerFields: ['selectAccount'],
|
||||
},
|
||||
fieldName: 'username',
|
||||
label: $t('authentication.username'),
|
||||
rules: z.string().min(1, { message: $t('authentication.usernameTip') }),
|
||||
},
|
||||
{
|
||||
component: 'VbenInputPassword',
|
||||
componentProps: {
|
||||
placeholder: $t('authentication.password'),
|
||||
},
|
||||
fieldName: 'password',
|
||||
label: $t('authentication.password'),
|
||||
rules: z.string().min(1, { message: $t('authentication.passwordTip') }),
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const isDev = import.meta.env.MODE === 'development';
|
||||
function mockLogin(username: string, password: string, isSkip: boolean = true) {
|
||||
authStore.authLogin({
|
||||
username,
|
||||
password,
|
||||
_isSkip: isSkip,
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-[90%]">
|
||||
<AuthenticationLogin
|
||||
:form-schema="formSchema"
|
||||
:loading="authStore.loginLoading"
|
||||
@submit="authStore.authLogin"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="isDev">
|
||||
<p class="text-center">快速登录</p>
|
||||
<a-space>
|
||||
<a-button @click="mockLogin('Admin.itl', 'ABC123')">超级管理员</a-button>
|
||||
<a-button @click="mockLogin('zhangxs.itl', 'Rlgs!6243910')">zxs</a-button>
|
||||
<a-button @click="mockLogin('zengp.itl', 'Rlgs!6243910')">zp</a-button>
|
||||
<a-button @click="mockLogin('rlqym', 'Rlgs!6243910', false)">
|
||||
rlqym
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
</template>
|
|
@ -1,10 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import { AuthenticationQrCodeLogin } from '@vben/common-ui';
|
||||
import { LOGIN_PATH } from '@vben/constants';
|
||||
|
||||
defineOptions({ name: 'QrCodeLogin' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthenticationQrCodeLogin :login-path="LOGIN_PATH" />
|
||||
</template>
|
|
@ -1,25 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import type { LoginAndRegisterParams } from '@vben/common-ui';
|
||||
|
||||
import { ref } from 'vue';
|
||||
|
||||
import { AuthenticationRegister } from '@vben/common-ui';
|
||||
import { LOGIN_PATH } from '@vben/constants';
|
||||
|
||||
defineOptions({ name: 'Register' });
|
||||
|
||||
const loading = ref(false);
|
||||
|
||||
function handleSubmit(value: LoginAndRegisterParams) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('register submit:', value);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthenticationRegister
|
||||
:loading="loading"
|
||||
:login-path="LOGIN_PATH"
|
||||
@submit="handleSubmit"
|
||||
/>
|
||||
</template>
|
|
@ -1,7 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import { Fallback } from '@vben/common-ui';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Fallback status="coming-soon" />
|
||||
</template>
|
|
@ -1,9 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import { Fallback } from '@vben/common-ui';
|
||||
|
||||
defineOptions({ name: 'Fallback403Demo' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Fallback status="403" />
|
||||
</template>
|
|
@ -1,9 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import { Fallback } from '@vben/common-ui';
|
||||
|
||||
defineOptions({ name: 'Fallback500Demo' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Fallback status="500" />
|
||||
</template>
|
|
@ -1,9 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import { Fallback } from '@vben/common-ui';
|
||||
|
||||
defineOptions({ name: 'Fallback404Demo' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Fallback status="404" />
|
||||
</template>
|
|
@ -1,9 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import { Fallback } from '@vben/common-ui';
|
||||
|
||||
defineOptions({ name: 'FallbackOfflineDemo' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Fallback status="offline" />
|
||||
</template>
|
|
@ -1,186 +0,0 @@
|
|||
import { dict } from '@fast-crud/fast-crud';
|
||||
|
||||
import { DICT_TYPE, getDictObj, getDictOptions } from '#/utils/dict';
|
||||
import { filterContractTypes } from '#/views/contract/utils';
|
||||
|
||||
export function getFormSchema(params: any = {}) {
|
||||
const { contractTypeData, readOnly = false } = params;
|
||||
|
||||
return {
|
||||
contractName: {
|
||||
title: '合同名称',
|
||||
key: 'contractName',
|
||||
col: { span: 24 },
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
allowClear: false,
|
||||
disabled: readOnly,
|
||||
},
|
||||
rules: [{ required: true, message: '请输入合同名称' }],
|
||||
},
|
||||
ctrType: {
|
||||
title: '合同类别',
|
||||
key: 'ctrType',
|
||||
col: { span: 12 },
|
||||
component: {
|
||||
name: 'fs-dict-select',
|
||||
vModel: 'value',
|
||||
class: 'min-w-[200px]',
|
||||
prototype: true,
|
||||
dict: dict({
|
||||
async getData(_context) {
|
||||
return filterContractTypes(contractTypeData, '-1');
|
||||
},
|
||||
}),
|
||||
disabled: readOnly,
|
||||
},
|
||||
valueChange: {
|
||||
immediate: true, // 是否立即执行一次
|
||||
handle({ form, value, getComponentRef }) {
|
||||
form.ctrTwoType = undefined;
|
||||
console.log(getComponentRef('ctrTwoType'));
|
||||
getComponentRef('ctrTwoType').reloadDict(); // 执行city的select组件的reloadDict()方法,触发“city”重新加载字典
|
||||
},
|
||||
},
|
||||
rules: [{ required: true, message: '请选择合同类别' }],
|
||||
},
|
||||
ctrTwoType: {
|
||||
title: '二级类别',
|
||||
key: 'ctrTwoType',
|
||||
col: { span: 12 },
|
||||
component: {
|
||||
name: 'fs-dict-select',
|
||||
vModel: 'value',
|
||||
class: 'min-w-[200px]',
|
||||
prototype: true,
|
||||
dict: dict({
|
||||
async getData({ form = {} }) {
|
||||
console.log(form);
|
||||
return filterContractTypes(contractTypeData, form.ctrType);
|
||||
},
|
||||
}),
|
||||
disabled: readOnly,
|
||||
},
|
||||
rules: [{ required: true, message: '请选择二级类别' }],
|
||||
},
|
||||
frameProtocol: {
|
||||
title: '框架协议',
|
||||
key: 'frameProtocol',
|
||||
col: { span: 8 },
|
||||
component: {
|
||||
name: 'fs-dict-radio',
|
||||
vModel: 'value',
|
||||
dict: dict({
|
||||
data: getDictOptions(DICT_TYPE.common_whether),
|
||||
}),
|
||||
disabled: readOnly,
|
||||
},
|
||||
rules: [{ required: true, message: '请选择框架协议' }],
|
||||
},
|
||||
frameProtocolCtr: {
|
||||
title: '框架协议下的合同',
|
||||
key: 'frameProtocolCtr',
|
||||
col: { span: 12 },
|
||||
labelCol: { style: { width: '200px' } },
|
||||
component: {
|
||||
name: 'fs-dict-radio',
|
||||
vModel: 'value',
|
||||
dict: dict({
|
||||
data: getDictOptions(DICT_TYPE.common_whether),
|
||||
}),
|
||||
disabled: readOnly,
|
||||
},
|
||||
rules: [{ required: true, message: '请选择框架协议下的合同' }],
|
||||
},
|
||||
fundAllocation: {
|
||||
title: '资金流向',
|
||||
key: 'fundAllocation',
|
||||
col: { span: 12 },
|
||||
component: {
|
||||
name: 'fs-dict-select',
|
||||
vModel: 'value',
|
||||
allowClear: false,
|
||||
class: 'min-w-[200px]',
|
||||
dict: dict({
|
||||
data: getDictOptions(DICT_TYPE.contract_fund_flow),
|
||||
}),
|
||||
disabled: readOnly,
|
||||
},
|
||||
valueChange: {
|
||||
immediate: true, // 是否立即执行一次
|
||||
handle({ form }) {
|
||||
form.fundAllocationName = getDictObj(
|
||||
DICT_TYPE.contract_fund_flow,
|
||||
form.fundAllocation,
|
||||
)?.label;
|
||||
},
|
||||
},
|
||||
rules: [{ required: true, message: '请选择资金流向' }],
|
||||
},
|
||||
fundDitch: {
|
||||
title: '资金渠道',
|
||||
key: 'fundDitch',
|
||||
col: { span: 12 },
|
||||
component: {
|
||||
name: 'fs-dict-select',
|
||||
vModel: 'value',
|
||||
allowClear: false,
|
||||
class: 'min-w-[200px]',
|
||||
dict: dict({
|
||||
data: getDictOptions(DICT_TYPE.contract_funding_source),
|
||||
}),
|
||||
disabled: readOnly,
|
||||
},
|
||||
rules: [{ required: true, message: '请选择资金渠道' }],
|
||||
},
|
||||
budgetSum: {
|
||||
title: '预算金额',
|
||||
key: 'budgetSum',
|
||||
col: { span: 8 },
|
||||
colon: false,
|
||||
component: {
|
||||
name: 'a-input-number',
|
||||
vModel: 'value',
|
||||
class: 'w-full',
|
||||
min: 0,
|
||||
disabled: readOnly,
|
||||
},
|
||||
},
|
||||
priceType: {
|
||||
title: '',
|
||||
key: 'priceType',
|
||||
col: { span: 6 },
|
||||
labelCol: { style: { width: '12px' } },
|
||||
colon: false,
|
||||
component: {
|
||||
name: 'fs-dict-select',
|
||||
vModel: 'value',
|
||||
dict: dict({
|
||||
data: getDictOptions(DICT_TYPE.contract_currency_unit),
|
||||
}),
|
||||
disabled: readOnly,
|
||||
},
|
||||
},
|
||||
organiza: {
|
||||
title: '组织形式',
|
||||
key: 'organiza',
|
||||
col: { span: 24 },
|
||||
component: {
|
||||
name: 'fs-dict-radio',
|
||||
vModel: 'value',
|
||||
allowClear: false,
|
||||
class: 'min-w-[180px]',
|
||||
dict: dict({
|
||||
data: getDictOptions(DICT_TYPE.contract_organization_form, 'number'),
|
||||
}),
|
||||
disabled: readOnly,
|
||||
},
|
||||
rules: [{ required: true, message: '请选择组织形式' }],
|
||||
},
|
||||
fileList: {
|
||||
title: '相关附件',
|
||||
key: 'fileList',
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,829 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, nextTick, onMounted, reactive, ref } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
import { Page, useVbenModal } from '@vben/common-ui';
|
||||
import { MdiAdd, MdiUpload } from '@vben/icons';
|
||||
import { useUserStore } from '@vben/stores';
|
||||
|
||||
import { message, Modal, type UploadChangeParam } from 'ant-design-vue';
|
||||
import { logger } from 'common-utils';
|
||||
|
||||
import Apis from '#/api';
|
||||
import temporaryFormModal from '#/components/temporary-form-modal/temporary-form-modal.vue';
|
||||
import { useVxeTable } from '#/hooks/vxeTable';
|
||||
import { DICT_TYPE, getDictObj } from '#/utils/dict';
|
||||
import { FileUploader } from '#/utils/file';
|
||||
import AuditNodeTable from '#/views/contract/components/audit-node-table/audit-node-table.vue';
|
||||
import chooseUserModal from '#/views/system/user/choose-user-modal.vue';
|
||||
|
||||
import chooseSigningBasisModal from '../signing-basis/choose-signing-basis-modal.vue';
|
||||
import { getColumns } from '../signing-basis/columns';
|
||||
import { getFormSchema } from './curd';
|
||||
|
||||
const { xGridRef, gridProps } = useVxeTable({ ref: 'xGridRef' });
|
||||
|
||||
const [ChooseUserModal, chooseUserModalApi] = useVbenModal({
|
||||
connectedComponent: chooseUserModal,
|
||||
});
|
||||
|
||||
const [ChooseSigningBasisModal, chooseSigningBasisModalApi] = useVbenModal({
|
||||
connectedComponent: chooseSigningBasisModal,
|
||||
});
|
||||
|
||||
const [TemporaryFormModal, temporaryFormModalApi] = useVbenModal({
|
||||
connectedComponent: temporaryFormModal,
|
||||
});
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
const userInfo = computed(() => userStore.userInfo);
|
||||
|
||||
const fileUploader = new FileUploader({});
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const id = ref(route.params.id);
|
||||
const taskId = route.query.taskId;
|
||||
const auditId = ref();
|
||||
const pageRef = ref();
|
||||
|
||||
const currData = ref<any>({});
|
||||
|
||||
const formRef = ref();
|
||||
|
||||
const isLoading = ref(false);
|
||||
|
||||
const contractTypeData = ref<any[]>([]);
|
||||
|
||||
const formBinding = ref({
|
||||
col: { span: 24 },
|
||||
initialForm: {
|
||||
contractName: '',
|
||||
frameProtocol: '0',
|
||||
frameProtocolCtr: '0',
|
||||
priceType: 'CNY',
|
||||
},
|
||||
labelCol: { style: { width: '120px' } },
|
||||
columns: {},
|
||||
});
|
||||
|
||||
/** Hooks - 表格 */
|
||||
const gridOptions = reactive(
|
||||
gridProps({
|
||||
height: '200px',
|
||||
columns: getColumns(),
|
||||
data: [],
|
||||
toolbarConfig: {
|
||||
enabled: false,
|
||||
},
|
||||
pagerConfig: {
|
||||
enabled: false,
|
||||
},
|
||||
rowConfig: {
|
||||
useKey: true,
|
||||
isCurrent: false,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const collapses = ['1', '2', '3'];
|
||||
const collapseActiveKey = ref(collapses);
|
||||
function areArraysEqualUnordered(arr1, arr2) {
|
||||
if (arr1.length !== arr2.length) return false;
|
||||
const sortedArr1 = [...arr1].sort();
|
||||
const sortedArr2 = [...arr2].sort();
|
||||
return JSON.stringify(sortedArr1) === JSON.stringify(sortedArr2);
|
||||
}
|
||||
const isFold = computed(() => {
|
||||
return !areArraysEqualUnordered(collapses, collapseActiveKey.value);
|
||||
});
|
||||
function handleFold() {
|
||||
collapseActiveKey.value = isFold.value ? collapses : [];
|
||||
}
|
||||
|
||||
function handleBack() {
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: `是否确认返回上一页面?`,
|
||||
onOk: async () => {
|
||||
back();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面返回并关闭tab
|
||||
*/
|
||||
function back() {
|
||||
router.replace('/contract/approval/todo');
|
||||
}
|
||||
|
||||
function handleOpenSignBasisChooseModal() {
|
||||
// 判断有没有签约依据
|
||||
const tableFullData = xGridRef.value?.getTableData().fullData;
|
||||
if (tableFullData && tableFullData.length > 0) {
|
||||
chooseSigningBasisModalApi.setData({
|
||||
title: '选择签约依据',
|
||||
guids: tableFullData.map((item) => item.guid) || [],
|
||||
});
|
||||
} else {
|
||||
chooseSigningBasisModalApi.setData({
|
||||
title: '选择签约依据',
|
||||
guids: [],
|
||||
});
|
||||
}
|
||||
|
||||
chooseSigningBasisModalApi.open();
|
||||
}
|
||||
|
||||
const handleChange = (info: UploadChangeParam) => {
|
||||
formRef.value.setFormData({
|
||||
fileList: info.fileList.length > 0 ? info.fileList : [],
|
||||
});
|
||||
};
|
||||
|
||||
function removeRow(row) {
|
||||
const $grid = xGridRef.value;
|
||||
if ($grid) {
|
||||
$grid.remove(row);
|
||||
message.success('移除成功');
|
||||
}
|
||||
}
|
||||
|
||||
const userModalOpenType = ref<'abolish' | 'audit'>('audit');
|
||||
const currAuditType = ref<'abolish' | 'audit'>('audit');
|
||||
|
||||
const userListByAbolish = ref([]);
|
||||
|
||||
async function handleAbolish(type: 'confirm' | 'openModal') {
|
||||
userModalOpenType.value = 'abolish';
|
||||
if (type === 'openModal') {
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '是否确认作废该合同?确认后该合同无法再次使用',
|
||||
okType: 'danger',
|
||||
onOk: async () => {
|
||||
chooseUserModalApi.setData({
|
||||
title: '选择立项废除审批人',
|
||||
userIds: [],
|
||||
});
|
||||
chooseUserModalApi.open();
|
||||
},
|
||||
});
|
||||
}
|
||||
if (type === 'confirm') {
|
||||
const hideLoading = message.loading('提交中...', 0);
|
||||
try {
|
||||
await Apis.contractBaseInfo.post_abolishFlowStart({
|
||||
data: {
|
||||
guid: currData.value.guid,
|
||||
assigneeList: userListByAbolish.value.map((item) => item.ACCOUNT_ID),
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('立项废除提交失败', error);
|
||||
} finally {
|
||||
hideLoading();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function handleAbolishAudit(
|
||||
type: 'access' | 'accessConfirm' | 'reject' | 'rejectConfirm',
|
||||
data?: any,
|
||||
) {
|
||||
console.log(type);
|
||||
|
||||
if (type === 'access') {
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '是否确认立项废除审核通过?',
|
||||
onOk: () => {
|
||||
temporaryFormModalApi.setData({
|
||||
title: '备注信息',
|
||||
schema: {
|
||||
columns: {
|
||||
comment: {
|
||||
title: '',
|
||||
key: 'comment',
|
||||
col: { span: 24 },
|
||||
colon: false,
|
||||
component: {
|
||||
name: 'a-textarea',
|
||||
vModel: 'value',
|
||||
autoSize: { minRows: 4, maxRows: 6 },
|
||||
placeholder: '请输入',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入退回原因' }],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
temporaryFormModalApi.open();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (type === 'accessConfirm') {
|
||||
try {
|
||||
await Apis.contractBaseInfo.post_abolishSubmit({
|
||||
params: {
|
||||
guid: id.value,
|
||||
},
|
||||
data: {
|
||||
// appId: id.value,
|
||||
taskId,
|
||||
nodeId: '',
|
||||
comment: '通过',
|
||||
},
|
||||
});
|
||||
message.success('审核通过');
|
||||
back();
|
||||
} catch (error) {
|
||||
logger.error('审核通过失败', error);
|
||||
message.error('审核通过失败,请稍候再试');
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'reject') {
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '是否确认拒绝废除该立项?',
|
||||
onOk: () => {
|
||||
temporaryFormModalApi.setData({
|
||||
title: '退回原因',
|
||||
schema: {
|
||||
columns: {
|
||||
comment: {
|
||||
title: '',
|
||||
key: 'comment',
|
||||
col: { span: 24 },
|
||||
colon: false,
|
||||
component: {
|
||||
name: 'a-textarea',
|
||||
vModel: 'value',
|
||||
autoSize: { minRows: 4, maxRows: 6 },
|
||||
placeholder: '请输入',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入退回原因' }],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
temporaryFormModalApi.open();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (type === 'rejectConfirm') {
|
||||
const comment = data.comment;
|
||||
try {
|
||||
await Apis.contractBaseInfo.post_rollback({
|
||||
params: {
|
||||
guid: id.value,
|
||||
},
|
||||
data: {
|
||||
appId: id.value,
|
||||
taskId,
|
||||
nodeId: '',
|
||||
comment,
|
||||
},
|
||||
});
|
||||
temporaryFormModalApi.close();
|
||||
message.success('退回成功');
|
||||
back();
|
||||
} catch (error) {
|
||||
logger.error('合同立项退回失败', error);
|
||||
message.error('退回失败,请稍候再试');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleDelete() {
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '是否确认删除该条记录?',
|
||||
okType: 'danger',
|
||||
onOk: async () => {
|
||||
await Apis.contractBaseInfo.post_deletes({
|
||||
params: { ids: currData.value.guid },
|
||||
});
|
||||
message.success('删除成功');
|
||||
back();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function loadDataByContractTypeData() {}
|
||||
|
||||
function handleChooseConfirm(rows) {
|
||||
const $grid = xGridRef.value;
|
||||
// 判断上一个新增项有无完成,未完成则不允许新增
|
||||
if ($grid) {
|
||||
$grid.remove();
|
||||
$grid.insert(rows);
|
||||
} else {
|
||||
console.error('xGridRef不存在');
|
||||
}
|
||||
}
|
||||
|
||||
async function handleChooseUserConfirm(e) {
|
||||
chooseUserModalApi.close();
|
||||
isLoading.value = true;
|
||||
if (userModalOpenType.value === 'abolish') {
|
||||
userListByAbolish.value = e;
|
||||
handleAbolish('confirm');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await Apis.contractBaseInfo.post_applyFlowStart({
|
||||
data: {
|
||||
guid: id.value,
|
||||
assigneeList: e.map((item) => item.ACCOUNT_ID),
|
||||
},
|
||||
});
|
||||
message.success('提交成功');
|
||||
back();
|
||||
} catch (error) {
|
||||
logger.error('合同立项提交失败', error);
|
||||
message.error('提交失败,请稍候再试');
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSave() {
|
||||
try {
|
||||
await formRef.value.submit();
|
||||
} catch {
|
||||
message.error('请完成必填项的填写');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
isLoading.value = true;
|
||||
|
||||
let newForm: any = {};
|
||||
|
||||
// 判断有没有签约依据
|
||||
const tableFullData = xGridRef.value?.getTableData().fullData;
|
||||
if (tableFullData && tableFullData.length > 0) {
|
||||
newForm.basisId = tableFullData[0].basisId;
|
||||
} else {
|
||||
message.error('请选择签约依据');
|
||||
return;
|
||||
}
|
||||
|
||||
// 会议附件
|
||||
const fileList = formRef.value.form.fileList;
|
||||
let files: any = [];
|
||||
if (fileList && fileList.length > 0) {
|
||||
files = await fileUploader.upload(fileList, { source: 'ht' });
|
||||
}
|
||||
if (files) {
|
||||
newForm.fileUuid = (files.map((item) => item.fileUuid) || []).join(',');
|
||||
}
|
||||
|
||||
newForm = Object.assign({}, formRef.value.form, newForm);
|
||||
|
||||
delete newForm.fileList;
|
||||
|
||||
// 获取字典数据的name值
|
||||
for (const item of contractTypeData.value) {
|
||||
if (item.contrLevelId === newForm.ctrType) {
|
||||
newForm.ctrTypeName = item.contrLevelName;
|
||||
}
|
||||
if (item.contrLevelId === newForm.ctrTwoType) {
|
||||
newForm.ctrTwoTypeName = item.contrLevelName;
|
||||
}
|
||||
}
|
||||
|
||||
newForm.fundDitchName = getDictObj(
|
||||
DICT_TYPE.contract_funding_source,
|
||||
newForm.fundDitch,
|
||||
)?.label;
|
||||
|
||||
newForm.priceTypeName = getDictObj(
|
||||
DICT_TYPE.contract_currency_unit,
|
||||
newForm.priceType,
|
||||
)?.label;
|
||||
|
||||
newForm.contractMoney = newForm.budgetSum;
|
||||
newForm.currentContStepId = 0;
|
||||
|
||||
console.log(newForm);
|
||||
|
||||
// let result = await Apis.contractBaseInfo.post_apply({ data: newForm });
|
||||
|
||||
let result: any = {};
|
||||
|
||||
result = await Apis.contractBaseInfo.post_apply({ data: newForm });
|
||||
|
||||
id.value = result.value;
|
||||
auditId.value = result.value;
|
||||
|
||||
message.success('保存成功');
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '保存成功!是否进行提交?',
|
||||
onOk: () => {
|
||||
handleSubmit();
|
||||
},
|
||||
onCancel: () => {
|
||||
// back();
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
message.error('提交失败,请稍候再试');
|
||||
logger.error('立项结果报错失败', error);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
// 如果有 flowinstanceid 则不弹出选择审批人,表明是退回的单据又提交了
|
||||
if (currData.value.flowInstanceId) {
|
||||
auditType.value = 'access';
|
||||
handleAudit('confirm');
|
||||
return;
|
||||
}
|
||||
userModalOpenType.value = 'audit';
|
||||
// isLoading.value = true
|
||||
chooseUserModalApi.setData({
|
||||
title: '选择审批人',
|
||||
userIds: [],
|
||||
});
|
||||
chooseUserModalApi.open();
|
||||
}
|
||||
|
||||
let auditType = ref('');
|
||||
const isTemporaryFormModalLoading = ref(false);
|
||||
|
||||
async function handleAudit(
|
||||
type: 'confirm' | 'openAccessModal' | 'openRejectModal',
|
||||
data?: any,
|
||||
) {
|
||||
console.log(type);
|
||||
|
||||
if (type === 'openAccessModal') {
|
||||
auditType.value = 'access';
|
||||
temporaryFormModalApi.setData({
|
||||
title: '审核通过备注',
|
||||
schema: {
|
||||
columns: {
|
||||
comment: {
|
||||
title: '',
|
||||
key: 'comment',
|
||||
col: { span: 24 },
|
||||
colon: false,
|
||||
component: {
|
||||
name: 'a-textarea',
|
||||
vModel: 'value',
|
||||
autoSize: { minRows: 4, maxRows: 6 },
|
||||
placeholder: '请输入',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
temporaryFormModalApi.open();
|
||||
}
|
||||
|
||||
if (type === 'confirm' && auditType.value === 'access') {
|
||||
isTemporaryFormModalLoading.value = true;
|
||||
const comment = data.comment;
|
||||
|
||||
try {
|
||||
await Apis.contractBaseInfo.post_submit({
|
||||
params: {
|
||||
guid: id.value,
|
||||
},
|
||||
data: {
|
||||
appId: id.value,
|
||||
taskId,
|
||||
nodeId: '',
|
||||
comment: comment || '',
|
||||
},
|
||||
});
|
||||
message.success('审核通过');
|
||||
temporaryFormModalApi.close();
|
||||
back();
|
||||
} catch (error) {
|
||||
logger.error('审核通过失败', error);
|
||||
message.error('审核通过失败,请稍候再试');
|
||||
} finally {
|
||||
isTemporaryFormModalLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'openRejectModal') {
|
||||
auditType.value = 'reject';
|
||||
|
||||
temporaryFormModalApi.setData({
|
||||
title: '审核退回原因',
|
||||
schema: {
|
||||
columns: {
|
||||
comment: {
|
||||
title: '',
|
||||
key: 'comment',
|
||||
col: { span: 24 },
|
||||
colon: false,
|
||||
component: {
|
||||
name: 'a-textarea',
|
||||
vModel: 'value',
|
||||
autoSize: { minRows: 4, maxRows: 6 },
|
||||
placeholder: '请输入',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入退回原因' }],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
temporaryFormModalApi.open();
|
||||
}
|
||||
|
||||
if (type === 'confirm' && auditType.value === 'reject') {
|
||||
isTemporaryFormModalLoading.value = true;
|
||||
|
||||
const comment = data.comment;
|
||||
try {
|
||||
await Apis.contractBaseInfo.post_rollback({
|
||||
params: {
|
||||
guid: id.value,
|
||||
},
|
||||
data: {
|
||||
appId: id.value,
|
||||
taskId,
|
||||
nodeId: '',
|
||||
comment,
|
||||
},
|
||||
});
|
||||
temporaryFormModalApi.close();
|
||||
message.success('退回成功');
|
||||
back();
|
||||
} catch (error) {
|
||||
logger.error('合同立项退回失败', error);
|
||||
message.error('退回失败,请稍候再试');
|
||||
} finally {
|
||||
isTemporaryFormModalLoading.value = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
isLoading.value = true;
|
||||
|
||||
try {
|
||||
const contractReferTypeData: any = await Apis.contractReferType.get_list({
|
||||
params: {},
|
||||
});
|
||||
contractTypeData.value = contractReferTypeData.rows || [];
|
||||
|
||||
if (id.value) {
|
||||
const data: any = await Apis.contractBaseInfo.get_getOne({
|
||||
params: { guid: id.value },
|
||||
});
|
||||
|
||||
auditId.value = id.value;
|
||||
currData.value = data || {};
|
||||
|
||||
formBinding.value.columns = getFormSchema({
|
||||
contractTypeData: contractTypeData.value,
|
||||
readOnly: !id.value || currData.value.step !== 'paEdit',
|
||||
});
|
||||
|
||||
xGridRef.value!.reloadColumn(
|
||||
getColumns({
|
||||
readOnly: !id.value || currData.value.step !== 'paEdit',
|
||||
}),
|
||||
);
|
||||
|
||||
nextTick(() => {
|
||||
console.log(formRef.value);
|
||||
formRef.value.setFormData(data);
|
||||
});
|
||||
|
||||
// 如果有签约依据
|
||||
if (data.basisId) {
|
||||
const basisList = await Apis.lxBasisSale.get_page({
|
||||
params: { basisId: data.basisId },
|
||||
});
|
||||
nextTick(() => {
|
||||
xGridRef.value!.insert(basisList.rows);
|
||||
});
|
||||
}
|
||||
|
||||
if (data.fileUuid) {
|
||||
const files = await fileUploader.select(data.fileUuid);
|
||||
nextTick(() => {
|
||||
formRef.value.setFormData({
|
||||
fileList: files,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
loadDataByContractTypeData();
|
||||
} else {
|
||||
formBinding.value.columns = getFormSchema({
|
||||
contractTypeData: contractTypeData.value,
|
||||
readOnly: false,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('获取合同信息失败', error);
|
||||
|
||||
Modal.error({
|
||||
title: '提示',
|
||||
content: '当前合同信息不存在',
|
||||
onOk() {
|
||||
back();
|
||||
},
|
||||
});
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page ref="pageRef" content-class="h-full flex flex-col">
|
||||
<ChooseUserModal
|
||||
class="w-[950px]"
|
||||
multiple
|
||||
@confirm="handleChooseUserConfirm"
|
||||
/>
|
||||
|
||||
<ChooseSigningBasisModal class="w-[950px]" @confirm="handleChooseConfirm" />
|
||||
|
||||
<TemporaryFormModal
|
||||
v-model:loading="isTemporaryFormModalLoading"
|
||||
class="w-[700px]"
|
||||
@confirm="handleAudit('confirm', $event)"
|
||||
/>
|
||||
|
||||
<!-- {{ currData.step }} -->
|
||||
<a-affix
|
||||
:offset-top="0"
|
||||
:style="{ zIndex: 50 }"
|
||||
:target="() => pageRef.bodyRef"
|
||||
>
|
||||
<div class="flex w-full flex-row bg-white pl-1 pt-1">
|
||||
<a-space class="flex-1">
|
||||
<vben-button
|
||||
v-if="!id || ['paEdit'].includes(currData.step) || !taskId"
|
||||
variant="primary"
|
||||
@click="handleSave()"
|
||||
>
|
||||
保存
|
||||
</vben-button>
|
||||
<vben-button
|
||||
v-if="!id || ['paEdit'].includes(currData.step) || !taskId"
|
||||
:disabled="!auditId"
|
||||
variant="primary"
|
||||
@click="handleSubmit()"
|
||||
>
|
||||
提交
|
||||
</vben-button>
|
||||
|
||||
<vben-button
|
||||
v-if="['paApproval'].includes(currData.step) && taskId"
|
||||
:disabled="!auditId"
|
||||
variant="primary"
|
||||
@click="handleAudit('openAccessModal')"
|
||||
>
|
||||
通过
|
||||
</vben-button>
|
||||
<vben-button
|
||||
v-if="['paApproval'].includes(currData.step) && taskId"
|
||||
:disabled="!auditId"
|
||||
variant="destructive"
|
||||
@click="handleAudit('openRejectModal')"
|
||||
>
|
||||
退回
|
||||
</vben-button>
|
||||
<!-- <vben-button
|
||||
v-if="
|
||||
id &&
|
||||
!['edit', 'setupDepartmentAudit'].includes(currData.step) &&
|
||||
currData.inputUserId === userInfo!.userId
|
||||
"
|
||||
variant="destructive"
|
||||
@click="handleAbolish('openModal')"
|
||||
>
|
||||
废除
|
||||
</vben-button> -->
|
||||
<vben-button
|
||||
v-if="id && ['paEdit'].includes(currData.step)"
|
||||
variant="destructive"
|
||||
@click="handleDelete()"
|
||||
>
|
||||
删除
|
||||
</vben-button>
|
||||
|
||||
<!-- <vben-button
|
||||
v-if="['abolishDepartmentAudit'].includes(currData.step) && taskId"
|
||||
:disabled="!auditId"
|
||||
variant="warning"
|
||||
@click="handleAbolishAudit('accessConfirm')"
|
||||
>
|
||||
废除通过
|
||||
</vben-button> -->
|
||||
|
||||
<!-- <vben-button
|
||||
v-if="['abolishDepartmentAudit'].includes(currData.step) && taskId"
|
||||
:disabled="!auditId"
|
||||
variant="destructive"
|
||||
@click="handleAbolishAudit('accessConfirm')"
|
||||
>
|
||||
废除拒绝
|
||||
</vben-button>
|
||||
|
||||
<vben-button
|
||||
v-if="['departmentAudit'].includes(currData.step) && taskId"
|
||||
:disabled="!auditId"
|
||||
variant="primary"
|
||||
@click="handleAudit('accessConfirm')"
|
||||
>
|
||||
通过
|
||||
</vben-button> -->
|
||||
<vben-button variant="secondary" @click="handleBack()">
|
||||
返回
|
||||
</vben-button>
|
||||
</a-space>
|
||||
|
||||
<vben-button variant="secondary" @click="handleFold()">
|
||||
一键{{ isFold ? '展开' : '收起' }}
|
||||
</vben-button>
|
||||
</div>
|
||||
</a-affix>
|
||||
|
||||
<a-spin :spinning="isLoading">
|
||||
<div class="mx-auto overflow-auto py-2">
|
||||
<a-collapse v-model:active-key="collapseActiveKey" :bordered="false">
|
||||
<a-collapse-panel key="1" class="w-full" header="基本信息">
|
||||
<fs-form ref="formRef" class="w-full" v-bind="formBinding">
|
||||
<template #form_fileList="scope">
|
||||
<a-upload
|
||||
v-model:file-list="scope.form.fileList"
|
||||
:before-upload="() => false"
|
||||
:max-count="3"
|
||||
accept=".pdf,.ppt,.pptx"
|
||||
name="file"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-button v-if="!id || currData.step === 'edit'">
|
||||
<MdiUpload />
|
||||
点击上传
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
</fs-form>
|
||||
</a-collapse-panel>
|
||||
|
||||
<a-collapse-panel key="2" class="w-full" header="签约依据">
|
||||
<template #extra>
|
||||
<a-button
|
||||
v-if="!id || currData.step === 'edit'"
|
||||
type="primary"
|
||||
@click.stop="handleOpenSignBasisChooseModal()"
|
||||
>
|
||||
<MdiAdd class="mr-0.5 text-lg" />
|
||||
选择签约依据
|
||||
</a-button>
|
||||
</template>
|
||||
|
||||
<VxeGrid ref="xGridRef" v-bind="gridOptions" class="">
|
||||
<template #toolbar_buttons></template>
|
||||
<template #operate="{ row }">
|
||||
<a-space>
|
||||
<a-button
|
||||
v-if="!id || currData.step === 'edit'"
|
||||
class="text-red-500"
|
||||
size="small"
|
||||
type="text"
|
||||
@click="removeRow(row)"
|
||||
>
|
||||
移除
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</VxeGrid>
|
||||
</a-collapse-panel>
|
||||
|
||||
<a-collapse-panel
|
||||
v-if="currData.flowInstanceId"
|
||||
key="3"
|
||||
class="w-full"
|
||||
header="审批信息"
|
||||
>
|
||||
<AuditNodeTable :flow-instance-id="currData.flowInstanceId" />
|
||||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
</div>
|
||||
</a-spin>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
|
@ -1,205 +0,0 @@
|
|||
import type { VxeGridPropTypes } from 'vxe-table';
|
||||
|
||||
import { dict } from '@fast-crud/fast-crud';
|
||||
|
||||
import { useRender } from '#/hooks/useRender';
|
||||
import { DICT_TYPE, getDictOptions } from '#/utils/dict';
|
||||
import { getContractTypes } from '#/views/contract/utils';
|
||||
|
||||
export const PrimaryKey = 'guid';
|
||||
|
||||
export function getColumns(_params: any = {}): VxeGridPropTypes.Columns {
|
||||
return [
|
||||
{
|
||||
type: 'radio',
|
||||
width: 40,
|
||||
slots: { radio: 'radio_cell' },
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
field: 'step',
|
||||
title: '节点状态',
|
||||
width: 130,
|
||||
slots: {
|
||||
default: ({ row }) => {
|
||||
return useRender.renderDict(
|
||||
row.step,
|
||||
DICT_TYPE.contract_approval_flow_node,
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'contractName',
|
||||
title: '合同名称',
|
||||
minWidth: 200,
|
||||
slots: {
|
||||
default: ({ row }) => {
|
||||
return useRender.renderMultiLineText(row.contractName);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'reportNo',
|
||||
title: '报审序号',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
field: 'ctrTypeName',
|
||||
title: '合同类别',
|
||||
width: 200,
|
||||
slots: {
|
||||
default: ({ row }) => {
|
||||
return useRender.renderText(
|
||||
row.ctrTypeName,
|
||||
`-${row.ctrTwoTypeName}`,
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
{ field: 'budgetSum', title: '预算金额', width: 100 },
|
||||
{ field: 'priceTypeName', title: '币种', width: 100 },
|
||||
{
|
||||
field: 'organiza',
|
||||
title: '组织形式',
|
||||
width: 120,
|
||||
slots: {
|
||||
default: ({ row }) => {
|
||||
return useRender.renderDict(
|
||||
row.organiza,
|
||||
DICT_TYPE.contract_organization_form,
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'fundAllocation',
|
||||
title: '资金流向',
|
||||
width: 100,
|
||||
slots: {
|
||||
default: ({ row }) => {
|
||||
return useRender.renderDict(
|
||||
row.fundAllocation,
|
||||
DICT_TYPE.contract_fund_flow,
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
{ field: 'createTime', title: '申报时间', width: 130 },
|
||||
{ field: 'inputPerson', title: '承办人', width: 100 },
|
||||
{ field: 'inputDepartName', title: '承办部门', width: 100 },
|
||||
{ field: 'inputDate', title: '承办时间', width: 130 },
|
||||
{
|
||||
field: 'operate',
|
||||
title: '操作',
|
||||
width: 60,
|
||||
fixed: 'right',
|
||||
slots: { default: 'operate' },
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function getFormSchema(_params: any = {}) {
|
||||
return {
|
||||
initialForm: {},
|
||||
columns: {
|
||||
contractName: {
|
||||
title: '合同名称',
|
||||
key: 'contractName',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
},
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
organiza: {
|
||||
title: '组织形式',
|
||||
key: 'organiza',
|
||||
component: {
|
||||
name: 'fs-dict-select',
|
||||
vModel: 'value',
|
||||
class: 'min-w-[180px]',
|
||||
allowClear: true,
|
||||
dict: dict({
|
||||
data: getDictOptions(DICT_TYPE.contract_organization_form),
|
||||
}),
|
||||
},
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
price: {
|
||||
title: '预算金额',
|
||||
key: 'price',
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
render({ form }) {
|
||||
return (
|
||||
<div class="flex">
|
||||
<a-form-item class="!mb-0 inline-block">
|
||||
<a-input-number
|
||||
placeholder=""
|
||||
v-model:value={form.budgetSum1}
|
||||
/>
|
||||
</a-form-item>
|
||||
<span class="mx-1">至</span>
|
||||
<a-form-item class="!mb-0 inline-block">
|
||||
<a-input-number
|
||||
placeholder=""
|
||||
v-model:value={form.budgetSum2}
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
time: {
|
||||
title: '申报时间',
|
||||
key: 'time',
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
render({ form }) {
|
||||
// 注意此处的v-model写法
|
||||
return (
|
||||
<div class="flex">
|
||||
<a-form-item class="!mb-0 inline-block">
|
||||
<a-date-picker
|
||||
format="YYYY-MM-DD"
|
||||
placeholder=""
|
||||
v-model:value={form.startDate}
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</a-form-item>
|
||||
<span class="mx-1">至</span>
|
||||
<a-form-item class="!mb-0 inline-block">
|
||||
<a-date-picker
|
||||
format="YYYY-MM-DD"
|
||||
placeholder=""
|
||||
v-model:value={form.endDate}
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
ctrType: {
|
||||
title: '合同类别',
|
||||
key: 'ctrType',
|
||||
show: true,
|
||||
component: {
|
||||
name: 'fs-dict-select',
|
||||
vModel: 'value',
|
||||
class: 'min-w-[200px]',
|
||||
dict: dict({
|
||||
async getData(_context) {
|
||||
return await getContractTypes('-1');
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,215 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
import { Page } from "@vben/common-ui";
|
||||
import {
|
||||
MdiAdd,
|
||||
MdiDelete,
|
||||
MdiExport,
|
||||
MdiRadioChecked,
|
||||
MdiRadioUnchecked,
|
||||
MdiUpdate,
|
||||
} from "@vben/icons";
|
||||
|
||||
import { message, Modal } from "ant-design-vue";
|
||||
|
||||
import Apis from "#/api";
|
||||
import { useVxeTable } from "#/hooks/vxeTable";
|
||||
import { toDetailPage } from "#/views/contract/utils.ts";
|
||||
|
||||
import { getColumns, getFormSchema, PrimaryKey } from "./crud.tsx";
|
||||
|
||||
const router = useRouter();
|
||||
const searchRef = ref();
|
||||
|
||||
const { xGridRef, triggerProxy, gridProps } = useVxeTable({ ref: "xGridRef" });
|
||||
|
||||
const searchFormBinding = ref({
|
||||
...getFormSchema(),
|
||||
onSearch(_context: any) {
|
||||
triggerProxy("reload");
|
||||
},
|
||||
});
|
||||
|
||||
/** Hooks - 表格 */
|
||||
const gridOptions = reactive(
|
||||
gridProps({
|
||||
columns: getColumns(),
|
||||
proxyConfig: {
|
||||
autoLoad: false,
|
||||
ajax: {
|
||||
query: async ({ page }) => {
|
||||
const data = await Apis.contractBaseInfo.get_page({
|
||||
params: {
|
||||
pageNum: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...searchRef.value?.formData,
|
||||
},
|
||||
});
|
||||
return data;
|
||||
},
|
||||
},
|
||||
},
|
||||
pagerConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
toolbarConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
function handleEdit(record?: any) {
|
||||
if (record && record[PrimaryKey]) {
|
||||
router.push(`/contract/approval/edit/${record[PrimaryKey]}`);
|
||||
} else {
|
||||
router.push("/contract/approval/edit");
|
||||
}
|
||||
}
|
||||
|
||||
function handleDelete(row) {
|
||||
Modal.confirm({
|
||||
title: "提示",
|
||||
content: "是否确认删除该条记录?",
|
||||
okType: "danger",
|
||||
onOk: async () => {
|
||||
await Apis.contractBaseInfo.post_deletes({
|
||||
params: { ids: row[PrimaryKey] },
|
||||
});
|
||||
message.success("删除成功");
|
||||
triggerProxy("reload");
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function handleExport() {
|
||||
const $grid = xGridRef.value;
|
||||
if ($grid) {
|
||||
$grid.exportData({
|
||||
type: "xlsx",
|
||||
columnFilterMethod: ({ column }) => {
|
||||
if (["operate", "step"].includes(column.field)) {
|
||||
return false;
|
||||
}
|
||||
if (column.type === "radio") {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
});
|
||||
message.success("导出成功");
|
||||
}
|
||||
}
|
||||
|
||||
/** 选中数据 */
|
||||
const selectRow: any = computed(() => {
|
||||
return xGridRef.value?.getRadioRecord() || null;
|
||||
});
|
||||
|
||||
/** 单选框选中事件 */
|
||||
const setSelectRow = (row: any) => {
|
||||
if (selectRow.value && selectRow.value[PrimaryKey] === row[PrimaryKey]) {
|
||||
xGridRef.value?.clearRadioRow();
|
||||
} else {
|
||||
xGridRef.value?.setRadioRow(row);
|
||||
}
|
||||
};
|
||||
|
||||
/** 表格单元格单击事件 */
|
||||
function handleCellClick({ row }) {
|
||||
setSelectRow(row);
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
triggerProxy("reload");
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page content-class="h-full flex flex-col">
|
||||
<fs-search ref="searchRef" v-bind="searchFormBinding">
|
||||
<template #form_price="{ row }">
|
||||
<a-input-number v-model:value="row.budgetSum1" placeholder="" />
|
||||
<span class="mx-1">至</span>
|
||||
<a-input-number v-model:value="row.budgetSum2" placeholder="" />
|
||||
</template>
|
||||
<template #form_time="{ row }">
|
||||
<a-date-picker
|
||||
v-model:value="row.startTime"
|
||||
format="YYYY-MM-DD"
|
||||
placeholder=""
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
<span class="mx-1">至</span>
|
||||
<a-date-picker
|
||||
v-model:value="row.endTime"
|
||||
format="YYYY-MM-DD"
|
||||
placeholder=""
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</template>
|
||||
</fs-search>
|
||||
|
||||
<div class="min-h-300px flex-1">
|
||||
<vxe-grid ref="xGridRef" v-bind="gridOptions" @cell-click="handleCellClick">
|
||||
<template #toolbar_buttons>
|
||||
<a-space>
|
||||
<vben-button variant="primary" @click="handleEdit()">
|
||||
<MdiAdd class="mr-0.5 text-lg" />
|
||||
新增
|
||||
</vben-button>
|
||||
<vben-button
|
||||
:disabled="
|
||||
!selectRow ||
|
||||
!selectRow[PrimaryKey] ||
|
||||
!['paEdit'].includes(selectRow.step)
|
||||
"
|
||||
variant="warning"
|
||||
@click="handleEdit(selectRow)"
|
||||
>
|
||||
<MdiUpdate class="mr-0.5 text-lg" />
|
||||
信息维护
|
||||
</vben-button>
|
||||
<vben-button variant="primary" @click="handleExport()">
|
||||
<MdiExport class="mr-0.5 text-lg" />
|
||||
导出
|
||||
</vben-button>
|
||||
<vben-button
|
||||
:disabled="
|
||||
!selectRow ||
|
||||
!selectRow[PrimaryKey] ||
|
||||
!['paEdit'].includes(selectRow.step)
|
||||
"
|
||||
variant="destructive"
|
||||
@click="handleDelete(selectRow)"
|
||||
>
|
||||
<MdiDelete class="mr-0.5 text-lg" />
|
||||
删除
|
||||
</vben-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<template #radio_cell="{ row, checked }">
|
||||
<span class="text-base" @click.stop="setSelectRow(row)">
|
||||
<MdiRadioChecked v-if="checked" />
|
||||
<MdiRadioUnchecked v-else />
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template #operate="{ row }">
|
||||
<a-button
|
||||
class="text-primary"
|
||||
size="small"
|
||||
type="text"
|
||||
@click="toDetailPage('approval', row.guid)"
|
||||
>
|
||||
查看
|
||||
</a-button>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</div>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<style></style>
|
|
@ -1,204 +0,0 @@
|
|||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import Apis from '#/api';
|
||||
import { useVxeTable } from '#/hooks/vxeTable';
|
||||
|
||||
import { getColumns, getFormSchema } from './crud';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
multiple?: boolean;
|
||||
showDepartment?: boolean;
|
||||
}>(),
|
||||
{
|
||||
multiple: true,
|
||||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'confirm', row: any[]): any[];
|
||||
(e: 'rowClick', row: any): any;
|
||||
}>();
|
||||
|
||||
const isConfirmLoading = ref(false);
|
||||
|
||||
const [messageApi] = message.useMessage();
|
||||
|
||||
const { xGridRef, triggerProxy, gridProps } = useVxeTable({ ref: 'xGridRef' });
|
||||
|
||||
const searchRef = ref();
|
||||
|
||||
const data = ref({
|
||||
userIds: [],
|
||||
});
|
||||
|
||||
const checkRecords = ref([]);
|
||||
|
||||
const searchBinding = ref({
|
||||
...getFormSchema(),
|
||||
onSearch(context: any) {
|
||||
triggerProxy('reload');
|
||||
},
|
||||
});
|
||||
|
||||
/** Hooks - 表格 */
|
||||
const gridOptions = reactive(
|
||||
gridProps({
|
||||
height: '400px',
|
||||
columns: getColumns({ type: 'choose' }),
|
||||
pagerConfig: { size: 'mini' },
|
||||
proxyConfig: {
|
||||
autoLoad: true,
|
||||
ajax: {
|
||||
query: ({ page }) => {
|
||||
return Apis.lxBasisSale.get_page({
|
||||
params: {
|
||||
pageNum: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...searchRef.value.formData,
|
||||
},
|
||||
});
|
||||
},
|
||||
querySuccess() {
|
||||
for (const row of checkRecords.value) {
|
||||
xGridRef.value!.setCheckboxRow(row, true);
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
rowConfig: {
|
||||
keyField: 'basisId',
|
||||
},
|
||||
checkboxConfig: {
|
||||
labelField: 'basisId',
|
||||
// 取消显示全选头部按钮
|
||||
showHeader: false,
|
||||
highlight: true,
|
||||
range: false,
|
||||
// 保留勾选状态
|
||||
reserve: true,
|
||||
checkMethod: ({ row }) => {
|
||||
const checkRecordIds =
|
||||
checkRecords.value.map((item) => item.guid) || [];
|
||||
if (
|
||||
checkRecords.value.length === 0 ||
|
||||
checkRecordIds.includes(row.guid)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
/**
|
||||
* 单元行点击事件
|
||||
*/
|
||||
function handleCellClick({ row }) {
|
||||
console.log(row);
|
||||
emit('rowClick', row);
|
||||
}
|
||||
|
||||
/**
|
||||
* 复选框选中事件
|
||||
* @param e
|
||||
*/
|
||||
function handleCheckboxChange(e) {
|
||||
const currRows = xGridRef.value?.getCheckboxRecords() || [];
|
||||
const otherRows = xGridRef.value?.getCheckboxReserveRecords() || [];
|
||||
const allRows = [...currRows, ...otherRows];
|
||||
|
||||
if (e.checked) {
|
||||
const existingIds = new Set(checkRecords.value.map((item) => item.guid));
|
||||
|
||||
if (!existingIds.has(e.row.ACCOUNT_ID)) {
|
||||
checkRecords.value = [...checkRecords.value, e.row];
|
||||
}
|
||||
} else {
|
||||
handleCloseTag(e.row);
|
||||
}
|
||||
|
||||
console.log('[ checkRecords.value ] >', checkRecords.value);
|
||||
if (allRows.length > 0) {
|
||||
messageApi.warning('最多只能选择1条数据');
|
||||
}
|
||||
}
|
||||
|
||||
function handleCloseTag(row) {
|
||||
checkRecords.value = checkRecords.value.filter(
|
||||
(item) => item.guid != row.guid,
|
||||
);
|
||||
xGridRef.value?.setCheckboxRow(row, false);
|
||||
}
|
||||
|
||||
const title = ref('选择办公用品');
|
||||
|
||||
const [BaseModal, baseModalApi] = useVbenModal({
|
||||
onOpenChange(isOpen: boolean) {
|
||||
if (isOpen) {
|
||||
isConfirmLoading.value = false;
|
||||
data.value = baseModalApi.getData<Record<string, any>>() || {};
|
||||
if (data.value.title) {
|
||||
title.value = data.value.title;
|
||||
}
|
||||
console.log(data.value.userIds);
|
||||
const rows: any = [];
|
||||
for (const element of checkRecords.value) {
|
||||
if (data.value.guids.includes(element.guid)) {
|
||||
rows.push(element);
|
||||
}
|
||||
}
|
||||
checkRecords.value = rows;
|
||||
}
|
||||
},
|
||||
onConfirm() {
|
||||
console.info('onConfirm');
|
||||
emit('confirm', checkRecords.value);
|
||||
baseModalApi.close();
|
||||
},
|
||||
onCancel() {
|
||||
baseModalApi.close();
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<BaseModal
|
||||
:confirm-loading="isConfirmLoading"
|
||||
:loading="isConfirmLoading"
|
||||
:title="title"
|
||||
>
|
||||
<div v-if="props.multiple" class="py-12px flex flex-row">
|
||||
<span class="mr-12px block">已选择:</span>
|
||||
<div class="flex flex-1 flex-row">
|
||||
<a-space>
|
||||
<a-tag
|
||||
v-for="(item, index) in checkRecords"
|
||||
:key="index"
|
||||
closable
|
||||
@close="handleCloseTag(item)"
|
||||
>
|
||||
{{ item.basisName }}
|
||||
</a-tag>
|
||||
</a-space>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex h-full flex-col">
|
||||
<fs-search ref="searchRef" v-bind="searchBinding" />
|
||||
<div class="min-h-300px flex-1">
|
||||
<VxeGrid
|
||||
ref="xGridRef"
|
||||
class="h-420px"
|
||||
v-bind="gridOptions"
|
||||
@cell-click="handleCellClick"
|
||||
@checkbox-change="handleCheckboxChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</BaseModal>
|
||||
</template>
|
|
@ -1,49 +0,0 @@
|
|||
import type { VxeGridPropTypes } from 'vxe-table';
|
||||
|
||||
import { useRender } from '#/hooks/useRender';
|
||||
import { DICT_TYPE, getDictObj } from '#/utils/dict';
|
||||
|
||||
export function getColumns(params?): VxeGridPropTypes.Columns {
|
||||
const { readOnly = false } = params || {};
|
||||
|
||||
const columns: VxeGridPropTypes.Columns = [
|
||||
{ type: 'seq', title: '序号', width: 60 },
|
||||
{ field: 'basisId', title: '依据号', width: 130 },
|
||||
{
|
||||
field: 'basisName',
|
||||
title: '依据名称',
|
||||
width: 200,
|
||||
},
|
||||
{ field: 'basisNum', title: '依据编号', width: 180 },
|
||||
{
|
||||
field: 'basisTypeId',
|
||||
title: '依据类型',
|
||||
width: 100,
|
||||
slots: {
|
||||
default: ({ row }) => {
|
||||
return getDictObj(DICT_TYPE.contract_basis_type, row.basisTypeId)
|
||||
?.label;
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'endDate',
|
||||
title: '有效期',
|
||||
width: 150,
|
||||
slots: {
|
||||
default: ({ row }) => {
|
||||
return useRender.renderDate(row.endDate, 'YYYY-MM-DD');
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
if (!readOnly) {
|
||||
columns.push({
|
||||
title: '操作',
|
||||
width: 120,
|
||||
slots: { default: 'operate' },
|
||||
});
|
||||
}
|
||||
return columns;
|
||||
}
|
|
@ -1,176 +0,0 @@
|
|||
import type { VxeGridPropTypes } from 'vxe-table';
|
||||
|
||||
import { dict } from '@fast-crud/fast-crud';
|
||||
|
||||
import { useRender } from '#/hooks/useRender';
|
||||
import { DICT_TYPE, getDictObj, getDictOptions } from '#/utils/dict';
|
||||
|
||||
export const PrimaryKey = 'guid';
|
||||
export function getColumns(params: any = {}): VxeGridPropTypes.Columns {
|
||||
const columns: VxeGridPropTypes.Columns = [];
|
||||
|
||||
if (params.type === 'choose') {
|
||||
return [
|
||||
{ field: 'basisId', title: '依据号', type: 'checkbox', width: 160 },
|
||||
{
|
||||
field: 'basisName',
|
||||
title: '依据名称',
|
||||
width: 200,
|
||||
},
|
||||
{ field: 'basisNum', title: '依据编号', width: 180 },
|
||||
{
|
||||
field: 'basisTypeId',
|
||||
title: '依据类型',
|
||||
width: 100,
|
||||
slots: {
|
||||
default: ({ row }) => {
|
||||
return (
|
||||
getDictObj(DICT_TYPE.contract_basis_type, row.basisTypeId)
|
||||
?.label || ''
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'endDate',
|
||||
title: '有效期',
|
||||
width: 150,
|
||||
slots: {
|
||||
default: ({ row }) => {
|
||||
return useRender.renderDate(row.endDate, 'YYYY-MM-DD');
|
||||
},
|
||||
},
|
||||
},
|
||||
{ field: 'inputPerson', title: '创建人', width: 150 },
|
||||
{
|
||||
field: 'inputDate',
|
||||
title: '创建时间',
|
||||
width: 150,
|
||||
slots: {
|
||||
default: ({ row }) => {
|
||||
return useRender.renderDate(row.inputDate, 'YYYY-MM-DD');
|
||||
},
|
||||
},
|
||||
},
|
||||
{ field: 'remark', title: '备注', minWidth: 200 },
|
||||
];
|
||||
}
|
||||
return [
|
||||
{ field: 'basisId', title: '依据号', width: 130 },
|
||||
{
|
||||
field: 'basisName',
|
||||
title: '依据名称',
|
||||
width: 200,
|
||||
},
|
||||
{ field: 'basisNum', title: '依据编号', width: 180 },
|
||||
{
|
||||
field: 'basisTypeId',
|
||||
title: '依据类型',
|
||||
width: 100,
|
||||
slots: {
|
||||
default: ({ row }) => {
|
||||
return (
|
||||
getDictObj(DICT_TYPE.contract_basis_type, row.basisTypeId)?.label ||
|
||||
''
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'endDate',
|
||||
title: '有效期',
|
||||
width: 150,
|
||||
slots: {
|
||||
default: ({ row }) => {
|
||||
return useRender.renderDate(row.endDate, 'YYYY-MM-DD');
|
||||
},
|
||||
},
|
||||
},
|
||||
{ field: 'inputPerson', title: '创建人', width: 150 },
|
||||
{
|
||||
field: 'inputDate',
|
||||
title: '创建时间',
|
||||
width: 150,
|
||||
slots: {
|
||||
default: ({ row }) => {
|
||||
return useRender.renderDate(row.inputDate, 'YYYY-MM-DD');
|
||||
},
|
||||
},
|
||||
},
|
||||
{ field: 'remark', title: '备注', minWidth: 200 },
|
||||
];
|
||||
|
||||
return columns;
|
||||
}
|
||||
|
||||
export function getFormSchema(_params: any = {}) {
|
||||
return {
|
||||
initialForm: {},
|
||||
columns: {
|
||||
basisName: {
|
||||
title: '依据名称',
|
||||
key: 'basisName',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
},
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
basisNum: {
|
||||
title: '依据编号',
|
||||
key: 'basisNum',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
},
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
basisTypeId: {
|
||||
title: '依据类型',
|
||||
key: 'basisTypeId',
|
||||
component: {
|
||||
name: 'fs-dict-select',
|
||||
vModel: 'value',
|
||||
class: 'min-w-[180px]',
|
||||
allowClear: true,
|
||||
dict: dict({
|
||||
async getData(_form) {
|
||||
return getDictOptions(DICT_TYPE.contract_basis_type);
|
||||
},
|
||||
}),
|
||||
},
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
inputPerson: {
|
||||
title: '创建人',
|
||||
key: 'inputPerson',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
},
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
inputDate: {
|
||||
title: '创建年份',
|
||||
key: 'inputDate',
|
||||
component: {
|
||||
name: 'a-date-picker',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
picker: 'year',
|
||||
format: 'YYYY年',
|
||||
valueFormat: 'YYYY',
|
||||
},
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,173 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
|
||||
import { Page, useVbenModal } from '@vben/common-ui';
|
||||
import {
|
||||
MdiAdd,
|
||||
MdiDelete,
|
||||
MdiExport,
|
||||
MdiRadioChecked,
|
||||
MdiRadioUnchecked,
|
||||
MdiUpdate,
|
||||
} from '@vben/icons';
|
||||
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
|
||||
import Apis from '#/api';
|
||||
import { useVxeTable } from '#/hooks/vxeTable';
|
||||
|
||||
import { getColumns, getFormSchema, PrimaryKey } from './crud.tsx';
|
||||
import signingBasisEditModal from './signing-basis-edit-modal.vue';
|
||||
|
||||
const [EditModal, editModalApi] = useVbenModal({
|
||||
connectedComponent: signingBasisEditModal,
|
||||
});
|
||||
|
||||
const searchRef = ref();
|
||||
|
||||
const { xGridRef, triggerProxy, gridProps } = useVxeTable({ ref: 'xGridRef' });
|
||||
|
||||
/** Hooks - 表格 */
|
||||
const gridOptions = reactive(
|
||||
gridProps({
|
||||
columns: getColumns(),
|
||||
proxyConfig: {
|
||||
autoLoad: false,
|
||||
ajax: {
|
||||
query: ({ page }) => {
|
||||
return Apis.lxBasisSale.get_page({
|
||||
params: {
|
||||
pageNum: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...searchRef.value?.formData,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
pagerConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
toolbarConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
function handleEdit(record?: any) {
|
||||
editModalApi.setData({
|
||||
isUpdate: Boolean(record && record[PrimaryKey]),
|
||||
record: JSON.parse(JSON.stringify(record || {})),
|
||||
});
|
||||
editModalApi.open();
|
||||
}
|
||||
|
||||
function handleDelete(row) {
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '是否确认删除该条记录?',
|
||||
okType: 'danger',
|
||||
onOk: async () => {
|
||||
await Apis.lxBasisSale.post_deletes({ params: { ids: row.guid } });
|
||||
message.success('删除成功');
|
||||
triggerProxy('reload');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function handleExport() {
|
||||
const $grid = xGridRef.value;
|
||||
if ($grid) {
|
||||
$grid.exportData({
|
||||
type: 'xlsx',
|
||||
});
|
||||
message.success('导出成功');
|
||||
}
|
||||
}
|
||||
|
||||
/** 选中数据 */
|
||||
const selectRow: any = computed(() => {
|
||||
return xGridRef.value?.getRadioRecord() || null;
|
||||
});
|
||||
|
||||
/** 单选框选中事件 */
|
||||
const setSelectRow = (row: any) => {
|
||||
if (selectRow.value && selectRow.value.guid === row.guid) {
|
||||
xGridRef.value?.clearRadioRow();
|
||||
} else {
|
||||
xGridRef.value?.setRadioRow(row);
|
||||
}
|
||||
};
|
||||
|
||||
/** 表格单元格单击事件 */
|
||||
function handleCellClick({ row }) {
|
||||
setSelectRow(row);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
triggerProxy('reload');
|
||||
});
|
||||
|
||||
const searchForm = ref({
|
||||
...getFormSchema(),
|
||||
onSearch(_context: any) {
|
||||
triggerProxy('reload');
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page content-class="h-full flex flex-col">
|
||||
<EditModal
|
||||
class="w-[600px] max-w-[80vw]"
|
||||
@success="triggerProxy('reload')"
|
||||
/>
|
||||
|
||||
<fs-search ref="searchRef" v-bind="searchForm" />
|
||||
<div class="min-h-300px flex-1">
|
||||
<vxe-grid
|
||||
ref="xGridRef"
|
||||
v-bind="gridOptions"
|
||||
@cell-click="handleCellClick"
|
||||
>
|
||||
<template #toolbar_buttons>
|
||||
<a-space>
|
||||
<vben-button variant="primary" @click="handleEdit()">
|
||||
<MdiAdd class="mr-0.5 text-lg" />
|
||||
新增
|
||||
</vben-button>
|
||||
<vben-button
|
||||
:disabled="!selectRow || !selectRow.guid"
|
||||
variant="warning"
|
||||
@click="handleEdit(selectRow)"
|
||||
>
|
||||
<MdiUpdate class="mr-0.5 text-lg" />
|
||||
修改
|
||||
</vben-button>
|
||||
<vben-button variant="primary" @click="handleExport()">
|
||||
<MdiExport class="mr-0.5 text-lg" />
|
||||
导出
|
||||
</vben-button>
|
||||
<vben-button
|
||||
:disabled="!selectRow || !selectRow.guid"
|
||||
variant="destructive"
|
||||
@click="handleDelete(selectRow)"
|
||||
>
|
||||
<MdiDelete class="mr-0.5 text-lg" />
|
||||
删除
|
||||
</vben-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<template #radio_cell="{ row, checked }">
|
||||
<span class="text-base" @click.stop="setSelectRow(row)">
|
||||
<MdiRadioChecked v-if="checked" />
|
||||
<MdiRadioUnchecked v-else />
|
||||
</span>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</div>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<style></style>
|
|
@ -1,199 +0,0 @@
|
|||
<script lang="tsx" setup>
|
||||
import { nextTick, ref } from 'vue';
|
||||
|
||||
import { useVbenModal } from '@vben/common-ui';
|
||||
import { MdiCloudUpload } from '@vben/icons';
|
||||
|
||||
import { dict } from '@fast-crud/fast-crud';
|
||||
import { message, type UploadChangeParam } from 'ant-design-vue';
|
||||
import dayjs, { Dayjs } from 'dayjs';
|
||||
|
||||
import Apis from '#/api';
|
||||
import { DICT_TYPE, getDictObj, getDictOptions } from '#/utils/dict';
|
||||
import { FileUploader } from '#/utils/file';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'success'): void;
|
||||
}>();
|
||||
|
||||
const fileUploader = new FileUploader({});
|
||||
|
||||
const data = ref({
|
||||
isUpdate: false,
|
||||
record: {} as any,
|
||||
});
|
||||
|
||||
const formRef = ref();
|
||||
const isConfirmLoading = ref(false);
|
||||
|
||||
const formBinding = ref({
|
||||
col: { span: 24 },
|
||||
initialForm: {},
|
||||
labelCol: { style: { width: '120px' } },
|
||||
columns: {
|
||||
basisTypeId: {
|
||||
title: '依据类型',
|
||||
key: 'basisTypeId',
|
||||
component: {
|
||||
name: 'fs-dict-radio',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
dict: dict({
|
||||
async getData() {
|
||||
return await getDictOptions(DICT_TYPE.contract_basis_type);
|
||||
},
|
||||
}),
|
||||
},
|
||||
rules: [{ required: true, message: '请选择依据类型' }],
|
||||
},
|
||||
basisNum: {
|
||||
title: '依据编号',
|
||||
key: 'basisNum',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入依据编号' }],
|
||||
},
|
||||
basisName: {
|
||||
title: '依据名称',
|
||||
key: 'basisName',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
},
|
||||
rules: [{ required: true, message: '请输入依据名称' }],
|
||||
},
|
||||
endDate: {
|
||||
title: '有效期',
|
||||
key: 'endDate',
|
||||
component: {
|
||||
name: 'a-date-picker',
|
||||
vModel: 'value',
|
||||
allowClear: false,
|
||||
disabledDate: (current: Dayjs) => {
|
||||
return current <= dayjs();
|
||||
},
|
||||
format: 'YYYY-MM-DD',
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
},
|
||||
rules: [{ required: true, message: '请选择有效期' }],
|
||||
},
|
||||
remark: {
|
||||
title: '备注',
|
||||
key: 'remark',
|
||||
component: {
|
||||
name: 'a-textarea',
|
||||
vModel: 'value',
|
||||
autoSize: { minRows: 4, maxRows: 6 },
|
||||
},
|
||||
},
|
||||
fileList: {
|
||||
title: '附件上传',
|
||||
key: 'fileList',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const handleChange = (info: UploadChangeParam) => {
|
||||
formRef.value.setFormData({
|
||||
fileList: info.fileList.length > 0 ? info.fileList : [],
|
||||
});
|
||||
};
|
||||
|
||||
const [BaseModal, baseModalApi] = useVbenModal({
|
||||
async onOpenChange(isOpen: boolean) {
|
||||
if (isOpen) {
|
||||
isConfirmLoading.value = false;
|
||||
|
||||
data.value = baseModalApi.getData<Record<string, any>>() || {};
|
||||
if (data.value.isUpdate) {
|
||||
if (data.value.record.fileUuid) {
|
||||
const files = await fileUploader.select(data.value.record.fileUuid);
|
||||
console.log(files);
|
||||
data.value.record.fileList = files;
|
||||
}
|
||||
|
||||
nextTick(() => {
|
||||
formRef.value.setFormData(data.value.record || {});
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
async onConfirm() {
|
||||
try {
|
||||
isConfirmLoading.value = true;
|
||||
console.info('onConfirm');
|
||||
console.log(formRef.value?.form);
|
||||
await formRef.value?.submit();
|
||||
|
||||
const form = formRef.value.form;
|
||||
{
|
||||
const tempFileList = form.fileList;
|
||||
let tempFiles: any = [];
|
||||
if (tempFileList && tempFileList.length > 0) {
|
||||
tempFiles = await fileUploader.upload(tempFileList, { source: 'ht' });
|
||||
}
|
||||
console.log(tempFiles);
|
||||
if (tempFiles) {
|
||||
form.fileUuid = (tempFiles.map((item) => item.fileUuid) || []).join(
|
||||
',',
|
||||
);
|
||||
}
|
||||
delete form.fileList;
|
||||
}
|
||||
|
||||
if (form.basisTypeId) {
|
||||
form.basisTypeName = getDictObj(
|
||||
DICT_TYPE.contract_basis_type,
|
||||
form.basisTypeId,
|
||||
)?.label;
|
||||
}
|
||||
|
||||
await Apis.lxBasisSale.post_save({ data: form });
|
||||
baseModalApi.close();
|
||||
message.success('操作成功');
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
isConfirmLoading.value = false;
|
||||
emit('success');
|
||||
}
|
||||
},
|
||||
onCancel() {
|
||||
baseModalApi.close();
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<BaseModal
|
||||
:confirm-loading="isConfirmLoading"
|
||||
:loading="isConfirmLoading"
|
||||
:title="data.isUpdate ? '修改签约依据信息' : '新增签约依据信息'"
|
||||
>
|
||||
<fs-form ref="formRef" v-bind="formBinding">
|
||||
<template #form_fileList="{ form }">
|
||||
<a-upload-dragger
|
||||
v-model:file-list="form.fileList"
|
||||
:before-upload="() => false"
|
||||
:max-count="1"
|
||||
accept=".pdf"
|
||||
name="file"
|
||||
@change="handleChange"
|
||||
>
|
||||
<div class="flex flex-col items-center">
|
||||
<MdiCloudUpload class="text-center text-[50px] text-gray-600" />
|
||||
<p class="ant-upload-text">点击或拖动文件到该区域来上传</p>
|
||||
<p class="ant-upload-hint">仅支持 pdf 类型的文件</p>
|
||||
</div>
|
||||
</a-upload-dragger>
|
||||
</template>
|
||||
</fs-form>
|
||||
</BaseModal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
:deep(.ant-divider-horizontal.ant-divider-with-text) {
|
||||
margin: 0 !important;
|
||||
}
|
||||
</style>
|
|
@ -1,12 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { Page } from '@vben/common-ui';
|
||||
import TodoPage from '../../components/todo-page/todo-page.vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page content-class="h-full">
|
||||
<TodoPage :module="['contractSetup']" />
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
|
@ -1,85 +0,0 @@
|
|||
import type { VxeGridPropTypes } from 'vxe-table';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
export const PrimaryKey = 'guid';
|
||||
|
||||
export function getColumns(_params?: any): VxeGridPropTypes.Columns {
|
||||
return [
|
||||
{
|
||||
type: 'radio',
|
||||
width: 40,
|
||||
slots: { radio: 'radio_cell' },
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
field: 'reviewNumber',
|
||||
title: '报审序号',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
field: 'contractNumber',
|
||||
title: '正式合同编号',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
field: 'contractName',
|
||||
title: '合同名称',
|
||||
width: 200,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
field: 'contractType',
|
||||
title: '合同类别',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
field: 'contractTerminator',
|
||||
title: '合同终止人',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
field: 'archiveTime',
|
||||
title: '合同归档时间',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function getFormSchema(_params: any = {}) {
|
||||
return {
|
||||
initialForm: {
|
||||
startDate: dayjs().startOf('month').format('YYYY-MM-DD'),
|
||||
},
|
||||
columns: {
|
||||
contractName: {
|
||||
title: '合同名称',
|
||||
key: 'contractName',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
},
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
contractNumber: {
|
||||
title: '正式合同编号',
|
||||
key: 'contractNumber',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
},
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { Page } from '@vben/common-ui';
|
||||
import { MdiExport, MdiRadioChecked, MdiRadioUnchecked } from '@vben/icons';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import Apis from '#/api';
|
||||
import { useVxeTable } from '#/hooks/vxeTable';
|
||||
|
||||
import { getColumns, getFormSchema, PrimaryKey } from './crud.tsx';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const searchRef = ref();
|
||||
|
||||
const { xGridRef, triggerProxy, gridProps } = useVxeTable({ ref: 'xGridRef' });
|
||||
|
||||
/** Hooks - 表格 */
|
||||
const gridOptions = reactive(
|
||||
gridProps({
|
||||
columns: getColumns(),
|
||||
proxyConfig: {
|
||||
autoLoad: false,
|
||||
ajax: {
|
||||
query: async ({ page }) => {
|
||||
const data = await Apis.contractFilingFormal.get_pageArchivedContract(
|
||||
{
|
||||
params: {
|
||||
pageNum: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...searchRef.value?.formData,
|
||||
},
|
||||
},
|
||||
);
|
||||
return data;
|
||||
},
|
||||
},
|
||||
},
|
||||
pagerConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
toolbarConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
function handleExport() {
|
||||
const $grid = xGridRef.value;
|
||||
if ($grid) {
|
||||
$grid.exportData({
|
||||
type: 'xlsx',
|
||||
});
|
||||
message.success('导出成功');
|
||||
}
|
||||
}
|
||||
|
||||
/** 选中数据 */
|
||||
const selectRow: any = computed(() => {
|
||||
return xGridRef.value?.getRadioRecord() || null;
|
||||
});
|
||||
|
||||
/** 单选框选中事件 */
|
||||
const setSelectRow = (row: any) => {
|
||||
if (selectRow.value && selectRow.value[PrimaryKey] === row[PrimaryKey]) {
|
||||
xGridRef.value?.clearRadioRow();
|
||||
} else {
|
||||
xGridRef.value?.setRadioRow(row);
|
||||
}
|
||||
};
|
||||
|
||||
/** 表格单元格单击事件 */
|
||||
function handleCellClick({ row }) {
|
||||
setSelectRow(row);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
triggerProxy('reload');
|
||||
});
|
||||
|
||||
const searchForm = ref({
|
||||
...getFormSchema(),
|
||||
onSearch(_context: any) {
|
||||
triggerProxy('reload');
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page content-class="h-full flex flex-col">
|
||||
<fs-search ref="searchRef" v-bind="searchForm" />
|
||||
|
||||
<div class="min-h-300px flex-1">
|
||||
<vxe-grid
|
||||
ref="xGridRef"
|
||||
v-bind="gridOptions"
|
||||
@cell-click="handleCellClick"
|
||||
>
|
||||
<template #toolbar_buttons>
|
||||
<a-space>
|
||||
<vben-button variant="primary" @click="handleExport()">
|
||||
<MdiExport class="mr-0.5 text-lg" />
|
||||
导出
|
||||
</vben-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<template #radio_cell="{ row, checked }">
|
||||
<span class="text-base" @click.stop="setSelectRow(row)">
|
||||
<MdiRadioChecked v-if="checked" />
|
||||
<MdiRadioUnchecked v-else />
|
||||
</span>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</div>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<style></style>
|
|
@ -1,99 +0,0 @@
|
|||
import type { VxeGridPropTypes } from 'vxe-table';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
export const PrimaryKey = 'guid';
|
||||
|
||||
export function getColumns(_params?: any): VxeGridPropTypes.Columns {
|
||||
return [
|
||||
{
|
||||
type: 'radio',
|
||||
width: 40,
|
||||
slots: { radio: 'radio_cell' },
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
field: 're',
|
||||
title: '归档',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
field: 'reviewNumber',
|
||||
title: '报审序号',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
field: 'contractNumber',
|
||||
title: '正式合同编号',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
field: 'contractName',
|
||||
title: '合同名称',
|
||||
width: 200,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
field: 'contractType',
|
||||
title: '合同类别',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
field: 'contractTerminator',
|
||||
title: '合同终止人',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
field: 'archiveTime',
|
||||
title: '合同归档时间',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
slots: {
|
||||
default: 'operate',
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function getFormSchema(_params: any = {}) {
|
||||
return {
|
||||
initialForm: {
|
||||
startDate: dayjs().startOf('month').format('YYYY-MM-DD'),
|
||||
},
|
||||
columns: {
|
||||
contractName: {
|
||||
title: '合同名称',
|
||||
key: 'contractName',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
},
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
contractNumber: {
|
||||
title: '正式合同编号',
|
||||
key: 'contractNumber',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
},
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { Page } from '@vben/common-ui';
|
||||
import { MdiExport, MdiRadioChecked, MdiRadioUnchecked } from '@vben/icons';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import Apis from '#/api';
|
||||
import { useVxeTable } from '#/hooks/vxeTable';
|
||||
|
||||
import { getColumns, getFormSchema, PrimaryKey } from './crud.tsx';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const searchRef = ref();
|
||||
|
||||
const { xGridRef, triggerProxy, gridProps } = useVxeTable({ ref: 'xGridRef' });
|
||||
|
||||
/** Hooks - 表格 */
|
||||
const gridOptions = reactive(
|
||||
gridProps({
|
||||
columns: getColumns(),
|
||||
proxyConfig: {
|
||||
autoLoad: false,
|
||||
ajax: {
|
||||
query: async ({ page }) => {
|
||||
const data = await Apis.contractFilingFormal.get_pageArchivedContract(
|
||||
{
|
||||
params: {
|
||||
pageNum: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...searchRef.value?.formData,
|
||||
},
|
||||
},
|
||||
);
|
||||
return data;
|
||||
},
|
||||
},
|
||||
},
|
||||
pagerConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
toolbarConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
function handleExport() {
|
||||
const $grid = xGridRef.value;
|
||||
if ($grid) {
|
||||
$grid.exportData({
|
||||
type: 'xlsx',
|
||||
});
|
||||
message.success('导出成功');
|
||||
}
|
||||
}
|
||||
|
||||
/** 选中数据 */
|
||||
const selectRow: any = computed(() => {
|
||||
return xGridRef.value?.getRadioRecord() || null;
|
||||
});
|
||||
|
||||
/** 单选框选中事件 */
|
||||
const setSelectRow = (row: any) => {
|
||||
if (selectRow.value && selectRow.value[PrimaryKey] === row[PrimaryKey]) {
|
||||
xGridRef.value?.clearRadioRow();
|
||||
} else {
|
||||
xGridRef.value?.setRadioRow(row);
|
||||
}
|
||||
};
|
||||
|
||||
/** 表格单元格单击事件 */
|
||||
function handleCellClick({ row }) {
|
||||
setSelectRow(row);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
triggerProxy('reload');
|
||||
});
|
||||
|
||||
const searchForm = ref({
|
||||
...getFormSchema(),
|
||||
onSearch(_context: any) {
|
||||
triggerProxy('reload');
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page content-class="h-full flex flex-col">
|
||||
<fs-search ref="searchRef" v-bind="searchForm" />
|
||||
|
||||
<div class="min-h-300px flex-1">
|
||||
<vxe-grid
|
||||
ref="xGridRef"
|
||||
v-bind="gridOptions"
|
||||
@cell-click="handleCellClick"
|
||||
>
|
||||
<template #toolbar_buttons>
|
||||
<a-space>
|
||||
<vben-button variant="primary" @click="handleExport()">
|
||||
<MdiExport class="mr-0.5 text-lg" />
|
||||
导出
|
||||
</vben-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<template #radio_cell="{ row, checked }">
|
||||
<span class="text-base" @click.stop="setSelectRow(row)">
|
||||
<MdiRadioChecked v-if="checked" />
|
||||
<MdiRadioUnchecked v-else />
|
||||
</span>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</div>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<style></style>
|
|
@ -1,105 +0,0 @@
|
|||
import type { VxeGridPropTypes } from 'vxe-table';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
export const PrimaryKey = 'guid';
|
||||
|
||||
export function getColumns(_params?: any): VxeGridPropTypes.Columns {
|
||||
return [
|
||||
{
|
||||
type: 'radio',
|
||||
width: 40,
|
||||
slots: { radio: 'radio_cell' },
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
field: 're',
|
||||
title: '回档',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
field: 'reviewNumber',
|
||||
title: '报审序号',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
field: 'contractDeclareNumber',
|
||||
title: '合同申报编号',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
field: 'contractNumber',
|
||||
title: '正式合同编号',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
field: 'contractName',
|
||||
title: '合同名称',
|
||||
width: 200,
|
||||
align: 'left',
|
||||
},
|
||||
{
|
||||
field: 'contractType',
|
||||
title: '合同类别',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
field: 'contractTerminator',
|
||||
title: '合同终止人',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
field: 'contractTerminationTime',
|
||||
title: '合同终止时间',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
slots: {
|
||||
default: 'operate',
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function getFormSchema(_params: any = {}) {
|
||||
return {
|
||||
initialForm: {
|
||||
startDate: dayjs().startOf('month').format('YYYY-MM-DD'),
|
||||
},
|
||||
columns: {
|
||||
contractName: {
|
||||
title: '合同名称',
|
||||
key: 'contractName',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
},
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
contractNumber: {
|
||||
title: '正式合同编号',
|
||||
key: 'contractNumber',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
},
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { Page } from '@vben/common-ui';
|
||||
import { MdiExport, MdiRadioChecked, MdiRadioUnchecked } from '@vben/icons';
|
||||
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
import Apis from '#/api';
|
||||
import { useVxeTable } from '#/hooks/vxeTable';
|
||||
|
||||
import { getColumns, getFormSchema, PrimaryKey } from './crud.tsx';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const searchRef = ref();
|
||||
|
||||
const { xGridRef, triggerProxy, gridProps } = useVxeTable({ ref: 'xGridRef' });
|
||||
|
||||
/** Hooks - 表格 */
|
||||
const gridOptions = reactive(
|
||||
gridProps({
|
||||
columns: getColumns(),
|
||||
proxyConfig: {
|
||||
autoLoad: false,
|
||||
ajax: {
|
||||
query: async ({ page }) => {
|
||||
const data = await Apis.contractFilingFormal.get_pageArchivedContract(
|
||||
{
|
||||
params: {
|
||||
pageNum: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...searchRef.value?.formData,
|
||||
},
|
||||
},
|
||||
);
|
||||
return data;
|
||||
},
|
||||
},
|
||||
},
|
||||
pagerConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
toolbarConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
function handleExport() {
|
||||
const $grid = xGridRef.value;
|
||||
if ($grid) {
|
||||
$grid.exportData({
|
||||
type: 'xlsx',
|
||||
});
|
||||
message.success('导出成功');
|
||||
}
|
||||
}
|
||||
|
||||
/** 选中数据 */
|
||||
const selectRow: any = computed(() => {
|
||||
return xGridRef.value?.getRadioRecord() || null;
|
||||
});
|
||||
|
||||
/** 单选框选中事件 */
|
||||
const setSelectRow = (row: any) => {
|
||||
if (selectRow.value && selectRow.value[PrimaryKey] === row[PrimaryKey]) {
|
||||
xGridRef.value?.clearRadioRow();
|
||||
} else {
|
||||
xGridRef.value?.setRadioRow(row);
|
||||
}
|
||||
};
|
||||
|
||||
/** 表格单元格单击事件 */
|
||||
function handleCellClick({ row }) {
|
||||
setSelectRow(row);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
triggerProxy('reload');
|
||||
});
|
||||
|
||||
const searchForm = ref({
|
||||
...getFormSchema(),
|
||||
onSearch(_context: any) {
|
||||
triggerProxy('reload');
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page content-class="h-full flex flex-col">
|
||||
<fs-search ref="searchRef" v-bind="searchForm" />
|
||||
|
||||
<div class="min-h-300px flex-1">
|
||||
<vxe-grid
|
||||
ref="xGridRef"
|
||||
v-bind="gridOptions"
|
||||
@cell-click="handleCellClick"
|
||||
>
|
||||
<template #toolbar_buttons>
|
||||
<a-space>
|
||||
<vben-button variant="primary" @click="handleExport()">
|
||||
<MdiExport class="mr-0.5 text-lg" />
|
||||
导出
|
||||
</vben-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<template #radio_cell="{ row, checked }">
|
||||
<span class="text-base" @click.stop="setSelectRow(row)">
|
||||
<MdiRadioChecked v-if="checked" />
|
||||
<MdiRadioUnchecked v-else />
|
||||
</span>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</div>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<style></style>
|
|
@ -1,97 +0,0 @@
|
|||
import type { VxeGridPropTypes } from 'vxe-table';
|
||||
import { useRender } from '#/hooks/useRender';
|
||||
import dayjs from 'dayjs';
|
||||
import { DICT_TYPE, getDictOptions } from '#/utils/dict';
|
||||
import { dict } from '@fast-crud/fast-crud';
|
||||
|
||||
export const PrimaryKey = 'guid';
|
||||
|
||||
export function getColumns(params: any = {}): VxeGridPropTypes.Columns {
|
||||
return [
|
||||
{ type: 'radio', width: 40, slots: { radio: 'radio_cell' }, align: 'center', fixed: 'left' },
|
||||
{
|
||||
field: 'contractName', title: '合同名称', minWidth: 200, slots: {
|
||||
default: ({ row }) => {
|
||||
return useRender.renderMultiLineText(row.contractName);
|
||||
}
|
||||
}, fixed: 'left'
|
||||
},
|
||||
{
|
||||
field: 'reportNo', title: '报审序号', width: 100,
|
||||
},
|
||||
{
|
||||
field: 'ctrTypeName', title: '合同类别', width: 200, slots: {
|
||||
default: ({ row }) => {
|
||||
return useRender.renderText(row.ctrTypeName, '-' + row.ctrTwoTypeName);
|
||||
}
|
||||
}
|
||||
},
|
||||
{ field: 'budgetSum', title: '预算金额', width: 100 },
|
||||
{ field: 'priceTypeName', title: '币种', width: 100 },
|
||||
{
|
||||
field: 'organiza', title: '组织形式', width: 120, slots: {
|
||||
default: ({ row }) => {
|
||||
return useRender.renderDict(row.organiza, DICT_TYPE.contract_organization_form);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'fundAllocation', title: '资金流向', width: 100, slots: {
|
||||
default: ({ row }) => {
|
||||
return useRender.renderDict(row.fundAllocation, DICT_TYPE.contract_fund_flow);
|
||||
}
|
||||
}
|
||||
},
|
||||
{ field: 'inputPerson', title: '承办人', width: 100 },
|
||||
{ field: 'inputDepartName', title: '承办部门', width: 100 },
|
||||
{ field: 'inputDate', title: '承办时间', width: 130 },
|
||||
]
|
||||
}
|
||||
|
||||
export function getFormSchema(_params: any = {}) {
|
||||
return {
|
||||
initialForm: {
|
||||
startDate: dayjs().startOf('month').format("YYYY-MM-DD"),
|
||||
},
|
||||
columns: {
|
||||
contractName: {
|
||||
title: '合同名称',
|
||||
key: 'contractName',
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
},
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
organiza: {
|
||||
title: '组织形式',
|
||||
key: 'organiza',
|
||||
component: {
|
||||
name: 'fs-dict-select',
|
||||
vModel: 'value',
|
||||
class: 'min-w-[180px]',
|
||||
allowClear: true,
|
||||
dict: dict({
|
||||
data: getDictOptions(DICT_TYPE.contract_organization_form)
|
||||
}),
|
||||
},
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
price: {
|
||||
title: '预算金额',
|
||||
key: 'price',
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
time: {
|
||||
title: '申报时间',
|
||||
key: 'startDate',
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
|
@ -1,245 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import { Page, useVbenModal } from '@vben/common-ui';
|
||||
import {
|
||||
MdiAdd,
|
||||
MdiDelete,
|
||||
MdiExport,
|
||||
MdiRadioChecked,
|
||||
MdiRadioUnchecked,
|
||||
MdiUpdate,
|
||||
} from '@vben/icons';
|
||||
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
|
||||
import Apis from '#/api';
|
||||
import { useVxeTable } from '#/hooks/vxeTable';
|
||||
import { getMonthStartAndEnd } from '#/utils/time';
|
||||
|
||||
import { getColumns, getFormSchema, PrimaryKey } from './crud.tsx';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const checkedValue = ref('all');
|
||||
const exportSearchParams = ref<any>({
|
||||
daterange: getMonthStartAndEnd(),
|
||||
});
|
||||
|
||||
const searchRef = ref();
|
||||
const isConfirmLoading = ref(false);
|
||||
const [_Modal, modalApi] = useVbenModal({
|
||||
async onConfirm() {
|
||||
isConfirmLoading.value = true;
|
||||
|
||||
try {
|
||||
let params = {};
|
||||
if (checkedValue.value == 'daterange') {
|
||||
params = {
|
||||
startDate: exportSearchParams.value.daterange[0],
|
||||
endDate: exportSearchParams.value.daterange[1],
|
||||
};
|
||||
}
|
||||
const res = await Apis.zbgl
|
||||
.post_export({
|
||||
params,
|
||||
config: {
|
||||
meta: {
|
||||
responseType: 'blob',
|
||||
},
|
||||
},
|
||||
})
|
||||
.send();
|
||||
message.success('导出成功');
|
||||
modalApi.close();
|
||||
showExportModal.value = false;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
isConfirmLoading.value = false;
|
||||
}
|
||||
|
||||
console.info('onConfirm');
|
||||
},
|
||||
});
|
||||
|
||||
const { xGridRef, triggerProxy, gridProps } = useVxeTable({ ref: 'xGridRef' });
|
||||
|
||||
const treeData = ref([]);
|
||||
|
||||
/** Hooks - 表格 */
|
||||
const gridOptions = reactive(
|
||||
gridProps({
|
||||
columns: getColumns(),
|
||||
proxyConfig: {
|
||||
autoLoad: false,
|
||||
ajax: {
|
||||
query: ({ page }) => {
|
||||
return Apis.contractBaseInfo.get_page({
|
||||
params: {
|
||||
pageNum: page.currentPage,
|
||||
pageSize: page.pageSize,
|
||||
...searchRef.value?.formData,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
pagerConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
toolbarConfig: {
|
||||
enabled: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
function handleEdit(record?: any) {
|
||||
if (record && record[PrimaryKey]) {
|
||||
router.push(`/contract/approval/edit/${record[PrimaryKey]}`);
|
||||
} else {
|
||||
router.push('/contract/approval/edit');
|
||||
}
|
||||
}
|
||||
|
||||
function handleDelete(row) {
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '是否确认删除该条记录?',
|
||||
okType: 'danger',
|
||||
onOk: async () => {
|
||||
await Apis.contractBaseInfo.post_deletes({
|
||||
params: { ids: row[PrimaryKey] },
|
||||
});
|
||||
message.success('删除成功');
|
||||
triggerProxy('reload');
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function handleExport() {
|
||||
const $grid = xGridRef.value;
|
||||
if ($grid) {
|
||||
$grid.exportData({
|
||||
type: 'xlsx',
|
||||
});
|
||||
message.success('导出成功');
|
||||
}
|
||||
}
|
||||
|
||||
/** 选中数据 */
|
||||
const selectRow: any = computed(() => {
|
||||
return xGridRef.value?.getRadioRecord() || null;
|
||||
});
|
||||
|
||||
/** 单选框选中事件 */
|
||||
const setSelectRow = (row: any) => {
|
||||
if (selectRow.value && selectRow.value[PrimaryKey] === row[PrimaryKey]) {
|
||||
xGridRef.value?.clearRadioRow();
|
||||
} else {
|
||||
xGridRef.value?.setRadioRow(row);
|
||||
}
|
||||
};
|
||||
|
||||
/** 表格单元格单击事件 */
|
||||
function handleCellClick({ row }) {
|
||||
setSelectRow(row);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
triggerProxy('reload');
|
||||
});
|
||||
|
||||
const searchForm = ref({
|
||||
...getFormSchema(),
|
||||
onSearch(context: any) {
|
||||
triggerProxy('reload');
|
||||
},
|
||||
});
|
||||
|
||||
function toPage() {
|
||||
window.open('/iframe/meeting/standing-book', '_blank');
|
||||
}
|
||||
|
||||
function toDetail(row) {
|
||||
window.open(`/iframe/meeting/start/${row.guid}`, '_blank');
|
||||
}
|
||||
// 页面打开后获取列表数据
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page content-class="h-full flex flex-col">
|
||||
<fs-search ref="searchRef" v-bind="searchForm">
|
||||
<template #search_price="{ row }">
|
||||
<a-input-number v-model:value="row.budgetSum1" placeholder="" />
|
||||
<span class="mx-1">至</span>
|
||||
<a-input-number v-model:value="row.budgetSum2" placeholder="" />
|
||||
</template>
|
||||
<template #form_time="{ row }">
|
||||
<a-date-picker
|
||||
v-model:value="row.startTime"
|
||||
format="YYYY-MM-DD"
|
||||
placeholder=""
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
<span class="mx-1">至</span>
|
||||
<a-date-picker
|
||||
v-model:value="row.endTime"
|
||||
format="YYYY-MM-DD"
|
||||
placeholder=""
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</template>
|
||||
</fs-search>
|
||||
|
||||
<div class="min-h-300px flex-1">
|
||||
<vxe-grid
|
||||
ref="xGridRef"
|
||||
v-bind="gridOptions"
|
||||
@cell-click="handleCellClick"
|
||||
>
|
||||
<template #toolbar_buttons>
|
||||
<a-space>
|
||||
<vben-button variant="primary" @click="handleEdit()">
|
||||
<MdiAdd class="mr-0.5 text-lg" />
|
||||
新增
|
||||
</vben-button>
|
||||
<vben-button
|
||||
:disabled="!selectRow || !selectRow[PrimaryKey]"
|
||||
variant="warning"
|
||||
@click="handleEdit(selectRow)"
|
||||
>
|
||||
<MdiUpdate class="mr-0.5 text-lg" />
|
||||
修改
|
||||
</vben-button>
|
||||
<vben-button variant="primary" @click="handleExport()">
|
||||
<MdiExport class="mr-0.5 text-lg" />
|
||||
导出
|
||||
</vben-button>
|
||||
<vben-button
|
||||
:disabled="!selectRow || !selectRow[PrimaryKey]"
|
||||
variant="destructive"
|
||||
@click="handleDelete(selectRow)"
|
||||
>
|
||||
<MdiDelete class="mr-0.5 text-lg" />
|
||||
删除
|
||||
</vben-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<template #radio_cell="{ row, checked }">
|
||||
<span class="text-base" @click.stop="setSelectRow(row)">
|
||||
<MdiRadioChecked v-if="checked" />
|
||||
<MdiRadioUnchecked v-else />
|
||||
</span>
|
||||
</template>
|
||||
</vxe-grid>
|
||||
</div>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<style></style>
|
|
@ -1,182 +0,0 @@
|
|||
<template>
|
||||
<Page contentClass="h-full flex flex-col">
|
||||
<a-space direction="vertical" size="small">
|
||||
<a-card title="待办" size="small">
|
||||
<vxe-grid ref="xGridRef" v-bind="gridOptions">
|
||||
<template #toolbar_buttons> </template>
|
||||
</vxe-grid>
|
||||
</a-card>
|
||||
<a-card title="已办" size="small" contentClass="">
|
||||
<vxe-grid ref="xGrid2Ref" v-bind="grid2Options">
|
||||
<template #toolbar_buttons> </template>
|
||||
</vxe-grid>
|
||||
</a-card>
|
||||
</a-space>
|
||||
</Page>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineComponent, ref, reactive, onMounted } from 'vue';
|
||||
import { FsCrud } from '@fast-crud/fast-crud';
|
||||
import { type VxeGridProps } from 'vxe-table'
|
||||
import { Page, useVbenModal } from '@vben/common-ui';
|
||||
import { useVxeTable } from '#/hooks/vxeTable';
|
||||
import {
|
||||
type CreateCrudOptionsProps,
|
||||
useColumns,
|
||||
useFormWrapper,
|
||||
useFs,
|
||||
utils,
|
||||
} from '@fast-crud/fast-crud';
|
||||
import { MdiAdd, MdiUpdate, MdiDelete } from '@vben/icons';
|
||||
import { dict } from "@fast-crud/fast-crud";
|
||||
|
||||
import Apis from '#/api'
|
||||
|
||||
const { xGridRef, triggerProxy, gridProps } = useVxeTable({ ref: 'xGridRef' });
|
||||
|
||||
const { xGridRef:xGrid2Ref, triggerProxy:triggerProxy2 } = useVxeTable({ ref: 'xGrid2Ref' });
|
||||
|
||||
|
||||
const treeData = ref([]);
|
||||
|
||||
/** Hooks - 表格 */
|
||||
const gridOptions = reactive(gridProps({
|
||||
columns: [
|
||||
{ type: 'seq', width: 50, align: 'center', fixed: 'left' },
|
||||
{ field: 'contractId', title: '编号', width: 100 },
|
||||
{
|
||||
field: 'title', title: '名称', minWidth: 200, slots: {
|
||||
default: ({ row }) => {
|
||||
// let text = row.title
|
||||
// if (text) {
|
||||
// let classArr: string[] = ["line-clamp-3"];
|
||||
// return h(
|
||||
// NTooltip,
|
||||
// { trigger: 'hover' },
|
||||
// {
|
||||
// trigger: () => h('span', { class: classArr.join(' ') }, text),
|
||||
// default: () => text
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
return '';
|
||||
}
|
||||
}
|
||||
},
|
||||
{ field: 'contractAmount', title: '模块', width: 150 },
|
||||
{ field: 'contractSubject', title: '任务', width: 200 },
|
||||
{ field: 'contractCounterparty', title: '分配时间', width: 150 },
|
||||
{ field: 'cumulativeSettlementAmount', title: '承办单位/部门', width: 150 },
|
||||
{ field: 'changeCount', title: '承办人', width: 100 },
|
||||
{ field: 'contractStatus', title: '交接给', width: 100 }
|
||||
],
|
||||
proxyConfig: {
|
||||
autoLoad: true,
|
||||
ajax: {
|
||||
query: ({ page }) => {
|
||||
return Apis.ccsq.get_toDoPage({ params: { pageNum: page.currentPage, pageSize: page.pageSize, ...searchParams } })
|
||||
}
|
||||
},
|
||||
},
|
||||
pagerConfig: {
|
||||
enabled: true
|
||||
},
|
||||
toolbarConfig: {
|
||||
enabled: false
|
||||
},
|
||||
}));
|
||||
|
||||
/** Hooks - 表格 */
|
||||
const grid2Options = reactive(gridProps({
|
||||
columns: [
|
||||
{ type: 'seq', width: 50, align: 'center', fixed: 'left' },
|
||||
{ field: 'contractId', title: '编号', width: 100 },
|
||||
{
|
||||
field: 'title', title: '名称', minWidth: 200, slots: {
|
||||
default: ({ row }) => {
|
||||
// let text = row.title
|
||||
// if (text) {
|
||||
// let classArr: string[] = ["line-clamp-3"];
|
||||
// return h(
|
||||
// NTooltip,
|
||||
// { trigger: 'hover' },
|
||||
// {
|
||||
// trigger: () => h('span', { class: classArr.join(' ') }, text),
|
||||
// default: () => text
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
return '';
|
||||
}
|
||||
}
|
||||
},
|
||||
{ field: 'contractAmount', title: '模块', width: 150 },
|
||||
{ field: 'contractSubject', title: '任务', width: 200 },
|
||||
{ field: 'contractCounterparty', title: '分配时间', width: 150 },
|
||||
{ field: 'cumulativeSettlementAmount', title: '承办单位/部门', width: 150 },
|
||||
{ field: 'changeCount', title: '承办人', width: 100 },
|
||||
{ field: 'contractStatus', title: '交接给', width: 100 }
|
||||
],
|
||||
proxyConfig: {
|
||||
autoLoad: true,
|
||||
ajax: {
|
||||
query: ({ page }) => {
|
||||
return Apis.ccsq.get_donePage({ params: { pageNum: page.currentPage, pageSize: page.pageSize, ...searchParams } })
|
||||
}
|
||||
},
|
||||
},
|
||||
pagerConfig: {
|
||||
enabled: true
|
||||
},
|
||||
toolbarConfig: {
|
||||
enabled: false
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
})
|
||||
|
||||
let searchParams = reactive({})
|
||||
const searchForm = ref({
|
||||
columns: {
|
||||
name: {
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
props: {
|
||||
type: 'text',
|
||||
showWordLimit: true,
|
||||
},
|
||||
},
|
||||
title: '字典标签',
|
||||
key: 'type',
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
age: {
|
||||
component: {
|
||||
name: 'a-input',
|
||||
vModel: 'value',
|
||||
allowClear: true,
|
||||
},
|
||||
title: '字典键值',
|
||||
key: 'value',
|
||||
autoSearchTrigger: 'enter',
|
||||
show: true,
|
||||
},
|
||||
},
|
||||
onSearch(context: any) {
|
||||
searchParams = context.form
|
||||
triggerProxy('reload')
|
||||
},
|
||||
onReset(context: any) {
|
||||
searchParams = context.form
|
||||
},
|
||||
});
|
||||
// 页面打开后获取列表数据
|
||||
</script>
|
||||
|
||||
<style></style>
|
|
@ -1,282 +0,0 @@
|
|||
<script setup lang="tsx">
|
||||
import {
|
||||
computed,
|
||||
defineEmits,
|
||||
defineExpose,
|
||||
defineProps,
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
watch,
|
||||
withDefaults,
|
||||
} from 'vue';
|
||||
|
||||
import Apis from '#/api'; // 假设 Apis 引入的路径
|
||||
import { filterContractTypes } from '#/views/contract/utils'; // 假设 utils 引入的路径
|
||||
import type { UploadChangeParam } from 'ant-design-vue';
|
||||
|
||||
import { MdiUpload } from '@vben/icons';
|
||||
|
||||
import { DICT_TYPE, getDictDatasAsync } from '#/utils/dict';
|
||||
import { FileUploader } from '#/utils/file';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
form: Record<string, any>;
|
||||
}>(),
|
||||
{
|
||||
form: () => ({}),
|
||||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits(['update:form', 'field-change']);
|
||||
|
||||
const fileUploader = new FileUploader({});
|
||||
|
||||
const formRef = ref();
|
||||
const form = reactive({ ...props.form });
|
||||
|
||||
watch(
|
||||
() => props.form,
|
||||
async (newForm) => {
|
||||
Object.assign(form, newForm);
|
||||
},
|
||||
{ deep: true, immediate: true },
|
||||
);
|
||||
|
||||
const readOnly = computed(() => {
|
||||
return ['smApproval'].includes(form.businessStep);
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.form.fileUuid,
|
||||
async (newFileUuid) => {
|
||||
if (newFileUuid) {
|
||||
const files = await fileUploader.select(newFileUuid);
|
||||
console.log(files);
|
||||
form.fileList = files;
|
||||
} else {
|
||||
form.fileList = []; // 清空文件列表
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
watch(
|
||||
() => form,
|
||||
(newForm) => {
|
||||
emit('update:form', newForm);
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
const rules = {
|
||||
contractName: [{ required: true, message: '合同名称是必填项' }],
|
||||
ctrType: [{ required: true, message: '合同类别是必填项' }],
|
||||
ctrTwoType: [{ required: true, message: '二级类别是必填项' }],
|
||||
fundAllocation: [{ required: true, message: '请选择资金流向' }],
|
||||
fundDitch: [{ required: true, message: '请选择资金渠道' }],
|
||||
organiza: [{ required: true, message: '请选择组织方式' }],
|
||||
};
|
||||
|
||||
const contractTypeData = ref<any[]>([]);
|
||||
|
||||
function filteredContractTypes(parentType: string) {
|
||||
return filterContractTypes(contractTypeData.value, parentType);
|
||||
}
|
||||
|
||||
const dictMap = ref<any>({
|
||||
common_whether: [],
|
||||
contract_currency_unit: [],
|
||||
contract_fund_flow: [],
|
||||
contract_funding_source: [],
|
||||
contract_organization_form: [],
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
const contractReferTypeData: any = await Apis.contractReferType.get_list({
|
||||
params: {},
|
||||
});
|
||||
contractTypeData.value = contractReferTypeData.rows || [];
|
||||
|
||||
// 加载码表
|
||||
dictMap.value = await getDictDatasAsync([
|
||||
{ type: DICT_TYPE.contract_currency_unit, valueType: 'string' },
|
||||
{ type: DICT_TYPE.common_whether, valueType: 'string' },
|
||||
{ type: DICT_TYPE.contract_fund_flow, valueType: 'string' },
|
||||
{ type: DICT_TYPE.contract_funding_source, valueType: 'string' },
|
||||
{ type: DICT_TYPE.contract_organization_form, valueType: 'string' },
|
||||
]);
|
||||
console.log(dictMap.value);
|
||||
});
|
||||
|
||||
const handleChange = (info: UploadChangeParam) => {
|
||||
form.fileList = info.fileList.length > 0 ? info.fileList : [];
|
||||
};
|
||||
|
||||
function validate() {
|
||||
return formRef.value?.validate();
|
||||
}
|
||||
|
||||
function submit() {
|
||||
// return f
|
||||
}
|
||||
|
||||
defineExpose({ validate, submit });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-form
|
||||
ref="formRef"
|
||||
:label-col="{ style: { width: '120px' } }"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
>
|
||||
<a-row :gutter="16">
|
||||
<a-col :span="16">
|
||||
<a-form-item label="合同名称" name="contractName">
|
||||
<a-input v-model:value="form.contractName" :disabled="readOnly" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="8">
|
||||
<a-form-item label="报审序号" name="reportNo">
|
||||
<a-input v-model:value="form.reportNo" :disabled="readOnly" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="8">
|
||||
<a-form-item label="合同类别" name="ctrType">
|
||||
<a-select
|
||||
v-model:value="form.ctrType"
|
||||
:disabled="readOnly"
|
||||
:options="filteredContractTypes('-1')"
|
||||
class="min-w-[200px]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="8">
|
||||
<a-form-item label="二级类别" name="ctrTwoType">
|
||||
<a-select
|
||||
v-model:value="form.ctrTwoType"
|
||||
:disabled="readOnly"
|
||||
:options="filteredContractTypes(form.ctrType)"
|
||||
class="min-w-[200px]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="8">
|
||||
<!-- <a-form-item label="三级类别" name="ctrThreeType">
|
||||
<span>{{ form.ctrThreeType }}</span>
|
||||
</a-form-item> -->
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-row :gutter="16">
|
||||
<a-form-item label="预算金额" name="budgetSum">
|
||||
<a-input-number
|
||||
v-model:value="form.budgetSum"
|
||||
:disabled="readOnly"
|
||||
:min="0"
|
||||
class="min-w-[200px]"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-col :span="3">
|
||||
<a-form-item :colon="false" label="" name="priceType">
|
||||
<a-select
|
||||
v-model:value="form.priceType"
|
||||
:disabled="readOnly"
|
||||
:min="0"
|
||||
:options="dictMap[DICT_TYPE.contract_currency_unit]"
|
||||
class="w-full min-w-[120px]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="12">
|
||||
<a-form-item label="资金流向" name="fundAllocation">
|
||||
<a-select
|
||||
v-model:value="form.fundAllocation"
|
||||
:disabled="readOnly"
|
||||
:options="dictMap[DICT_TYPE.contract_fund_flow]"
|
||||
class="min-w-[200px]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="12">
|
||||
<a-form-item label="资金渠道" name="fundDitch">
|
||||
<a-select
|
||||
v-model:value="form.fundDitch"
|
||||
:disabled="readOnly"
|
||||
:options="dictMap[DICT_TYPE.contract_funding_source]"
|
||||
class="min-w-[200px]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="12">
|
||||
<a-form-item label="框架协议" name="frameProtocol">
|
||||
<a-radio-group
|
||||
v-model:value="form.frameProtocol"
|
||||
:disabled="readOnly"
|
||||
:options="dictMap[DICT_TYPE.common_whether]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="12">
|
||||
<a-form-item label="框架协议下的合同" name="frameProtocolCtr">
|
||||
<a-radio-group
|
||||
v-model:value="form.frameProtocolCtr"
|
||||
:disabled="readOnly"
|
||||
:options="dictMap[DICT_TYPE.common_whether]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item label="组织方式" name="organiza">
|
||||
<a-radio-group
|
||||
v-model:value="form.organiza"
|
||||
:disabled="readOnly"
|
||||
:options="dictMap[DICT_TYPE.contract_organization_form]"
|
||||
class="min-w-[200px]"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item label="合同附件" name="fileList">
|
||||
<a-upload
|
||||
v-model:file-list="form.fileList"
|
||||
:before-upload="() => false"
|
||||
:disabled="readOnly"
|
||||
:max-count="3"
|
||||
accept=".pdf,.ppt,.pptx"
|
||||
name="file"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-button v-if="!readOnly">
|
||||
<MdiUpload />
|
||||
点击上传
|
||||
</a-button>
|
||||
<div
|
||||
v-if="readOnly && form.fileList.length === 0"
|
||||
class="text-gray-700"
|
||||
>
|
||||
无附件
|
||||
</div>
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue