Compare commits

...

6 Commits

99 changed files with 4327 additions and 2545 deletions

View File

@ -76,7 +76,7 @@
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[html]": {
"editor.defaultFormatter": "vscode.html-language-features"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"

41
src/api/database/index.ts Normal file
View File

@ -0,0 +1,41 @@
import { defHttp } from '@/utils/http/axios';
import {AccountListGetResultModel,AccountListItem,AccountParams } from './model/index';
enum Api {
GETDATABASETABLEPAGE_LIST = '/api/SysDatabaseLink/LoadDataBaseInfo', //获取数据库
ADDDATABASETABLE = '/api/SysDatabaseLink/AddBaseLinkForm', //新增数据库
EDITDATABASETABLE = '/api/SysDatabaseLink/UpdateBaseLink?keyValue=', //编辑数据库
DELETEDATABASETABLE = '/api/SysDatabaseLink/DeleteBaseLink?id=', //删除数据库
GETDATABASEDETAIL = '/api/SysDatabaseLink/GetDataBaseForm', //编辑时获取详情数据
TEStCONNECTTION = '/api/SysDatabaseLink/TestConnection', //测试连接串是否正确
}
/**
* @description: Get sample options value
*/
export const getDataBasePageList = (params: AccountParams) =>
defHttp.get<AccountListGetResultModel>({ url: Api.GETDATABASETABLEPAGE_LIST, params });
export const getDataBaseDetail = (params: AccountParams) =>
defHttp.get<AccountListGetResultModel>({ url: Api.GETDATABASEDETAIL, params });
export const testDataBaseConnection = (params: AccountParams) =>
defHttp.get<AccountListGetResultModel>({ url: Api.TEStCONNECTTION, params });
export const addDataBaseInfo = (params: AccountListItem) =>
defHttp.post<AccountListGetResultModel>({ url: Api.ADDDATABASETABLE, params });
export const editDataBaseInfo = (params: AccountListItem) =>
defHttp.post<AccountListGetResultModel>({ url: Api.EDITDATABASETABLE+params.databaseLinkId,params });
export const delDataBaseInfo = (params: AccountListItem) =>
defHttp.post<AccountListGetResultModel>({ url: Api.DELETEDATABASETABLE+params.id, params });

View File

@ -0,0 +1,22 @@
import { BasicFetchResult } from '@/api/model/baseModel';
export interface AccountListItem {
databaseLinkId: string;
dbName: string;
dbAlias: string;
dbType: number;
serverAddress: string;
dbConnection: string;
description: string;
}
/**
* @description: Request list return value
*/
export interface AccountParams {
id?: string;
keyword?: string;
page?: string;
limit?: string;
};
export type AccountListGetResultModel = BasicFetchResult<AccountListItem>;

View File

@ -64,7 +64,7 @@ export function Post_AddForm(params: formModuleModel) {
// 编辑实体数据
export function Post_UpdateForm(params: formModuleModel) {
return defHttp.post<responsesmodel>({
url: Api.Post_UpdateForm,
url: Api.Post_UpdateForm + '?id=' + params.formModuleEntity.id,
params,
});
}

View File

@ -21,6 +21,7 @@ export type DeptParams = {
export type MenuParams = {
menuName?: string;
status?: string;
id?:string
};
export interface AccountListItem {
@ -35,11 +36,13 @@ export interface AccountListItem {
}
export interface DeptListItem {
id: string;
orderNo: string;
createTime: string;
remark: string;
status: number;
id?: string;
orderNo?: string;
createTime?: string;
remark?: string;
status?: number;
roleId?:string;
moduleIds?:any;
}
export interface MenuListItem {
@ -54,6 +57,7 @@ export interface MenuListItem {
export interface RoleListItem {
id: string;
name: string;
roleName: string;
roleValue: string;
status: number;

View File

@ -1,5 +1,4 @@
import { defHttp } from '@/utils/http/axios';
import { parseMinWidth } from 'element-plus/es/components/table/src/util';
import { DemoOptionsItem, selectParams, AccountListGetResultModel, AccountParams,NoOptionsParam } from './model/index';
enum Api {

View File

@ -4,6 +4,8 @@ export interface BasicPageParams {
}
export interface BasicFetchResult<T> {
moduleIds?: any;
elementIds?: any;
items: T[];
total: number;
}

View File

@ -1,35 +1,48 @@
// WFProcess 流程模版基本信息
import { defHttp } from '@/utils/http/axios';
import {CreateParams,DeleteDraftParams,RevokeAuditParams} from './model/WFProcessModel'
import {MyUncompletedParams} from './model/WFTaskModel'
import { CreateParams, DeleteDraftParams, RevokeAuditParams,LoadNextAuditorsParams } from './model/WFProcessModel'
import { MyUncompletedParams } from './model/WFTaskModel'
enum Api {
enum Api {
// 创建流程
Create = '/api/WFProcess/Create',
// 保存草稿
SaveDraft='/api/WFProcess/SaveDraft',
SaveDraft = '/api/WFProcess/SaveDraft',
// 我的流程
LoadMyPage='/api/WFProcess/LoadMyPage',
LoadMyPage = '/api/WFProcess/LoadMyPage',
// 我的草稿
LoadMyDraftPage='/api/WFProcess/LoadMyDraftPage',
LoadMyDraftPage = '/api/WFProcess/LoadMyDraftPage',
// 删除草稿
DeleteDraft='/api/WFProcess/DeleteDraft',
DeleteDraft = '/api/WFProcess/DeleteDraft',
// 催办
Urge='/api/WFProcess/Urge',
Urge = '/api/WFProcess/Urge',
// 撤销
Revoke='/api/WFProcess/Revoke',
Revoke = '/api/WFProcess/Revoke',
// 审核撤销
RevokeAudit='/api/WFProcess/RevokeAudit',
RevokeAudit = '/api/WFProcess/RevokeAudit',
// 获取流程图详情
GetBPMN='/api/WFProcess/GetBPMN'
GetBPMN = '/api/WFProcess/GetBPMN',
// 重新创建流程
CreateAgain = '/api/WFProcess/CreateAgain',
// 加签审核
SignAudit = '/api/WFProcess/SignAudit',
// 流程审核
Audit='/api/WFProcess/Audit',
// 获取下一节点审核人
LoadNextAuditors='/api/WFProcess/LoadNextAuditors',
}
/**
* @description: getLoadMyPage
*/
export function getLoadNextAuditors(params?: LoadNextAuditorsParams) {
return defHttp.get({ url: Api.LoadNextAuditors, params });
}
/**
* @description:
*/
export function create( params?:CreateParams) {
export function create(params?: CreateParams) {
return defHttp.post(
{
url: Api.Create,
@ -37,10 +50,43 @@ export function create( params?:CreateParams) {
},
);
}
/**
* @description:
*/
export function createAgain(params?: CreateParams) {
return defHttp.post(
{
url: Api.CreateAgain,
params,
},
);
}
/**
* @description:
*/
export function signAudit(id:String,params?: CreateParams) {
return defHttp.post(
{
url: Api.SignAudit+"?id="+id,
params,
},
);
}
/**
* @description:
*/
export function audit(id:String,params?: CreateParams) {
return defHttp.post(
{
url: Api.Audit+"?id="+id,
params,
},
);
}
/**
* @description: 稿
*/
export function saveDraft( params?:CreateParams) {
export function saveDraft(params?: CreateParams) {
return defHttp.post(
{
url: Api.SaveDraft,
@ -51,22 +97,22 @@ export function create( params?:CreateParams) {
/**
* @description: getLoadMyPage
*/
export function getLoadMyPage(params?: MyUncompletedParams) {
export function getLoadMyPage(params?: MyUncompletedParams) {
return defHttp.get({ url: Api.LoadMyPage, params });
}
/**
* @description: getLoadMyDraftPage
*/
export function getLoadMyDraftPage(params?: MyUncompletedParams) {
export function getLoadMyDraftPage(params?: MyUncompletedParams) {
return defHttp.get({ url: Api.LoadMyDraftPage, params });
}
/**
* @description: 稿
*/
export function deleteDraft( params:DeleteDraftParams) {
export function deleteDraft(params: DeleteDraftParams) {
return defHttp.post(
{
url: Api.DeleteDraft+"?id="+params.id,
url: Api.DeleteDraft + "?id=" + params.id,
params,
},
);
@ -74,10 +120,10 @@ export function create( params?:CreateParams) {
/**
* @description:
*/
export function urge( params:DeleteDraftParams) {
export function urge(params: DeleteDraftParams) {
return defHttp.post(
{
url: Api.Urge+"?id="+params.id,
url: Api.Urge + "?id=" + params.id,
params,
},
);
@ -85,10 +131,10 @@ export function create( params?:CreateParams) {
/**
* @description:
*/
export function revoke( params:DeleteDraftParams) {
export function revoke(params: DeleteDraftParams) {
return defHttp.post(
{
url: Api.Revoke+"?id="+params.id,
url: Api.Revoke + "?id=" + params.id,
params,
},
);
@ -96,10 +142,10 @@ export function create( params?:CreateParams) {
/**
* @description:
*/
export function revokeAudit(params:RevokeAuditParams) {
export function revokeAudit(params: RevokeAuditParams) {
return defHttp.post(
{
url: Api.RevokeAudit+"?id="+params.id+"&taskId="+params.taskId,
url: Api.RevokeAudit + "?id=" + params.id + "&taskId=" + params.taskId,
params,
},
);
@ -107,6 +153,6 @@ export function create( params?:CreateParams) {
/**
* @description: getPBMN
*/
export function getBPMN(params?: DeleteDraftParams) {
export function getBPMN(params: DeleteDraftParams) {
return defHttp.get({ url: Api.GetBPMN, params });
}

View File

@ -2,22 +2,22 @@
* @description:
*/
export interface CreateParams {
processId: string,
schemeCode: string,
title: string,
processId?: string,
schemeCode?: string,
title?: string,
userId?: string,
toUserId: string,
nextUsers: {
toUserId?: string,
nextUsers?: {
additionalProp1: string,
additionalProp2: string,
additionalProp3: string
},
des: string,
code: string,
name: string,
stampImg: string,
stampPassWord: string,
nextId: string
des?: string,
code?: string,
name?: string,
stampImg?: string,
stampPassWord?: string,
nextId?: string
}
/**
* @description: 稿
@ -32,3 +32,14 @@
id: string,
taskId:string,
}
/**
* @description:
*/
export interface LoadNextAuditorsParams {
code: string,
processId:string,
nodeId:string,
operationCode:string,
userId:string,
}

View File

@ -9,23 +9,23 @@ export interface CodeParams {
* @description:
*/
export interface AddParams {
itemName: string;
itemValue: string;
sortCode: number;
enabledMark: number;
description: string;
itemName?: string;
itemValue?: string;
sortCode?: number;
enabledMark?: number;
description?: string;
}
/**
* @description:
*/
export interface UpdateParams {
itemDetailId:string;
itemName: string;
itemValue: string;
sortCode: number;
enabledMark: number;
description: string;
itemDetailId?:string;
itemName?: string;
itemValue?: string;
sortCode?: number;
enabledMark?: number;
description?: string;
}
@ -39,7 +39,7 @@ export interface DeleteParams {
/**
* @description:
*/
export interface GetSysDataItemDetailModel {
export interface GetSysDataItemDetailItem {
itemDetailId: string;
itemId: string;
parentId: string;
@ -59,3 +59,4 @@ export interface GetSysDataItemDetailModel {
modifyUserId: string;
modifyUserName: string;
}
export type RoleListGetResultModel = GetSysDataItemDetailItem[];

View File

@ -12,7 +12,7 @@ export interface SchemeListParams {
* @description: \
*/
export interface DetailParams {
code: string;
code?: string;
}
/**

View File

@ -11,7 +11,7 @@ enum Api {
/**
* @description: postAdd
*/
export function postAdd(code:CodeParams, params:AddParams) {
export function postAdd(code:string, params?:AddParams) {
return defHttp.post(
{
url: Api.Add + "?code=" + code,

View File

@ -1,4 +1,5 @@
import SvgIcon from './src/SvgIcon.vue';
import IconPicker from './src/IconPicker.vue';
import Icon from './Icon.vue';
export { IconPicker, SvgIcon };
export { IconPicker, SvgIcon ,Icon};

View File

@ -0,0 +1 @@
export { default as PermissionBtn } from './index.vue';

View File

@ -1,26 +1,48 @@
<template>
<div class="process-design" :style="'display: flex; height:' + data.height">
<bpmn-process-designer v-model="data.xmlString" v-bind="data.controlForm" keyboard ref="processDesigner" :events="[
<bpmn-process-designer
v-model="data.xmlString"
v-bind="data.controlForm"
keyboard
ref="processDesigner"
:events="[
'element.click',
'connection.added',
'connection.removed',
'connection.changed',
'shape.removed'
]" @connection-added="connectionAdded" @connection-removed="connectionRemoved" @shape-removed="shapeRemoved"
@connection-changed="connectionChanged" @element-click="elementClick" @init-finished="initModeler"
@event="handlerEvent" @save="onSaveProcess" :schemeCode="data.schemeCode" :pageFlow="data.pageFlow"
:pageType="data.pageType" />
'shape.removed',
]"
@connection-added="connectionAdded"
@connection-removed="connectionRemoved"
@shape-removed="shapeRemoved"
@connection-changed="connectionChanged"
@element-click="elementClick"
@init-finished="initModeler"
@event="handlerEvent"
@save="onSaveProcess"
:schemeCode="data.schemeCode"
:pageFlow="data.pageFlow"
:pageType="data.pageType"
/>
<!-- 属性面板 -->
<bmpn-process-penal :bpmn-modeler="data.modeler" :prefix="data.controlForm.prefix" class="process-panel"
ref=processPanel :schemeCode="data.schemeCode" :pageView="data.pageView" :pageType="data.pageType" />
<bmpn-process-penal
:bpmn-modeler="data.modeler"
:prefix="data.controlForm.prefix"
class="process-panel"
ref="processPanel"
:schemeCode="data.schemeCode"
:pageView="data.pageView"
:pageType="data.pageType"
/>
</div>
</template>
<script lang="ts" setup>
import { h, reactive, onMounted, defineProps, computed, defineEmits, inject, ref ,watch} from 'vue';
import { reactive, defineProps, defineEmits, ref, watch } from 'vue';
import './package/theme/index.scss';
//
import { BpmnProcessDesigner, BmpnProcessPenal } from './package/index';
import { BpmnProcessDesigner } from './package/index';
import { BmpnProcessPenal } from './package/index';
import 'highlight.js/styles/atom-one-dark-reasonable.css';
import { flowStore } from '@/store/modules/flow';
@ -38,84 +60,79 @@
pageType: String,
//
pageFlow: String,
})
});
const data = reactive({
height: document.documentElement.clientHeight - 144.5 + "px;",
height: document.documentElement.clientHeight - 144.5 + 'px;',
xmlString: props.bpmnXml,
modeler: null,
controlForm: {
prefix: 'flowable',
},
element: null,
schemeCode:props.schemeCode,
pageView:props.pageView,
pageType:props.pageType,
pageFlow:props.pageFlow,
})
schemeCode: props.schemeCode,
pageView: props.pageView,
pageType: props.pageType,
pageFlow: props.pageFlow,
});
watch(
() => props.pageView,
(newVal, oldVal) => {
data.pageView=newVal
}
)
data.pageView = newVal;
},
);
watch(
() => props.pageFlow,
(newVal, oldVal) => {
data.pageFlow=newVal
}
)
data.pageFlow = newVal;
},
);
if (props.pageType == 'detail') {
data.height = document.documentElement.clientHeight - 294.5 + "px;"
data.height = document.documentElement.clientHeight - 294.5 + 'px;';
}
const processPanel = ref < any > ()
const processDesigner = ref < any > ()
const processPanel = ref<any>();
const processDesigner = ref<any>();
async function getFlow() {
let panel = await processPanel.value.getPanel()
let flow = await processDesigner.value.getFlow()
panel.scheme.flowContent = flow
return panel
let panel = await processPanel.value.getPanel();
let flow = await processDesigner.value.getFlow();
panel.scheme.flowContent = flow;
return panel;
}
async function validateFlow() {
let res = await processPanel.value.validatePanel()
return res
let res = await processPanel.value.validatePanel();
return res;
}
defineExpose({
getFlow,
validateFlow
})
validateFlow,
});
function connectionAdded(node) {
data.element = node;
console.log('connectionAdded')
console.log('connectionAdded');
}
function connectionRemoved(node) {
console.log(node)
console.log('connectionRemoved')
flowWfDataStore.deleteWfData(node)
console.log(node);
console.log('connectionRemoved');
flowWfDataStore.deleteWfData(node);
}
function shapeRemoved(node){
console.log('shapeRemoved')
flowWfDataStore.deleteWfData(node)
function shapeRemoved(node) {
console.log('shapeRemoved');
flowWfDataStore.deleteWfData(node);
}
function connectionChanged(node) {
data.element = node;
console.log('connectionChanged')
console.log('connectionChanged');
}
function elementClick(element) {
console.log('elementClick')
console.log('elementClick');
data.element = element;
}
function initModeler(modeler) {
console.log(modeler)
console.log(modeler);
setTimeout(() => {
data.modeler = modeler;
}, 10);
}
function handlerEvent(eventName, element) {
}
function handlerEvent(eventName, element) {}
function onSaveProcess(saveData) {
emit('save', saveData);
}
@ -130,7 +147,6 @@
body,
body * {
/* 滚动条 */
&::-webkit-scrollbar-track-piece {
background-color: #fff;
@ -172,4 +188,4 @@
.process-panel {
height: 100%;
}
</style>
</style>

View File

@ -41,13 +41,13 @@
</template>
<script lang="ts" setup>
import { h, provide, reactive, onMounted, defineProps, computed, defineEmits ,watch} from 'vue';
import { h, provide, reactive, onMounted, defineProps, defineEmits ,watch} from 'vue';
import { SaveOutlined, ZoomOutOutlined, ZoomInOutlined, RotateLeftOutlined, RotateRightOutlined, ClearOutlined } from '@ant-design/icons-vue';
//
import BpmnModeler from "bpmn-js/lib/Modeler";
import DefaultEmptyXML from "./plugins/defaultEmpty.ts";
import DefaultEmptyXML from "./plugins/defaultEmpty";
// ()
import customTranslate from "./plugins/translate/customTranslate.ts";
import customTranslate from "./plugins/translate/customTranslate";
import MoveModule from 'diagram-js/lib/features/move'
import ModelingModule from 'bpmn-js/lib/features/modeling'
@ -58,8 +58,17 @@
import { flowStore } from '@/store/modules/flow';
const flowWfDataStore = flowStore();
// json
import convert from "xml-js";
const process = reactive({
interface processType{
defaultZoom: number,
previewModelVisible: boolean,
simulationStatus: boolean,
previewResult: string,
previewType: string,
recoverable: boolean,
revocable: boolean,
bpmnModeler: any
}
const process:processType = reactive({
defaultZoom: 1,
previewModelVisible: false,
simulationStatus: false,
@ -70,6 +79,14 @@
bpmnModeler: null
})
const props = defineProps({
processId:{
type:String,
default:''
},
processName:{
type:String,
default:''
},
value: String, // xml
prefix: {
type: String,
@ -111,8 +128,6 @@
})
async function getDetailInfo(a) {
let data = await getDetail({ code: props.schemeCode })
let scheme = JSON.parse(data.scheme.content);
let wfData = scheme.wfData
if (a == 1) {
createNewDiagram(data.scheme.flowContent)
}
@ -130,7 +145,6 @@
}
function initBpmnModeler() {
if (process.bpmnModeler) return;
const containerEl = document.querySelector('#bpmn-canvas');
process.bpmnModeler = new BpmnModeler({
container: '#bpmn-canvas',
additionalModules: [
@ -144,7 +158,6 @@
}
function initModelListeners() {
const EventBus = process.bpmnModeler.get("eventBus");
const that = this;
// , . - ,
props.events.forEach(event => {
EventBus.on(event, function (eventObj) {
@ -220,10 +233,6 @@
process.defaultZoom = newZoom;
process.bpmnModeler.get("canvas").zoom(process.defaultZoom);
}
function processReZoom() {
process.defaultZoom = 1;
process.bpmnModeler.get("canvas").zoom("fit-viewport", "auto");
}
function processRestart() {
process.recoverable = false;
process.revocable = false;
@ -231,20 +240,20 @@
flowWfDataStore.setWfDataAll([])
}
/*----------------------------- 方法结束 ---------------------------------*/
function previewProcessXML() {
process.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
process.previewResult = xml;
process.previewType = "xml";
process.previewModelVisible = true;
});
}
function previewProcessJson() {
process.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
process.previewResult = convert.xml2json(xml, { spaces: 2 });
process.previewType = "json";
process.previewModelVisible = true;
});
}
// function previewProcessXML() {
// process.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
// process.previewResult = xml;
// process.previewType = "xml";
// process.previewModelVisible = true;
// });
// }
// function previewProcessJson() {
// process.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
// process.previewResult = convert.xml2json(xml, { spaces: 2 });
// process.previewType = "json";
// process.previewModelVisible = true;
// });
// }
async function getFlow() {
let flowContent
await process.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {

View File

@ -1,172 +1,186 @@
<template>
<div class="auth-config">
<a-tabs v-model:activeKey="authType" type="card" size="small">
<a-tab-pane key="1" tab="所有成员">
<a-alert message="权限说明" description="所有人员指不限制流程模版的发起人员,表示每个人都能发起该流程模版。" type="info" show-icon />
</a-tab-pane>
<a-tab-pane key="2" tab="指定成员">
<a-space>
<a-radio-group>
<a-radio-button value="1" @click="handlePostClick"></a-radio-button>
<a-radio-button value="2" @click="handleRoleClick"></a-radio-button>
<a-radio-button value="3" @click="handleAccountClick"></a-radio-button>
</a-radio-group>
<a-button danger :size="size">清空</a-button>
</a-space>
<a-table size="small" :columns="columns" :data-source="dataSource" bordered :pagination="false">
<template #bodyCell="{ column, text, record }">
<template v-if="['name'].includes(column.dataIndex)">
<div>
{{ text }}
</div>
</template>
<template v-else-if="[ 'type'].includes(column.dataIndex)">
<div>
{{ typeFormat(text) }}
</div>
</template>
<template v-else-if="column.dataIndex === 'operation'">
<a-popconfirm v-if="dataSource.length" title="确定要删除吗?"
@confirm="onDelete(record.name)">
<delete-outlined two-tone-color='#eb2f96' />
</a-popconfirm>
</template>
</template>
</a-table>
</a-tab-pane>
</a-tabs>
<a-modal width="60%" v-model:open="data.postOpen" title="添加岗位" @ok="postHandleOk">
<SelectPos ref="posRef"></SelectPos>
</a-modal>
<a-modal width="60%" v-model:open="data.roleOpen" title="添加角色" @ok="roleHandleOk">
<SelectRole ref="roleRef"></SelectRole>
</a-modal>
<a-modal width="60%" v-model:open="data.accountOpen" title="添加角色" @ok="accountHandleOk">
<SelectAccount ref="accountRef"></SelectAccount>
</a-modal>
</div>
<div class="auth-config">
<a-tabs v-model:activeKey="authType" type="card" size="small">
<a-tab-pane key="1" tab="所有成员">
<a-alert
message="权限说明"
description="所有人员指不限制流程模版的发起人员,表示每个人都能发起该流程模版。"
type="info"
show-icon
/>
</a-tab-pane>
<a-tab-pane key="2" tab="指定成员">
<a-space>
<a-radio-group>
<a-radio-button value="1" @click="handlePostClick"></a-radio-button>
<a-radio-button value="2" @click="handleRoleClick"></a-radio-button>
<a-radio-button value="3" @click="handleAccountClick"></a-radio-button>
</a-radio-group>
<a-button danger>清空</a-button>
</a-space>
<a-table
size="small"
:columns="columns"
:data-source="dataSource"
bordered
:pagination="false"
>
<template #bodyCell="{ column, text, record }">
<template v-if="['name'].includes(column.dataIndex)">
<div>
{{ text }}
</div>
</template>
<template v-else-if="['type'].includes(column.dataIndex)">
<div>
{{ typeFormat(text) }}
</div>
</template>
<template v-else-if="column.dataIndex === 'operation'">
<a-popconfirm
v-if="dataSource.length"
title="确定要删除吗?"
@confirm="onDelete(record.name)"
>
<delete-outlined two-tone-color="#eb2f96" />
</a-popconfirm>
</template>
</template>
</a-table>
</a-tab-pane>
</a-tabs>
<a-modal width="60%" v-model:open="data.postOpen" title="添加岗位" @ok="postHandleOk">
<SelectPos ref="posRef"></SelectPos>
</a-modal>
<a-modal width="60%" v-model:open="data.roleOpen" title="添加角色" @ok="roleHandleOk">
<SelectRole ref="roleRef"></SelectRole>
</a-modal>
<a-modal width="60%" v-model:open="data.accountOpen" title="添加角色" @ok="accountHandleOk">
<SelectAccount ref="accountRef"></SelectAccount>
</a-modal>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted, nextTick, unref } from 'vue';
let authType = ref("1")
import { cloneDeep } from 'lodash-es';
import type { UnwrapRef } from 'vue';
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue'
import SelectPos from '@/components/SelectPos/index.vue';
import SelectRole from '@/components/SelectRole/index.vue';
import SelectAccount from '@/components/SelectAccount/index.vue';
const columns = [
{
title: '名称',
dataIndex: 'name',
},
{
title: '类型',
dataIndex: 'type',
},
{
title: '操作',
dataIndex: 'operation',
},
import { reactive, ref} from 'vue';
let authType = ref('1');
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue';
import { SelectPos } from '@/components/SelectPos/index';
import { SelectRole } from '@/components/SelectRole/index';
import { SelectAccount } from '@/components/SelectAccount/index';
const columns = [
{
title: '名称',
dataIndex: 'name',
},
{
title: '类型',
dataIndex: 'type',
},
{
title: '操作',
dataIndex: 'operation',
},
];
let dataSource = ref([]);
const data = reactive({
postOpen: false,
roleOpen: false,
accountOpen: false,
});
function typeFormat(type) {
type = type.toString();
switch (type) {
case '1':
return '岗位';
case '2':
return '角色';
case '3':
return '用户';
case '4':
return '上下级';
case '5':
return '节点';
case '6':
return '表字段';
}
}
function addTableData(selectData) {
let addData = selectData.filter((t) => dataSource.value.findIndex((t2) => t2.id == t.id) == -1);
dataSource.value = dataSource.value.concat(addData);
}
//
const posRef = ref<any>();
];
let dataSource = ref([])
const data = reactive({
postOpen: false,
roleOpen: false,
accountOpen: false,
})
function typeFormat(type) {
type=type.toString()
switch (type) {
case '1':
return '岗位'
case '2':
return '角色'
case '3':
return '用户'
case '4':
return '上下级'
case '5':
return '节点'
case '6':
return '表字段'
}
}
function addTableData(selectData) {
let addData = selectData.filter(t => dataSource.value.findIndex(t2 => t2.id == t.id) == -1);
dataSource.value = dataSource.value.concat(addData);
}
//
const posRef = ref < any > ()
function handlePostClick() {
data.postOpen = true;
}
function postHandleOk() {
let selectData = posRef.value.getRow().map((t) => {
return { type: '1', id: t.id, name: t.name };
});
addTableData(selectData);
data.postOpen = false;
}
//
const roleRef = ref<any>();
function handlePostClick() {
data.postOpen = true;
}
function postHandleOk() {
let selectData = posRef.value.getRow().map(t => {
return { type: '1', id: t.id, name: t.name }
});
addTableData(selectData);
data.postOpen = false;
}
//
const roleRef = ref < any > ()
function handleRoleClick() {
data.roleOpen = true;
}
function roleHandleOk() {
let selectData = roleRef.value.getRow().map(t => { return { type: '2', id: t.id, name: t.name, condition: '' } });
addTableData(selectData);
data.roleOpen = false;
}
//
const accountRef = ref < any > ()
function handleAccountClick() {
data.accountOpen = true;
}
function accountHandleOk() {
let selectData = accountRef.value.getRow().map(t => { return { type: '3', id: t.id, name: t.name } });
addTableData(selectData);
data.accountOpen = false;
}
function onDelete(key) {
dataSource.value = dataSource.value.filter(item => item.name !== key);
}
function setForm(data) {
console.log(data)
authType.value = data.authType.toString()
dataSource.value = data.authData
}
function getForm() {
return {
authType: authType.value,
authData: dataSource.value
}
}
defineExpose({
getForm,
setForm
})
function handleRoleClick() {
data.roleOpen = true;
}
function roleHandleOk() {
let selectData = roleRef.value.getRow().map((t) => {
return { type: '2', id: t.id, name: t.name, condition: '' };
});
addTableData(selectData);
data.roleOpen = false;
}
//
const accountRef = ref<any>();
function handleAccountClick() {
data.accountOpen = true;
}
function accountHandleOk() {
let selectData = accountRef.value.getRow().map((t) => {
return { type: '3', id: t.id, name: t.name };
});
addTableData(selectData);
data.accountOpen = false;
}
function onDelete(key) {
dataSource.value = dataSource.value.filter((item) => item.name !== key);
}
function setForm(data) {
console.log(data);
authType.value = data.authType.toString();
dataSource.value = data.authData;
}
function getForm() {
return {
authType: authType.value,
authData: dataSource.value,
};
}
defineExpose({
getForm,
setForm,
});
</script>
<style lang="less" scoped>
.site-space-compact-wrapper {
width: 100%;
.site-space-compact-wrapper {
width: 100%;
.ant-select {
width: 100%;
}
.ant-select {
width: 100%;
}
}
::v-deep .ant-tabs {
padding: 0 !important;
}
::v-deep .ant-tabs {
padding: 0 !important;
}
::v-deep .ant-table-content {
margin-top: 10px;
}
</style>
::v-deep .ant-table-content {
margin-top: 10px;
}
</style>

View File

@ -1,7 +1,14 @@
<!-- 开始节点配置 -->
<template>
<div class="end-event">
<a-form ref="formRef" :model="node" labelAlign="left" :disabled="data.componentDisabled" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-form
ref="formRef"
:model="node"
labelAlign="left"
:disabled="data.componentDisabled"
:label-col="labelCol"
:wrapper-col="wrapperCol"
>
<a-form-item label="节点标识">
<a-input v-model:value="node.id" placeholder="请输入" readonly />
</a-form-item>
@ -10,39 +17,38 @@
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted, nextTick, unref, h, watch, defineProps } from 'vue';
import { reactive, ref, watch, defineProps } from 'vue';
import { flowStore } from '@/store/modules/flow';
const flowWfDataStore = flowStore();
const node = ref({})
const node: any = ref({});
const props = defineProps({
element: Object,
pageType:String
})
pageType: String,
});
watch(
() => props.element,
(newVal, oldVal) => {
if(newVal.type == "bpmn:EndEvent"){
const currentNode = flowWfDataStore.getWfDataNode(newVal.id)
if (newVal.type == 'bpmn:EndEvent') {
const currentNode = flowWfDataStore.getWfDataNode(newVal.id);
if (currentNode) {
node.value = currentNode
node.value = currentNode;
} else {
node.value = newVal
node.value = newVal;
}
}
}
)
},
);
const labelCol = { span: 7 };
const wrapperCol = { span: 17 };
const data=reactive({
componentDisabled: props.pageType == 'detail' ? true : false
})
const data = reactive({
componentDisabled: props.pageType == 'detail' ? true : false,
});
function getForm() {
return node
return node;
}
defineExpose({
getForm
})
getForm,
});
</script>
<style>
</style>
<style></style>

View File

@ -0,0 +1,2 @@
export { default as conditionFormula } from './src/conditionFormula.vue';
export { default as conditionSql } from './src/conditionSql.vue';

View File

@ -1,6 +1,6 @@
<template>
<div class="user-task">
<a-form ref="formRef" :rules="rules" :model="node" labelAlign="left" :label-col="labelCol"
<a-form ref="formRef" :model="node" labelAlign="left" :label-col="labelCol"
:wrapper-col="wrapperCol" :disabled="data.componentDisabled">
<a-form-item label="节点标识">
<a-input v-model:value="node.id" placeholder="请输入" readonly />
@ -11,7 +11,7 @@
<a-radio-button value="1" @click="handleFormulaClick"></a-radio-button>
<a-radio-button value="2" @click="handleSQlClick">sql</a-radio-button>
</a-radio-group>
<a-button danger :size="size" @click="handleClearClick"></a-button>
<a-button danger @click="handleClearClick"></a-button>
</a-space>
<a-table :columns="data.columns" :data-source="node.conditions" bordered :pagination="false">
<template #bodyCell="{ column, text, record }">
@ -42,10 +42,9 @@
</template>
<script lang="ts" setup>
import conditionFormula from '../exclusiveGateway/src/conditionFormula.vue'
import conditionSql from '../exclusiveGateway/src/conditionSql.vue'
import { getDetail } from '@/api/sys/WFSchemeInfo'
import { reactive, ref, onMounted, nextTick, unref, h, watch, defineProps } from 'vue';
import {conditionFormula} from '../exclusiveGateway/index'
import {conditionSql} from '../exclusiveGateway/index'
import { reactive, ref, onMounted, watch, defineProps } from 'vue';
import { buildGUID } from '@/utils/uuid';
import { flowStore } from '@/store/modules/flow';
const flowWfDataStore = flowStore();
@ -59,7 +58,7 @@
pageType: String,
pageView: String,
})
const node = ref({
const node:any = ref({
conditions: [],
id: ''
})
@ -92,9 +91,7 @@
componentDisabled: props.pageType == 'detail' ? true : false
})
function updateWfData(key) {
flowWfDataStore.updataWfDataNode(node.value.id, key, node.value[key])
}
onMounted(() => {
})
@ -169,7 +166,7 @@
}
function onEdit(record) {
data.isEdit = true
if (data.type == 1) {
if (record.type == 1) {
data.formulaVisible = true;
conditionFormulaRef.value.setForm(record)
} else {

View File

@ -16,14 +16,14 @@
</template>
<script lang="ts" setup>
import { getDetail } from '@/api/sys/WFSchemeInfo'
import { ref, reactive, defineProps, onMounted, watch } from 'vue'
import { flowStore } from '@/store/modules/flow';
const flowWfDataStore = flowStore();
const props = defineProps({
element: Object,
pageType:String
})
let node = ref({})
let node:any = ref({})
const data = reactive({
conditionsOptions: [],
componentDisabled: props.pageType == 'detail' ? true : false

View File

@ -0,0 +1,11 @@
export { default as shcemeinfoConfig } from './shcemeInfo/index.vue';
export { default as authConfig } from './auth/index.vue';
export { default as StartEventOption } from './startEvent/index.vue';
export { default as userTaskOption } from './userTask/index.vue';
export { default as endEventOption } from './endEvent/index.vue';
export { default as parallelGatewayOption } from './parallelGateway/index.vue';
export { default as exclusiveGatewayOption } from './exclusiveGateway/index.vue';
export { default as inclusiveGatewayOption } from './inclusiveGateway/index.vue';
export { default as gatewayXorOption } from './config/gatewayXor.vue';
export { default as subprocessOption } from './subprocess/index.vue';
export { default as mylineOption } from './myline/index.vue';

View File

@ -13,8 +13,7 @@
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted, nextTick, unref, h, watch, defineProps } from 'vue';
import { getDetail } from '@/api/sys/WFSchemeInfo'
import { reactive, ref, onMounted, watch, defineProps } from 'vue';
import { flowStore } from '@/store/modules/flow';
const flowWfDataStore = flowStore();
const labelCol = { span: 7 };

View File

@ -1,268 +1,321 @@
<template>
<div class="shceme-info">
<a-form ref="formRef" :rules="rules" :model="formState" labelAlign="left" :label-col="labelCol"
:wrapper-col="wrapperCol" :disabled="data.componentDisabled">
<template v-if="!data.componentDisabled">
<a-form-item label="模板编号" name="code">
<a-input v-model:value="formState.code" placeholder="请输入" />
</a-form-item>
<a-form-item label="模板名称" name="name">
<a-input v-model:value="formState.name" placeholder="请输入" />
</a-form-item>
<a-form-item label="模板图标" name="icon">
<IconPicker v-model:value="formState.icon" />
</a-form-item>
<a-form-item label="图标颜色" name="color">
<a-input type="color" v-model="formState.color" placeholder="请输入"></a-input>
</a-form-item>
<a-form-item label="模板分类" name="category">
<a-select v-model:value="formState.category" placeholder="请选择" :options="data.optionsType"
:field-names="{ label: 'itemName', value: 'itemValue' }">
</a-select>
</a-form-item>
<a-form-item label="我的任务创建">
<a-radio-group v-model:value="formState.mark" name="radioGroup">
<a-radio v-for="item in data.optionsNotOrOk" :value="item.value">{{item.label}}</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="移动端创建">
<a-radio-group v-model:value="formState.isInApp" name="radioGroup">
<a-radio v-for="item in data.optionsNotOrOk" :value="item.value">{{item.label}}</a-radio>
</a-radio-group>
</a-form-item>
<a-textarea v-model:value="formState.description" placeholder="请填写备注"
:auto-size="{ minRows: 5, maxRows: 8 }" />
</template>
<a-divider plain="true">撤销操作</a-divider>
<a-tabs v-model:activeKey="formState.undoType" type="card" size="small" centered="true">
<a-tab-pane key="1" tab="执行SQL">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-select v-model:value="formState.undoDbCode" placeholder="请选择执行SQL数据库" :options="sqlOptions"
:field-names="{ label: 'text', value: 'id',options :'childNodes' }">
</a-select>
</a-space-compact>
<a-space-compact block>
<a-textarea v-model:value="formState.undoDbSQL"
placeholder="请填写SQL语句参数有 @processId流程进程主键 @userId用户Id @userAccount用户账号 @companyId用户公司 @departmentId用户部门"
:auto-size="{ minRows: 5, maxRows: 8 }" />
</a-space-compact>
</a-space>
</a-tab-pane>
<a-tab-pane key="2" tab=".NET方法">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-textarea v-model:value="formState.undoIOCName" placeholder="请填写.NET方法IOC别名"
:auto-size="{ minRows: 5, maxRows: 8 }" />
</a-space-compact>
</a-space>
</a-tab-pane>
<a-tab-pane key="3" tab="第三方接口">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-textarea v-model:value="formState.undoUrl"
placeholder="请填写第三方接口地址(POST),JSON 格式,参数有 userId用户Id,userAccount用户账号,companyId用户公司,departmentId用户部门"
:auto-size="{ minRows: 5, maxRows: 8 }" />
</a-space-compact>
</a-space>
</a-tab-pane>
</a-tabs>
<div class="shceme-info">
<a-form
ref="formRef"
:rules="rules"
:model="formState"
labelAlign="left"
:label-col="labelCol"
:wrapper-col="wrapperCol"
:disabled="data.componentDisabled"
>
<template v-if="!data.componentDisabled">
<a-form-item label="模板编号" name="code">
<a-input v-model:value="formState.code" placeholder="请输入" />
</a-form-item>
<a-form-item label="模板名称" name="name">
<a-input v-model:value="formState.name" placeholder="请输入" />
</a-form-item>
<a-form-item label="模板图标" name="icon">
<IconPicker v-model:value="formState.icon" />
</a-form-item>
<a-form-item label="图标颜色" name="color">
<a-input type="color" v-model="formState.color" placeholder="请输入"></a-input>
</a-form-item>
<a-form-item label="模板分类" name="category">
<a-select
v-model:value="formState.category"
placeholder="请选择"
:options="data.optionsType"
:field-names="{ label: 'itemName', value: 'itemValue' }"
>
</a-select>
</a-form-item>
<a-form-item label="我的任务创建">
<a-radio-group v-model:value="formState.mark" name="radioGroup">
<a-radio
v-for="(item, index) in data.optionsNotOrOk"
:key="index"
:value="item.value"
>{{ item.label }}</a-radio
>
</a-radio-group>
</a-form-item>
<a-form-item label="移动端创建">
<a-radio-group v-model:value="formState.isInApp" name="radioGroup">
<a-radio
v-for="(item, index) in data.optionsNotOrOk"
:key="index"
:value="item.value"
>{{ item.label }}</a-radio
>
</a-radio-group>
</a-form-item>
<a-textarea
v-model:value="formState.description"
placeholder="请填写备注"
:auto-size="{ minRows: 5, maxRows: 8 }"
/>
</template>
<a-divider plain="true">撤销操作</a-divider>
<a-tabs v-model:activeKey="formState.undoType" type="card" size="small" centered="true">
<a-tab-pane key="1" tab="执行SQL">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-select
v-model:value="formState.undoDbCode"
placeholder="请选择执行SQL数据库"
:options="sqlOptions"
:field-names="{ label: 'text', value: 'id', options: 'childNodes' }"
>
</a-select>
</a-space-compact>
<a-space-compact block>
<a-textarea
v-model:value="formState.undoDbSQL"
placeholder="请填写SQL语句参数有 @processId流程进程主键 @userId用户Id @userAccount用户账号 @companyId用户公司 @departmentId用户部门"
:auto-size="{ minRows: 5, maxRows: 8 }"
/>
</a-space-compact>
</a-space>
</a-tab-pane>
<a-tab-pane key="2" tab=".NET方法">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-textarea
v-model:value="formState.undoIOCName"
placeholder="请填写.NET方法IOC别名"
:auto-size="{ minRows: 5, maxRows: 8 }"
/>
</a-space-compact>
</a-space>
</a-tab-pane>
<a-tab-pane key="3" tab="第三方接口">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-textarea
v-model:value="formState.undoUrl"
placeholder="请填写第三方接口地址(POST),JSON 格式,参数有 userId用户Id,userAccount用户账号,companyId用户公司,departmentId用户部门"
:auto-size="{ minRows: 5, maxRows: 8 }"
/>
</a-space-compact>
</a-space>
</a-tab-pane>
</a-tabs>
<a-divider plain="true">作废操作</a-divider>
<a-tabs v-model:activeKey="formState.deleteType" type="card" size="small" centered="true">
<a-tab-pane key="1" tab="执行SQL">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-select v-model:value="formState.deleteDbCode" placeholder="请选择执行SQL数据库" :options="sqlOptions"
:field-names="{ label: 'text', value: 'id',options :'childNodes' }">
</a-select>
</a-space-compact>
<a-space-compact block>
<a-textarea v-model:value="formState.deleteDbSQL"
placeholder="请填写SQL语句参数有 @processId流程进程主键 @userId用户Id @userAccount用户账号 @companyId用户公司 @departmentId用户部门"
:auto-size="{ minRows: 5, maxRows: 8 }" />
</a-space-compact>
</a-space>
</a-tab-pane>
<a-tab-pane key="2" tab=".NET方法">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-textarea v-model:value="formState.deleteIOCName" placeholder="请填写.NET方法IOC别名"
:auto-size="{ minRows: 5, maxRows: 8 }" />
</a-space-compact>
</a-space>
</a-tab-pane>
<a-tab-pane key="3" tab="第三方接口">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-textarea v-model:value="formState.undoUrl"
placeholder="请填写第三方接口地址(POST),JSON 格式,参数有 userId用户Id,userAccount用户账号,companyId用户公司,departmentId用户部门"
:auto-size="{ minRows: 5, maxRows: 8 }" />
</a-space-compact>
</a-space>
</a-tab-pane>
</a-tabs>
<a-divider plain="true">作废操作</a-divider>
<a-tabs v-model:activeKey="formState.deleteType" type="card" size="small" centered="true">
<a-tab-pane key="1" tab="执行SQL">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-select
v-model:value="formState.deleteDbCode"
placeholder="请选择执行SQL数据库"
:options="sqlOptions"
:field-names="{ label: 'text', value: 'id', options: 'childNodes' }"
>
</a-select>
</a-space-compact>
<a-space-compact block>
<a-textarea
v-model:value="formState.deleteDbSQL"
placeholder="请填写SQL语句参数有 @processId流程进程主键 @userId用户Id @userAccount用户账号 @companyId用户公司 @departmentId用户部门"
:auto-size="{ minRows: 5, maxRows: 8 }"
/>
</a-space-compact>
</a-space>
</a-tab-pane>
<a-tab-pane key="2" tab=".NET方法">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-textarea
v-model:value="formState.deleteIOCName"
placeholder="请填写.NET方法IOC别名"
:auto-size="{ minRows: 5, maxRows: 8 }"
/>
</a-space-compact>
</a-space>
</a-tab-pane>
<a-tab-pane key="3" tab="第三方接口">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-textarea
v-model:value="formState.undoUrl"
placeholder="请填写第三方接口地址(POST),JSON 格式,参数有 userId用户Id,userAccount用户账号,companyId用户公司,departmentId用户部门"
:auto-size="{ minRows: 5, maxRows: 8 }"
/>
</a-space-compact>
</a-space>
</a-tab-pane>
</a-tabs>
<a-divider plain="true">删除草稿</a-divider>
<a-tabs v-model:activeKey="formState.deleteDraftType" type="card" size="small" centered="true">
<a-tab-pane key="1" tab="执行SQL">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-select v-model:value="formState.deleteDraftDbCode" placeholder="请选择执行SQL数据库" :options="sqlOptions"
:field-names="{ label: 'text', value: 'id',options :'childNodes' }">
</a-select>
</a-space-compact>
<a-space-compact block>
<a-textarea v-model:value="formState.deleteDraftDbSQL"
placeholder="请填写SQL语句参数有 @processId流程进程主键 @userId用户Id @userAccount用户账号 @companyId用户公司 @departmentId用户部门"
:auto-size="{ minRows: 5, maxRows: 8 }" />
</a-space-compact>
</a-space>
</a-tab-pane>
<a-tab-pane key="2" tab=".NET方法">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-textarea v-model:value="formState.deleteDraftIOCName" placeholder="请填写.NET方法IOC别名"
:auto-size="{ minRows: 5, maxRows: 8 }" />
</a-space-compact>
</a-space>
</a-tab-pane>
<a-tab-pane key="3" tab="第三方接口">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-textarea v-model:value="formState.undoUrl"
placeholder="请填写第三方接口地址(POST),JSON 格式,参数有 userId用户Id,userAccount用户账号,companyId用户公司,departmentId用户部门"
:auto-size="{ minRows: 5, maxRows: 8 }" />
</a-space-compact>
</a-space>
</a-tab-pane>
</a-tabs>
</a-form>
</div>
<a-divider plain="true">删除草稿</a-divider>
<a-tabs
v-model:activeKey="formState.deleteDraftType"
type="card"
size="small"
centered="true"
>
<a-tab-pane key="1" tab="执行SQL">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-select
v-model:value="formState.deleteDraftDbCode"
placeholder="请选择执行SQL数据库"
:options="sqlOptions"
:field-names="{ label: 'text', value: 'id', options: 'childNodes' }"
>
</a-select>
</a-space-compact>
<a-space-compact block>
<a-textarea
v-model:value="formState.deleteDraftDbSQL"
placeholder="请填写SQL语句参数有 @processId流程进程主键 @userId用户Id @userAccount用户账号 @companyId用户公司 @departmentId用户部门"
:auto-size="{ minRows: 5, maxRows: 8 }"
/>
</a-space-compact>
</a-space>
</a-tab-pane>
<a-tab-pane key="2" tab=".NET方法">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-textarea
v-model:value="formState.deleteDraftIOCName"
placeholder="请填写.NET方法IOC别名"
:auto-size="{ minRows: 5, maxRows: 8 }"
/>
</a-space-compact>
</a-space>
</a-tab-pane>
<a-tab-pane key="3" tab="第三方接口">
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
<a-space-compact block>
<a-textarea
v-model:value="formState.undoUrl"
placeholder="请填写第三方接口地址(POST),JSON 格式,参数有 userId用户Id,userAccount用户账号,companyId用户公司,departmentId用户部门"
:auto-size="{ minRows: 5, maxRows: 8 }"
/>
</a-space-compact>
</a-space>
</a-tab-pane>
</a-tabs>
</a-form>
</div>
</template>
<script lang="ts" setup>
import { Dayjs } from 'dayjs';
import { reactive, ref, toRaw, onMounted, defineProps } from 'vue';
import type { UnwrapRef } from 'vue';
import type { Rule } from 'ant-design-vue/es/form';
import { IconPicker } from '/@/components/Icon';
import { getLoad } from '@/api/sys/sysDataItemDetail';
import { reactive, ref, onMounted, defineProps } from 'vue';
import type { Rule } from 'ant-design-vue/es/form';
import { IconPicker } from '@/components/Icon/index';
import { getLoad } from '@/api/sys/sysDataItemDetail';
import { getLoadDataBaseLinkTree } from '@/api/demo/system';
const formRef = ref();
const labelCol = { span: 7 };
const wrapperCol = { span: 17 };
const activeKey = ref('1')
const props = defineProps({
pageType: String,
})
const data = reactive({
optionsNotOrOk: [{ label: '允许', value: 1 }, { label: '不允许', value: 2 }],
optionsType: [],
componentDisabled: props.pageType == 'detail' ? true : false,
})
const sqlOptions =ref([])
const formRef = ref();
const labelCol = { span: 7 };
const wrapperCol = { span: 17 };
const props = defineProps({
pageType: String,
});
const data = reactive({
optionsNotOrOk: [
{ label: '允许', value: 1 },
{ label: '不允许', value: 2 },
],
optionsType: [],
componentDisabled: props.pageType == 'detail' ? true : false,
});
const sqlOptions = ref([]);
let formState = ref({
code: '',
name: '',
category: '',
enabledMark: 1,
mark: 1,
isInApp: 2,
description: '',
let formState = ref({
code: '',
name: '',
category: '',
enabledMark: 1,
mark: 1,
isInApp: 2,
description: '',
titleRules: '',
titleRules: '',
undoType: "1",
undoDbCode: '',
undoDbSQL: '',
undoIOCName: '',
undoUrl: '',
undoType: '1',
undoDbCode: '',
undoDbSQL: '',
undoIOCName: '',
undoUrl: '',
deleteType: "1",
deleteDbCode: '',
deleteDbSQL: '',
deleteIOCName: '',
deleteUrl: '',
deleteType: '1',
deleteDbCode: '',
deleteDbSQL: '',
deleteIOCName: '',
deleteUrl: '',
deleteDraftType: "1",
deleteDraftDbCode: '',
deleteDraftDbSQL: '',
deleteDraftIOCName: '',
deleteDraftUrl: '',
icon: 'ant-design:appstore-outlined',
color: '#409EFF',
});
const rules: Record<string, Rule[]> = {
code: [
{ required: true, message: '请输入模板编号' },
// { validator: lr_existDbFiled, keyValue: () => { return data.formData.f_Id }, tableName: 'lr_wf_schemeinfo', keyName: 'f_Id', trigger: 'blur' }
],
name: [
{ required: true, message: '请输入模板名称' }
],
category: [
{ required: true, message: '请选择模板分类' }
],
icon: [
{ required: true, message: '请选择图标' }
],
color: [
{ required: true, message: '请选择颜色' }
],
};
async function getSQL(){
const data = await getLoadDataBaseLinkTree()
data.forEach(element => {
if(element.childNodes == null){
element.childNodes = []
}
});
sqlOptions.value = data
}
async function fetch() {
let list = await getLoad({ code: 'FlowSort' });
data.optionsType = list
}
async function validateForm() {
let res = await formRef.value
.validate()
.then((values) => {
return true
})
.catch((error: ValidateErrorEntity<FormState>) => {
return false
});
return res
}
function setForm(data) {
formState.value = data
}
function getForm() {
return formState.value
}
defineExpose({
setForm,
getForm,
validateForm
})
onMounted(() => {
fetch();
getSQL()
deleteDraftType: '1',
deleteDraftDbCode: '',
deleteDraftDbSQL: '',
deleteDraftIOCName: '',
deleteDraftUrl: '',
icon: 'ant-design:appstore-outlined',
color: '#409EFF',
});
const rules: Record<string, Rule[]> = {
code: [
{ required: true, message: '请输入模板编号' },
// { validator: lr_existDbFiled, keyValue: () => { return data.formData.f_Id }, tableName: 'lr_wf_schemeinfo', keyName: 'f_Id', trigger: 'blur' }
],
name: [{ required: true, message: '请输入模板名称' }],
category: [{ required: true, message: '请选择模板分类' }],
icon: [{ required: true, message: '请选择图标' }],
color: [{ required: true, message: '请选择颜色' }],
};
async function getSQL() {
const data = await getLoadDataBaseLinkTree();
data.forEach((element) => {
if (element.childNodes == null) {
element.childNodes = [];
}
});
sqlOptions.value = data;
}
async function fetch() {
let list = await getLoad({ code: 'FlowSort' });
data.optionsType = list;
}
async function validateForm() {
let res = await formRef.value
.validate()
.then((values) => {
return true;
})
.catch((error) => {
return false;
});
return res;
}
function setForm(data) {
formState.value = data;
}
function getForm() {
return formState.value;
}
defineExpose({
setForm,
getForm,
validateForm,
});
onMounted(() => {
fetch();
getSQL();
});
</script>
<style lang="less" scoped>
.site-space-compact-wrapper {
width: 100%;
.site-space-compact-wrapper {
width: 100%;
.ant-select {
width: 100%;
}
.ant-select {
width: 100%;
}
}
::v-deep .ant-tabs {
padding: 0 !important;
}
</style>
::v-deep .ant-tabs {
padding: 0 !important;
}
</style>

View File

@ -1,8 +1,14 @@
<!-- 开始节点配置 -->
<template>
<div class="subprocess">
<a-form ref="formRef" :model="node" labelAlign="left" :label-col="labelCol" :wrapper-col="wrapperCol"
:disabled="data.componentDisabled">
<a-form
ref="formRef"
:model="node"
labelAlign="left"
:label-col="labelCol"
:wrapper-col="wrapperCol"
:disabled="data.componentDisabled"
>
<a-form-item label="节点标识">
<a-input v-model:value="node.id" placeholder="请输入" readonly />
</a-form-item>
@ -10,12 +16,20 @@
<a-switch v-model:checked="node.isAsync" />
</a-form-item>
<a-form-item label="流程模版">
<a-select v-model:value="node.wfschemeId" :options="list" @change="changeScheme"
:fieldNames="{ value: 'id', label: 'name' }">
<a-select
v-model:value="node.wfschemeId"
:options="list"
@change="changeScheme"
:fieldNames="{ value: 'id', label: 'name' }"
>
</a-select>
</a-form-item>
<a-form-item label="流程版本">
<a-select v-model:value="node.wfVersionId" :options="verisons" :fieldNames="{value:'id',label:'createDate'}">
<a-select
v-model:value="node.wfVersionId"
:options="verisons"
:fieldNames="{ value: 'id', label: 'createDate' }"
>
</a-select>
</a-form-item>
</a-form>
@ -23,8 +37,8 @@
</template>
<script lang="ts" setup>
import { reactive, defineProps, computed, inject, ref, watch, h, onMounted } from 'vue'
import { getDetail, getLoad, getVerisonsLoad } from '@/api/sys/WFSchemeInfo'
import { reactive, defineProps, ref, watch, onMounted } from 'vue';
import { getLoad, getVerisonsLoad } from '@/api/sys/WFSchemeInfo';
import { flowStore } from '@/store/modules/flow';
const flowWfDataStore = flowStore();
const labelCol = { span: 7 };
@ -34,44 +48,41 @@
schemeCode: String,
pageType: String,
pageView: String,
})
let node = ref({})
});
let node: any = ref({});
const data = reactive({
componentDisabled: props.pageType == 'detail' ? true : false
})
const list = ref([])
const verisons = ref([])
componentDisabled: props.pageType == 'detail' ? true : false,
});
const list:any = ref([]);
const verisons = ref([]);
watch(
() => props.element,
(newVal, oldVal) => {
if (newVal.type == "bpmn:SubProcess") {
const currentNode = flowWfDataStore.getWfDataNode(newVal.id)
if (newVal.type == 'bpmn:SubProcess') {
const currentNode = flowWfDataStore.getWfDataNode(newVal.id);
if (currentNode) {
node.value = currentNode
node.value = currentNode;
} else {
node.value = newVal
node.value = newVal;
}
}
}
)
},
);
async function getSchemeList() {
const data = await getLoad()
list.value = data
const data = await getLoad();
list.value = data;
}
async function changeScheme() {
const data = await getVerisonsLoad({ id: node.value.wfschemeId })
verisons.value = data
const data = await getVerisonsLoad({ id: node.value.wfschemeId });
verisons.value = data;
}
onMounted(() => {
getSchemeList()
})
defineExpose({
})
getSchemeList();
});
defineExpose({});
</script>
<style>
</style>
<style></style>

View File

@ -221,17 +221,14 @@
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted, nextTick, unref, h, watch, defineProps } from 'vue';
import { BasicTree, TreeItem } from '@/components/Tree';
import SelectPos from '@/components/SelectPos/index.vue';
import SelectRole from '@/components/SelectRole/index.vue';
import SelectAccount from '@/components/SelectAccount/index.vue';
import AuditorLevel from './src/auditorLevel.vue'
import AuditorSql from './src/auditorSql.vue'
import AuditorNode from './src/auditorNode.vue'
import { getOrgPositonTree, userOrgs } from '@/api/demo/system';
import { reactive, ref, onMounted, h, watch, defineProps } from 'vue';
import {SelectPos} from '@/components/SelectPos/index';
import {SelectRole} from '@/components/SelectRole/index';
import {SelectAccount} from '@/components/SelectAccount/index';
import {AuditorLevel} from './page'
import {AuditorSql} from './page'
import {AuditorNode} from './page'
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue'
import { getDetail } from '@/api/sys/WFSchemeInfo'
import { flowStore } from '@/store/modules/flow';
const flowWfDataStore = flowStore();
const labelCol = { span: 7 };
@ -285,7 +282,7 @@
componentDisabled: props.pageType == 'detail' ? true : false
})
let node = ref({})
let node:any = ref({})
const props = defineProps({
element: Object,
schemeCode: String,

View File

@ -0,0 +1,3 @@
export { default as AuditorLevel } from './src/auditorLevel.vue';
export { default as AuditorSql } from './src/auditorSql.vue';
export { default as AuditorNode } from './src/auditorNode.vue';

View File

@ -1,66 +1,76 @@
<template>
<div class="l-from-body">
<a-form ref="formRef" :rules="data.rules" :model="data.formData" labelAlign="left" :label-col="labelCol"
:wrapper-col="wrapperCol">
<a-form-item label="上下级" name="id">
<a-select v-model:value="data.formData.id" placeholder="请选择上下级" :options="data.options"
@change="handleChange">
</a-select>
</a-form-item>
</a-form>
</div>
<div class="l-from-body">
<a-form
ref="formRef"
:rules="data.rules"
:model="data.formData"
labelAlign="left"
:label-col="labelCol"
:wrapper-col="wrapperCol"
>
<a-form-item label="上下级" name="id">
<a-select
v-model:value="data.formData.id"
placeholder="请选择上下级"
:options="data.options"
@change="handleChange"
>
</a-select>
</a-form-item>
</a-form>
</div>
</template>
<script lang="ts" setup>
import { reactive,ref } from 'vue'
const formRef = ref<any>()
const data = reactive({
formData: {
name: '',
type: '4',
id: '',
},
rules: {
id: [
{ required: true, message: '请选择上下级' }
]
},
options: [
{ value: '1', label: '上一级' },
{ value: '2', label: '上二级' },
{ value: '3', label: '上三级' },
{ value: '4', label: '上四级' },
{ value: '5', label: '上五级' },
{ value: '6', label: '下一级' },
{ value: '7', label: '下二级' },
{ value: '8', label: '下三级' },
{ value: '9', label: '下四级' },
{ value: '10', label: '下五级' }
]
})
function handleChange(val,option) {
data.formData.name = option.label
}
function validateForm(){
formRef.value
.validate()
.then(async (values) => {
return true
})
.catch(async (error) => {
return false
});
}
function getForm() {
let rows = data.formData
return rows
}
defineExpose({
getForm,
validateForm
})
import { reactive, ref } from 'vue';
const formRef = ref<any>();
const labelCol = { span: 7 };
const wrapperCol = { span: 17 };
const data = reactive({
formData: {
name: '',
type: '4',
id: '',
},
rules: {
id: [{ required: true, message: '请选择上下级' }],
},
options: [
{ value: '1', label: '上一级' },
{ value: '2', label: '上二级' },
{ value: '3', label: '上三级' },
{ value: '4', label: '上四级' },
{ value: '5', label: '上五级' },
{ value: '6', label: '下一级' },
{ value: '7', label: '下二级' },
{ value: '8', label: '下三级' },
{ value: '9', label: '下四级' },
{ value: '10', label: '下五级' },
],
});
function handleChange(val, option) {
data.formData.name = option.label;
}
function validateForm() {
formRef.value
.validate()
.then(async (values) => {
return true;
})
.catch(async (error) => {
return false;
});
}
function getForm() {
let rows = data.formData;
return rows;
}
defineExpose({
getForm,
validateForm,
});
</script>
<style scoped>
.l-from-body {
padding: 10px;
}
</style>
.l-from-body {
padding: 10px;
}
</style>

View File

@ -1,88 +1,99 @@
<template>
<div class="l-from-body">
<a-form ref="formRef" :rules="data.rules" :model="data.formData" labelAlign="left" :label-col="labelCol"
:wrapper-col="wrapperCol">
<a-form-item label="节点" name="id">
<a-select v-model:value="data.formData.id" placeholder="请选择节点" :options="data.options"
:field-names="{ label: 'name', value: 'id' }" @change="handleChange">
</a-select>
</a-form-item>
</a-form>
</div>
<div class="l-from-body">
<a-form
ref="formRef"
:rules="data.rules"
:model="data.formData"
labelAlign="left"
:label-col="labelCol"
:wrapper-col="wrapperCol"
>
<a-form-item label="节点" name="id">
<a-select
v-model:value="data.formData.id"
placeholder="请选择节点"
:options="data.options"
:field-names="{ label: 'name', value: 'id' }"
@change="handleChange"
>
</a-select>
</a-form-item>
</a-form>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, defineEmits, defineProps, watch,onMounted } from 'vue'
import { flowStore } from '@/store/modules/flow';
import { reactive, ref, defineEmits, defineProps, watch, onMounted } from 'vue';
import { flowStore } from '@/store/modules/flow';
const flowWfDataStore = flowStore();
const emit = defineEmits(['success']);
const props = defineProps({
id: String
})
console.log(props)
watch(
() => props.id,
(newVal, oldVal) => {
console.log(newVal)
getOptions(newVal)
}
)
const formRef = ref < any > ()
const data = reactive({
formData: {
name: '',
type: '5',
id: '',
},
rules: {
id: [
{ required: true, message: '请选择节点' }
]
},
options: []
})
onMounted(() => {
getOptions(props.id)
})
function getOptions(nodeId) {
/**
const labelCol = { span: 7 };
const wrapperCol = { span: 17 };
const emit = defineEmits(['success']);
const props = defineProps({
id: String,
});
console.log(props);
watch(
() => props.id,
(newVal, oldVal) => {
console.log(newVal);
getOptions(newVal);
},
);
const formRef = ref<any>();
const data = reactive({
formData: {
name: '',
type: '5',
id: '',
},
rules: {
id: [{ required: true, message: '请选择节点' }],
},
options: [],
});
onMounted(() => {
getOptions(props.id);
});
function getOptions(nodeId) {
/**
ExclusiveGateway:'排他网关',
Task:'审核节点',
*/
let wfdata = flowWfDataStore.getWfData
var arr = []
wfdata.forEach(element => {
if (element.type == 'bpmn:Task' && element.id != nodeId) {
arr.push(element)
}
});
console.log(arr)
data.options = arr
}
function handleChange(val, option) {
data.formData.name = option.name
}
function validateForm() {
formRef.value
.validate()
.then(async (values) => {
return true
})
.catch(async (error) => {
return false
});
}
function getForm() {
let rows = data.formData
console.log(rows)
return rows
}
defineExpose({
getForm,
validateForm
})
let wfdata = flowWfDataStore.getWfData;
var arr = [];
wfdata.forEach((element) => {
if (element.type == 'bpmn:Task' && element.id != nodeId) {
arr.push(element);
}
});
console.log(arr);
data.options = arr;
}
function handleChange(val, option) {
data.formData.name = option.name;
}
function validateForm() {
formRef.value
.validate()
.then(async (values) => {
return true;
})
.catch(async (error) => {
return false;
});
}
function getForm() {
let rows = data.formData;
console.log(rows);
return rows;
}
defineExpose({
getForm,
validateForm,
});
</script>
<style scoped>
.l-from-body {
padding: 10px;
}
</style>
.l-from-body {
padding: 10px;
}
</style>

View File

@ -1,8 +1,14 @@
<template>
<div class="l-from-body">
<a-form ref="formRef" :rules="data.rules" :model="formData" labelAlign="left" :label-col="labelCol"
:wrapper-col="wrapperCol">
<!-- <a-form-item label="数据库" name="dbCode">
<div class="l-from-body">
<a-form
ref="formRef"
:rules="data.rules"
:model="formData"
labelAlign="left"
:label-col="labelCol"
:wrapper-col="wrapperCol"
>
<!-- <a-form-item label="数据库" name="dbCode">
<a-select v-model:value="formData.dbCode" placeholder="请选择" :options="data.options">
<el-option-group v-for="group in lr_dblinkTree" :key="group.id" :label="group.label">
<el-option v-for="item in group.children" :key="item.id" :label="item.label" :value="item.id">
@ -10,108 +16,110 @@
</el-option-group>
</a-select>
</a-form-item> -->
<a-form-item label="数据表" name="table">
<!-- <a-select v-model:value="formData.table" placeholder="请选择" :options="formData.columns">
<a-form-item label="数据表" name="table">
<!-- <a-select v-model:value="formData.table" placeholder="请选择" :options="formData.columns">
</a-select> -->
<a-space>
<a-input v-model:value="formData.table" placeholder="请输入" readonly />
<a-button @click="handleTableClick"></a-button>
</a-space>
</a-form-item>
<a-form-item label="关联流程字段" name="rfield">
<a-select v-model:value="formData.rfield" placeholder="请选择" :options="data.columns">
</a-select>
</a-form-item>
<a-form-item label="审核人字段" name="auditorField">
<a-select v-model:value="formData.auditorField" placeholder="请选择" :options="data.columns">
</a-select>
</a-form-item>
</a-form>
<a-modal width="60%" height="80%" v-model:open="data.tableOpen" title="选择数据表" @ok="tableHandleOk">
<SelectTable ref="tableRef"></SelectTable>
</a-modal>
</div>
<a-space>
<a-input v-model:value="formData.table" placeholder="请输入" readonly />
<a-button @click="handleTableClick"></a-button>
</a-space>
</a-form-item>
<a-form-item label="关联流程字段" name="rfield">
<a-select v-model:value="formData.rfield" placeholder="请选择" :options="data.columns">
</a-select>
</a-form-item>
<a-form-item label="审核人字段" name="auditorField">
<a-select
v-model:value="formData.auditorField"
placeholder="请选择"
:options="data.columns"
>
</a-select>
</a-form-item>
</a-form>
<a-modal
width="60%"
height="80%"
v-model:open="data.tableOpen"
title="选择数据表"
@ok="tableHandleOk"
>
<SelectTable ref="tableRef"></SelectTable>
</a-modal>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted } from 'vue'
import SelectTable from '@/components/SelectTable/index.vue'
import { getTableForms } from '@/api/sys/flowPenal'
import { reactive, ref } from 'vue';
import { SelectTable } from '@/components/SelectTable/index';
import { getTableForms } from '@/api/sys/flowPenal';
const labelCol = { span: 5 };
const wrapperCol = { span: 17 };
const formRef = ref < any > ()
const tableRef = ref < any > ()
const labelCol = { span: 5 };
const wrapperCol = { span: 17 };
const formRef = ref<any>();
const tableRef = ref<any>();
const data = reactive({
rules: {
dbCode: [
{ required: true, message: '请选择数据库' }
],
table: [
{ required: true, message: '请选择数据表' }
],
rfield: [
{ required: true, message: '请选择关联字段' }
],
auditorField: [
{ required: true, message: '请选择审核人字段' }
]
},
columns:[],
tableOpen: false
})
let formData = ref({
dbCode: '',
table: '',
rfield: '',
auditorField: '',
type: '6'
})
function handleTableClick() {
data.tableOpen = true
}
function tableHandleOk() {
console.log(tableRef.value.getRow())
const obj = tableRef.value.getRow()
formData.value.table = obj[0].name
handleTableChange(obj[0].name)
data.tableOpen = false
}
//
async function handleTableChange(table) {
var querys = {
dbCode: 'lrsystemdb',
tableNames: table
}
console.log(querys)
const data = await getTableForms(querys)
console.log(data);
}
//
function validateForm() {
formRef.value
.validate()
.then(async (values) => {
return true
})
.catch(async (error) => {
return false
});
}
function setForm(data) {
this.formData = this.$deepClone(data);
}
function getForm() {
return formData.value;
}
const data = reactive({
rules: {
dbCode: [{ required: true, message: '请选择数据库' }],
table: [{ required: true, message: '请选择数据表' }],
rfield: [{ required: true, message: '请选择关联字段' }],
auditorField: [{ required: true, message: '请选择审核人字段' }],
},
columns: [],
tableOpen: false,
});
let formData = ref({
dbCode: '',
table: '',
rfield: '',
auditorField: '',
type: '6',
});
function handleTableClick() {
data.tableOpen = true;
}
function tableHandleOk() {
console.log(tableRef.value.getRow());
const obj = tableRef.value.getRow();
formData.value.table = obj[0].name;
handleTableChange(obj[0].name);
data.tableOpen = false;
}
//
async function handleTableChange(table) {
var querys = {
dbCode: 'lrsystemdb',
tableNames: table,
};
console.log(querys);
const data = await getTableForms(querys);
console.log(data);
}
//
function validateForm() {
formRef.value
.validate()
.then(async (values) => {
return true;
})
.catch(async (error) => {
return false;
});
}
function setForm(data) {
this.formData = this.$deepClone(data);
}
function getForm() {
return formData.value;
}
defineExpose({
validateForm,
getForm
})
defineExpose({
validateForm,
getForm,
});
</script>
<style scoped>
.l-from-body {
padding: 10px 30px;
}
</style>
.l-from-body {
padding: 10px 30px;
}
</style>

View File

@ -0,0 +1,2 @@
export { default as ProcessDesigner } from './package/designer/ProcessDesigner.vue';

View File

@ -0,0 +1,2 @@
export { default as ProcessViewer } from './index.vue';

View File

@ -0,0 +1 @@
export { default as SelectAccount } from './index.vue';

View File

@ -0,0 +1 @@
export { default as SelectPos } from './index.vue';

View File

@ -0,0 +1 @@
export { default as SelectRole } from './index.vue';

View File

@ -0,0 +1 @@
export { default as SelectTable } from './index.vue';

View File

@ -34,7 +34,13 @@ export function resetRouter() {
}
});
}
router.beforeEach((to:any, from:any, next:Function) => {
if(to.query && to.query.name){
to.meta.title = to.query.name
}
next()
})
// config router
// 配置路由器
export function setupRouter(app: App<Element>) {

View File

@ -44,12 +44,10 @@ export const H5HtmlRoute: AppRouteRecordRaw = {
name: 'h5html',
component: () => import('@/views/demo/h5html/index.vue'),
meta: {
title: t('routes.basic.h5html'),
title: 'H5表单',
},
};
// Basic routing without permission
// 未经许可的基本路由
export const basicRoutes = [

View File

@ -23,6 +23,19 @@ const dashboard: AppRouteModule = {
title: t('routes.dashboard.analysis'),
},
},
{
path: '/formCallPage',
name: 'formCallPage',
meta: {
title: '表单调用',
hideMenu: true,
},
beforeEnter: (to:any, from:any, next:Function) => {
to.meta.title = to.query.name
next()
},
component: () => import('@/views/demo/onlineform/formCall/index.vue'),
},
{
path: 'scheme_preview/:id',
name: 'SchemePreview',
@ -73,5 +86,5 @@ const dashboard: AppRouteModule = {
},
],
};
export default dashboard;

View File

@ -135,7 +135,8 @@ export const usePermissionStore = defineStore({
},
name: data.item.name,
hideMenu: false,
path: data.item.url,
path: data.item.url || '/formCallPage?id='+data.item.id+'&name='+data.item.name,
id: data.item.id || '',
children: [],
}
if (data.children && data.children.length > 0) {
@ -191,7 +192,6 @@ export const usePermissionStore = defineStore({
await Promise.all(moduleRoutes);
// 设置菜单列表
_this.setFrontMenuList(moduleRoutes);
}

View File

@ -29,6 +29,7 @@
</template>
<script lang="ts" setup>
import { onMounted, ref, nextTick, unref,reactive } from 'vue';
import { useRoute } from 'vue-router';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { getFormGroupList,getBaseConfigList } from '@/api/formdesign/index';
import { columns, searchFormSchema } from './index.data';
@ -37,6 +38,9 @@
import { IFormConfig,IToolbarMethods } from '../../form-design/typings/v-form-component';
const eFormPreview = ref<null | IToolbarMethods>(null);
const route = useRoute();
const paramsId = route.query.id;
const [registerTable, { reload, getSelectRows }] = useTable({
title: '表单列表',

View File

@ -39,11 +39,15 @@
v-show="stepsCurrent == 0"
@change-form-verisons="changeFormVerisons"
ref="modalFrom_formData"
:editData="editData"
:isNextSteps="isNextSteps"
@set-steps-current="setStepsCurrent"
/>
<ModalDesign
v-show="stepsCurrent == 1"
:modalFormVerison="modalFormVerison"
ref="modalDesign_config"
:modalFormVerison="modalFormVerison"
:editData="editData"
/>
</div>
</div>
@ -64,29 +68,56 @@
//
let isSubmitClick = ref(false);
//
let formEdit = ref(false);
let formEdit = false;
//
const modalFrom_formData = ref();
const modalDesign_config = ref();
//
const editData = ref();
const modalFormVerison = ref('');
const defaultFormData = {
type: 1,
code: '',
name: '',
icon: 'ant-design:star-outlined',
formCode: '',
formCodeName: '',
formVerison: '',
pmoduleId: '',
moduleId: '',
enabledMark: 1,
isSys: false,
sortCode: '0',
description: '',
};
const [registerModal, { closeModal }] = useModalInner((data: any) => {
console.log(75, data);
formEdit.value = data.formEdit;
// if(){
// }
formEdit = data.formEdit;
if (formEdit) {
editData.value = data;
} else {
data.record = defaultFormData;
editData.value = data;
}
stepsCurrent.value = 0;
isSubmitClick.value = false;
});
//
function formNextClick() {
stepsCurrent.value = 1;
isNextSteps.value = true;
isSubmitClick.value = false;
}
//
function setStepsCurrent(flag) {
if (flag) {
stepsCurrent.value = 1;
isNextSteps.value = true;
} else {
stepsCurrent.value = 0;
isNextSteps.value = false;
}
}
//
function formPrevClick() {
isNextSteps.value = false;
@ -102,7 +133,7 @@
//
async function submitClick() {
const postData = getForm();
if (formEdit.value) {
if (formEdit) {
await Post_UpdateForm(postData);
} else {
await Post_AddForm(postData);
@ -117,28 +148,11 @@
//
let formModuleEntity = {};
formModuleEntity.id = formData.id;
formModuleEntity.code = formData.code;
formModuleEntity.formCode = formData.formCode.id;
formModuleEntity.formVerison = formData.formVerison.value;
formModuleEntity.icon = formData.icon;
formModuleEntity.name = formData.name;
formModuleEntity.type = formData.type;
formModuleEntity.pmoduleId = formData.pmoduleId;
formModuleEntity.moduleId = '';
formModuleEntity.sortCode = formData.sortCode;
formModuleEntity.enabledMark = formData.enabledMark;
formModuleEntity.description = formData.description;
// formModuleEntity.createDate= ;
// formModuleEntity.createUserId= ;
// formModuleEntity.createUserName= ;
formModuleEntity = formData;
formModuleEntity.formCode = formData.formCode;
formModuleEntity.formVerison = formData.formVerison;
formModuleEntity.modifyDate = new Date();
// formModuleEntity.modifyUserId= ;
// formModuleEntity.modifyUserName= ;
formModuleEntity.scheme = JSON.stringify(config);
formModuleEntity.keyWord = '';
formModuleEntity.tenantId = '';
formModuleEntity.isMain = '';
// sysModule
let sysModule = {};
@ -203,12 +217,10 @@
postData.sysModuleColumn = sysModuleColumn;
postData.sysModuleForm = sysModuleForm;
console.log('postData', postData);
return postData;
}
// modalFormmodalDesign
const modalFormVerison = ref('');
function changeFormVerisons(formVerison) {
modalFormVerison.value = formVerison;
}

View File

@ -1,17 +1,17 @@
<template>
<lrlayout style="background: #f1f2f5" :left="240">
<template #left>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<div class="m-2 mr-0 w-1/4 xl:w-1/5 overflow-hidden bg-white">
<BasicTree
ref="asyncExpandTreeRef"
title="常用按钮"
checkable
:treeData="btnsTree"
:treeData="btnsTreeData"
:defaultExpandAll="true"
:fieldNames="{ key: 'id', title: 'label' }"
@check="handleCheck"
/>
</template>
<BasicTable @register="btnsTable">
</div>
<BasicTable @register="btnsTable" class="m-2 mr-0 w-3/4 xl:w-4/5">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'isRowBtn'">
<a-switch
@ -48,21 +48,21 @@
<template v-if="column.key === 'sort'">
<a-input-number v-model:value="record.sort" :min="0" />
</template>
<template v-if="column.key === 'icon'">
<!-- <template v-if="column.key === 'icon'">
<div v-if="record.prop in ['Add', 'Import', 'Export']">
<IconPicker v-model:value="record.icon" />
</div>
</template>
</template> -->
</template>
</BasicTable>
</lrlayout>
</PageWrapper>
</template>
<script lang="ts" setup>
import { ref, inject, defineProps } from 'vue';
import { ref, inject, defineProps, watch } from 'vue';
import { BasicTable, useTable } from '@/components/Table';
import lrlayout from '@/components/lrLayout';
import { PageWrapper } from '@/components/Page';
import { BasicTree } from '@/components/Tree';
import { IconPicker } from '/@/components/Icon';
// import { IconPicker } from '/@/components/Icon';
import { btns } from './config.data';
@ -73,12 +73,24 @@
default: () => ({}), //
},
});
const btnsTree = props.btnsTree;
const btnsTreeData = props.btnsTree;
// config
const config = inject('formConfig');
const btnsData = ref(config.table.btns);
// watch(
// () => props.btnsTree,
// () => {
// console.log(btnsTreeData);
// },
// );
// watch(
// () => config.table.btns,
// () => {
// console.log(btnsData);
// },
// );
const classList = [
{ label: 'primary', value: 'primary' },
{ label: 'success', value: 'success' },
@ -91,11 +103,12 @@
dataSource: btnsData,
columns: btns(),
bordered: true,
pagination: false,
});
//
function handleCheck(keys) {
btnsData.value = btnsTree.filter((item) => {
btnsData.value = btnsTreeData.filter((item) => {
return keys.includes(item.id);
});
config.table.btns = btnsData.value;

View File

@ -1,23 +1,24 @@
<template>
<lrlayout style="background: #f1f2f5" :left="240">
<template #left>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<div class="m-2 mr-0 w-1/4 xl:w-1/5 overflow-hidden bg-white">
<BasicTree
ref="asyncExpandTreeRef"
ref="columnsTreeRef"
title="列字段"
checkable
:treeData="columnsTree"
v-model:selectedKeys="columnsSelectData"
:treeData="columnsTreeData"
:defaultExpandAll="true"
:fieldNames="{ key: 'key', title: 'label' }"
@check="handleCheck"
/>
</template>
<BasicTable @register="columnsTable">
</div>
<BasicTable @register="columnsTable" class="m-2 mr-0 w-3/4 xl:w-4/5 overflow-hidden">
<template #toolbar>
<span style="margin-right: 8px">是否分页</span>
<a-switch class="mars-switch" v-model:checked="config.table.isPage" />
<span style="margin-left: 20px; margin-right: 8px">排序字段</span>
<a-select
:options="columnsTree[0].children"
:options="columnsTreeData[0].children"
v-model:value="config.table.sidx"
placeholder="请选择"
style="width: 120px"
@ -48,13 +49,13 @@
</template>
</template>
</BasicTable>
</lrlayout>
</PageWrapper>
</template>
<script lang="ts" setup>
import { ref, inject, defineProps, onMounted, nextTick, unref } from 'vue';
import { ref, inject, defineProps, onMounted, PropType } from 'vue';
import { PageWrapper } from '@/components/Page';
import { BasicTable, useTable } from '@/components/Table';
import lrlayout from '@/components/lrLayout';
import { BasicTree } from '@/components/Tree';
import { columns } from './config.data';
@ -65,8 +66,13 @@
type: Object,
default: () => ({}), //
},
columnsSelect: {
type: Array as PropType<string[]>,
default: () => [],
},
});
const columnsTree = props.columnsTree;
const columnsTreeData = props.columnsTree;
const columnsSelectData = props.columnsSelect;
// config
const config = inject('formConfig');
@ -83,26 +89,20 @@
dataSource: columnsData,
columns: columns(),
bordered: true,
pagination: false,
});
const asyncExpandTreeRef = ref<Nullable<TreeActionType>>(null);
async function fetch() {
//
nextTick(() => {
unref(asyncExpandTreeRef)?.expandAll(true);
});
}
//
function handleCheck(keys) {
columnsData.value = columnsTree[0].children.filter((item) => {
columnsData.value = columnsTreeData[0].children.filter((item) => {
return keys.includes(item.key);
});
config.table.columns = columnsData.value;
console.log(columnsSelectData);
reload();
}
onMounted(() => {
fetch();
// fetch();
});
</script>

View File

@ -23,6 +23,6 @@ export function btns(): BasicColumn[] {
{ title: '流程模版', dataIndex: 'wFlowCode', width: '240' },
{ title: '权限标识', dataIndex: 'class', width: '120' },
{ title: '排序', dataIndex: 'sort', width: '80' },
{ title: '图标', dataIndex: 'icon', width: '240' },
// { title: '图标', dataIndex: 'icon', width: '240' },
];
}

View File

@ -1,38 +1,46 @@
<template>
<lrlayout style="background: #f1f2f5" :left="240">
<template #left>
<lrPanel title="列表关联字段" style="padding: 8px 0 0 0">
<a-radio-group :options="colslist" v-model:value="config.left.colField" />
</lrPanel>
</template>
<lrPanel title="设置" style="padding: 8px 0 0 4px">
<a-form style="padding: 16px; maxwidth: 400px" size="mini" ref="form" label-width="80px">
<a-form-item label="树形标题">
<a-input v-model="config.left.title" />
</a-form-item>
<div style="text-align: center; margin-bottom: 16px">
<a-radio-group
v-model:value="config.left.dataType"
size="mini"
button-style="solid"
@change="handleDataTypeChange"
>
<a-radio-button value="1">静态数据</a-radio-button>
<a-radio-button value="2">数据字典</a-radio-button>
<a-radio-button value="3">数据源</a-radio-button>
</a-radio-group>
</div>
<!--静态数据-->
<div v-if="config.left.dataType == 1">
<a-tree
ref="tree"
:data="config.left.options"
default-expand-all
draggable
node-key="value"
:expand-on-click-node="false"
>
<!-- <template #default="{ node, data }">
<div>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<div class="m-2 mr-0 w-1/4 xl:w-1/5 overflow-hidden bg-white">
<BasicTree
ref="asyncExpandTreeRef"
title="列表关联字段"
checkable
:treeData="colslist"
:defaultExpandAll="true"
:fieldNames="{ key: 'id', title: 'label' }"
@check="handleCheck"
/>
</div>
<div class="l-rblock m-2 mr-0 w-1/6 xl:w-1/6 overflow-hidden bg-white">
<lrPanel title="设置" class="m-2 mr-0 w-3/4 xl:w-4/5">
<a-form style="padding: 16px; maxwidth: 400px" size="mini" ref="form" label-width="80px">
<a-form-item label="树形标题">
<a-input v-model="config.left.title" />
</a-form-item>
<div style="text-align: center; margin-bottom: 16px">
<a-radio-group
v-model:value="config.left.dataType"
size="mini"
button-style="solid"
@change="handleDataTypeChange"
>
<a-radio-button value="1">静态数据</a-radio-button>
<a-radio-button value="2">数据字典</a-radio-button>
<a-radio-button value="3">数据源</a-radio-button>
</a-radio-group>
</div>
<!--静态数据-->
<div v-if="config.left.dataType == 1">
<a-tree
ref="tree"
:data="config.left.options"
default-expand-all
draggable
node-key="value"
:expand-on-click-node="false"
>
<!-- <template #default="{ node, data }">
<span class="custom-tree-node">
<span>{{ node.label }}</span>
<span>
@ -52,80 +60,78 @@
</span>
</span>
</template> -->
</a-tree>
<div style="margin-left: 22px">
<a-button size="mini" type="text" icon="" @click="handleParentNodeAdd">
添加父级
</a-button>
</div>
</div>
<!--数据字典-->
<div v-else-if="config.left.dataType == 2">
<l-tree-select
v-model="config.left.dataCode"
:options="lr_dataItemClassifysTree"
placeholder="请选择数据字典"
size="mini"
/>
</div>
<!--远端数据-->
<div v-else>
<a-form-item label="数据源">
<l-select
v-model="config.left.dataCode"
placeholder="请选择数据源"
size="mini"
:options="lr_dataSource"
labelKey="f_Name"
valueKey="f_Code"
@change="handleDataSourceChange"
/>
</a-form-item>
<a-form-item label="关联字段">
<l-select
v-model="config.left.dataValueKey"
placeholder="请选择选项关联字段"
size="mini"
:options="myColNameList"
/>
</a-form-item>
<a-form-item label="显示字段">
<l-select
v-model="config.left.dataLabelKey"
placeholder="请选择选项显示字段"
size="mini"
:options="myColNameList"
/>
</a-form-item>
<a-form-item label="id字段">
<l-select
v-model="config.left.dataIdKey"
placeholder="请选择选项id字段"
size="mini"
:options="myColNameList"
/>
</a-form-item>
<a-form-item label="pid字段">
<l-select
v-model="config.left.dataPIdKey"
placeholder="请选择选项父级id字段"
size="mini"
:options="myColNameList"
/>
</a-form-item>
</div>
</a-form>
</lrPanel>
</lrlayout>
</a-tree>
<div style="margin-left: 22px">
<a-button size="mini" type="text" icon="" @click="handleParentNodeAdd">
添加父级
</a-button>
</div>
</div>
<!--数据字典-->
<div v-else-if="config.left.dataType == 2">
<l-tree-select
v-model="config.left.dataCode"
:options="lr_dataItemClassifysTree"
placeholder="请选择数据字典"
size="mini"
/>
</div>
<!--远端数据-->
<div v-else>
<a-form-item label="数据源">
<l-select
v-model="config.left.dataCode"
placeholder="请选择数据源"
size="mini"
:options="lr_dataSource"
labelKey="f_Name"
valueKey="f_Code"
@change="handleDataSourceChange"
/>
</a-form-item>
<a-form-item label="关联字段">
<l-select
v-model="config.left.dataValueKey"
placeholder="请选择选项关联字段"
size="mini"
:options="myColNameList"
/>
</a-form-item>
<a-form-item label="显示字段">
<l-select
v-model="config.left.dataLabelKey"
placeholder="请选择选项显示字段"
size="mini"
:options="myColNameList"
/>
</a-form-item>
<a-form-item label="id字段">
<l-select
v-model="config.left.dataIdKey"
placeholder="请选择选项id字段"
size="mini"
:options="myColNameList"
/>
</a-form-item>
<a-form-item label="pid字段">
<l-select
v-model="config.left.dataPIdKey"
placeholder="请选择选项父级id字段"
size="mini"
:options="myColNameList"
/>
</a-form-item>
</div>
</a-form>
</lrPanel>
</div>
</PageWrapper>
</div>
</template>
<script lang="ts" setup>
import { PageWrapper } from '@/components/Page';
import { ref, inject, defineProps } from 'vue';
import { BasicTable, useTable } from '@/components/Table';
import lrlayout from '@/components/lrLayout';
import { BasicTree } from '@/components/Tree';
import lrPanel from '@/components/lrPanel';
import { columns } from './config.data';
// props,
const props = defineProps({
@ -134,7 +140,6 @@
default: () => ({}), //
},
});
const colslist = props.colslist;
// config

View File

@ -1,6 +1,6 @@
<template>
<lrlayout style="background: #f1f2f5" :left="240">
<template #left>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<div class="m-2 mr-0 w-1/3 xl:w-1/4 overflow-hidden bg-white">
<BasicTree
title="查询字段"
checkable
@ -10,41 +10,32 @@
:fieldNames="{ key: 'key', title: 'label' }"
@check="handleCheck"
/>
</template>
<a-layout style="background: #f1f2f5">
<a-layout-sider :style="{ width: '1000px' }">
<BasicTable @register="queryTable">
<template #toolbar>
<div class="l-panel--item" size="mini">
<a-radio-group
v-model:value="radioData"
size="mini"
@change="radioChange"
button-style="solid"
>
<a-radio-button value="1">风格一</a-radio-button>
<a-radio-button value="2">风格二</a-radio-button>
</a-radio-group>
</div>
</template>
</BasicTable>
</a-layout-sider>
<a-layout-content>
<div class="l-rblock">
<img
style="width: 100%"
:src="`/public/mars/img/onlineform/query${config.queryType}.jpg`"
/>
</div>
<BasicTable @register="queryTable" class="m-2 mr-0 w-1/3 xl:w-2/4 overflow-hidden">
<template #toolbar>
<div class="l-panel--item" size="mini">
<a-radio-group
v-model:value="radioData"
size="mini"
@change="radioChange"
button-style="solid"
>
<a-radio-button :value="1">风格一</a-radio-button>
<a-radio-button :value="2">风格二</a-radio-button>
</a-radio-group>
</div>
</a-layout-content>
</a-layout>
</lrlayout>
</template>
</BasicTable>
<div class="l-rblock m-2 mr-0 w-1/6 xl:w-1/6">
<img style="width: 100%" :src="`/public/mars/img/onlineform/query${config.queryType}.jpg`" />
</div>
</PageWrapper>
</template>
<script lang="ts" setup>
import { ref, inject, defineProps } from 'vue';
import { BasicTable, useTable } from '@/components/Table';
import lrlayout from '@/components/lrLayout';
import { PageWrapper } from '@/components/Page';
import { BasicTree } from '@/components/Tree';
import { querys } from './config.data';
@ -70,6 +61,7 @@
dataSource: querysData,
columns: querys(),
bordered: true,
pagination: false,
});
//

View File

@ -92,7 +92,6 @@
return createMessage.warn('请选择一个按钮进行编辑');
}
const record = rows[0];
// record.type = '2';
formModalVisible.value = true;
openModal(true, {
formEdit: true,
@ -105,8 +104,6 @@
if (rows.length == 0) {
return createMessage.warn('请选择一个表单进行删除');
}
console.log(rows);
const query = { id: rows[0].id };
createConfirm({
iconType: 'info',

View File

@ -14,11 +14,10 @@
<webcodeQuery :queryTree="queryTree" />
</el-tab-pane>
<el-tab-pane :label="$t('按钮设置')" name="tab04">
<webcodeBtns :btnsTree="btnsTree" />
<webcodeBtns :btnsTree="btnsTree" :columnsSelect="columnsSelect" />
</el-tab-pane>
</el-tabs>
</div>
<a-button @click="validateSteps" />
</template>
<script lang="ts" setup>
@ -36,41 +35,51 @@
type: Object,
default: () => ({}), //
},
editData: {
type: Object,
default: () => ({}),
},
});
watch(
() => props.modalFormVerison,
(newVal) => {
validateSteps(newVal.value);
},
{
immediate: true,
(newVal, oldVal) => {
if (newVal != oldVal) {
validateSteps(newVal);
}
},
);
//
const pageActiveName = 'tab01';
//
// tree
const colslist = ref([]);
//
// tree
const columnsTree = ref([
{
label: '全选',
children: [],
},
]);
//
// tree
const columnsSelect = ref([]);
// tree
const queryTree = ref([
{
label: '全选',
children: [],
},
]);
// select
const querySelect = ref([]);
// tree
const btnsTree = ref([]);
// select
const btnsSelect = ref([]);
const config = ref({
layoutType: 1,
queryType: '1',
queryType: 1,
left: {
title: '左侧树形',
colField: '',
@ -96,7 +105,7 @@
label: '新增',
id: 'Add',
prop: 'Add',
icon: 'el-icon-plus',
icon: 'ant-design:file-add-outlined',
isRowBtn: false,
class: 'primary',
sort: 0,
@ -105,7 +114,7 @@
label: '导入',
id: 'Import',
prop: 'Import',
icon: 'el-icon-upload2',
icon: 'ant-design:upload-outlined',
isRowBtn: false,
class: 'primary',
sort: 1,
@ -114,29 +123,52 @@
label: '导出',
id: 'Export',
prop: 'Export',
icon: 'el-icon-download',
icon: 'ant-design:download-outlined',
isRowBtn: false,
class: 'primary',
sort: 2,
},
{ label: '编辑', id: 'Edit', prop: 'Edit', isRowBtn: true, class: 'success', sort: 3 },
{ label: '删除', id: 'Delete', prop: 'Delete', isRowBtn: true, class: 'error', sort: 4 },
{ label: '详情', id: 'Details', prop: 'Details', isRowBtn: true, class: 'primary', sort: 5 },
{
label: '编辑',
id: 'Edit',
prop: 'Edit',
icon: 'ant-design:edit-outlined',
isRowBtn: true,
class: 'success',
sort: 3,
},
{
label: '删除',
id: 'Delete',
prop: 'Delete',
icon: 'ant-design:delete-outlined',
isRowBtn: true,
class: 'error',
sort: 4,
},
{
label: '详情',
id: 'Details',
prop: 'Details',
icon: 'ant-design:align-center-outlined',
isRowBtn: true,
class: 'primary',
sort: 5,
},
],
});
const formScheme = ref('');
//
async function validateSteps(keyValue: string) {
if (!keyValue) {
async function validateSteps(formVerison) {
if (!formVerison) {
return;
}
//
// let keyValue: string = '4afddef9-e234-458c-a4a8-f67a9728a634';
const scheme = await functionGetPreviewForm({ keyValue: keyValue });
// let keyValue = typeof formVerison === 'string' ? formVerison : formVerison.value;
const scheme = await functionGetPreviewForm({ keyValue: formVerison });
formScheme.value = JSON.parse(scheme.scheme);
console.log(scheme);
const columns = [];
formScheme.value.formInfo.schemas.forEach((tab) => {
@ -150,15 +182,13 @@
colunmsMap[item.label + item.field] = item;
});
console.log(105, columns);
console.log(106, colunmsMap);
//
colslist.value = columns.map((t) => {
return { value: t.componentProps.fieldName, label: t.componentProps.fieldName };
});
// -
columnsTree.value[0].children = [];
columns.map((t) => {
columnsTree.value[0].children.push({
key: t.label + t.field,
@ -168,18 +198,12 @@
align: 'left',
isMinWidth: false,
});
// -
config.value.table.columns.push({
key: t.label + t.field,
label: t.label,
value: t.label,
width: 120,
align: 'left',
isMinWidth: false,
});
});
// -
config.value.table.columns = columnsTree.value[0].children;
//
queryTree.value[0].children = [];
queryTree.value[0].children = columns
.filter(
(t) =>
@ -188,26 +212,38 @@
.map((t) => {
return { key: t.label + t.field, label: t.label };
});
columns.forEach((t) => {
config.value.table.querys.push({
key: t.label + t.field,
label: t.label,
});
});
config.value.table.querys = queryTree.value[0].children;
//
const schemeInfo = await functionGetSchemeInfoEntity({ id: scheme.schemeInfoId });
if (schemeInfo.formType === 1) {
//
config.value.table.btns = config.value.btns.filter((t) =>
btnsTree.value = config.value.btns.filter((t) =>
['Import', 'Export', 'Details'].includes(t.id),
);
} else {
config.value.table.btns = config.value.btns;
btnsTree.value = config.value.btns;
}
console.log(187, config.value.table.btns);
config.value.table.btns = btnsTree.value;
//
if (props.editData.formEdit) {
if (props.editData.record.formVerison === formVerison) {
const editDataScheme = JSON.parse(props.editData.record.scheme);
config.value.table.columns = editDataScheme.table.columns;
config.value.table.querys = editDataScheme.table.querys;
config.value.table.btns = editDataScheme.table.btns;
}
}
//
config.value.table.columns.forEach((t) => {
columnsSelect.value.push(t.key);
});
config.value.table.querys.forEach((t) => {
querySelect.value.push(t.key);
});
config.value.table.btns.forEach((t) => {
btnsTree.value.push(t);
btnsSelect.value.push(t.id);
});
}

View File

@ -109,8 +109,8 @@
const [registerModal, { closeModal }] = useModal();
//
function modalSubmit() {
let row = getSelectRows();
emit('get-scheme-row', row);
let rows = getSelectRows();
emit('get-scheme-row', rows[0]);
closeModal();
clearSelectedRowKeys();
reload();

View File

@ -19,13 +19,16 @@
<a-form-item label="图标" name="icon">
<IconPicker v-model:value="formData.icon" />
</a-form-item>
<a-form-item label="表单选择" name="formCode" @click="handleShow">
<a-input v-model:value="formData.formCode.name">
<a-form-item label="表单选择" name="formCodeName" @click="handleShow">
<a-input v-model:value="formData.formCodeName">
<template #addonAfter>
<FileTextOutlined />
</template>
</a-input>
</a-form-item>
<a-form-item label="表单选择" name="formCode" v-show="false">
<a-input v-model:value="formData.formCode" />
</a-form-item>
<a-form-item label="表单版本" name="formVerison">
<a-select v-model:value="formData.formVerison" :options="formVerisons" />
</a-form-item>
@ -37,25 +40,15 @@
/>
</a-form-item>
<a-form-item label="状态" name="enabledMark">
<a-radio-group
v-model:value="formData.enabledMark"
size="mini"
@change="radioChange"
button-style="solid"
>
<a-radio-button value="1"></a-radio-button>
<a-radio-button value="0"></a-radio-button>
<a-radio-group v-model:value="formData.enabledMark" size="mini" button-style="solid">
<a-radio-button :value="1"></a-radio-button>
<a-radio-button :value="0"></a-radio-button>
</a-radio-group>
</a-form-item>
<a-form-item label="是否系统" name="isSys">
<a-radio-group
v-model:value="formData.isSys"
size="mini"
@change="radioChange"
button-style="solid"
>
<a-radio-button value="true"></a-radio-button>
<a-radio-button value="false"></a-radio-button>
<a-radio-group v-model:value="formData.isSys" size="mini" button-style="solid">
<a-radio-button :value="true"></a-radio-button>
<a-radio-button :value="false"></a-radio-button>
</a-radio-group>
</a-form-item>
<a-form-item label="排序" name="sortCode">
@ -78,13 +71,30 @@
import { IconPicker } from '@/components/Icon';
import { TreeItem } from '@/components/Tree';
import { useModal } from '@/components/Modal';
import { useMessage } from '@/hooks/web/useMessage';
import { getMenuList } from '@/api/demo/system';
import { useI18n } from '@/hooks/web/useI18n';
import ModuleModal from './modalForm-Modal.vue';
import { functionGetSchemePageList } from '@/api/demo/formScheme';
import { functionGetSchemePageList, functionGetForm } from '@/api/demo/formScheme';
// emit
const emit = defineEmits(['change-form-verisons']);
const emit = defineEmits(['change-form-verisons', 'set-steps-current']);
// message
const { createMessage } = useMessage();
// useI18n
const { t } = useI18n();
// props
const props = defineProps({
editData: {
type: Object,
default: () => ({}),
},
isNextSteps: {
type: Boolean,
default: () => false,
},
});
//
const labelCol = { span: 4 };
const wrapperCol = { span: 20 };
@ -105,6 +115,7 @@
name: '',
icon: 'ant-design:star-outlined',
formCode: '',
formCodeName: '',
formVerison: '',
pmoduleId: '',
moduleId: '',
@ -118,17 +129,54 @@
code: [{ required: true, message: '请输入' }],
name: [{ required: true, message: '请输入' }],
icon: [{ component: 'IconPicker', required: true, message: '请输入' }],
formCode: [{ required: true, message: '请输入' }],
formCodeName: [{ required: true, message: '请输入' }],
formVerison: [{ required: true, message: '请选择版本' }],
pmoduleId: [{ required: true, message: '请输入' }],
enabledMark: [{ required: true }],
};
// props
watch(
() => props.editData,
() => {
if (props.editData.formEdit) {
//
setFormData(props.editData.record);
} else {
//
formData.value = props.editData.record;
}
},
);
// props
watch(
() => props.isNextSteps,
() => {
//
if (props.isNextSteps) {
let checkdata = formData.value;
if (
checkdata.code === '' ||
checkdata.formCode === '' ||
checkdata.name === '' ||
checkdata.formVerison === '' ||
checkdata.pmoduleId === ''
) {
createMessage.error(t('数据未填完整'));
emit('set-steps-current', false);
} else {
emit('set-steps-current', true);
}
}
},
);
// formVerison
watch(
() => formData.value.formVerison,
() => {
changevalidateSteps();
if (formData.value.formVerison) {
changevalidateSteps();
}
},
);
@ -139,14 +187,15 @@
//
async function getSchemeRow(row) {
let formVerisons_temp = [];
formData.value.formCode = row[0];
formData.value.formCode = row.id;
formData.value.formCodeName = row.name;
//
const historyData = await functionGetSchemePageList({ schemeInfoId: row[0].id });
const historyData = await functionGetSchemePageList({ schemeInfoId: row.id });
historyData.items.forEach((t) => {
formVerisons_temp.push({ label: t.createDate, value: t.id });
});
formVerisons.value = formVerisons_temp;
formData.value.formVerison = formVerisons_temp[0];
formData.value.formVerison = formVerisons_temp[0].value;
}
//
@ -159,6 +208,14 @@
pmoduleIds.value = await getMenuList();
}
//
async function setFormData(record) {
// infoscheme
const result = await functionGetForm({ id: record.formCode });
formData.value = record;
getSchemeRow(result.info);
}
defineExpose({
formData,
});

View File

@ -285,8 +285,6 @@
//
function findModuleName(modules, pmoduleId) {
for (const module of modules) {
if (module.itemValue === pmoduleId) {
return module.itemName;

View File

@ -8,8 +8,9 @@
import { BasicModal, useModalInner } from '@/components/Modal';
import { BasicForm, useForm } from '@/components/Form';
import { accountFormSchema } from './account.data';
import { getDeptList ,addAccount} from '@/api/demo/system';
import { addAccount } from '@/api/demo/system';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
defineOptions({ name: 'AccountModal' });
const emit = defineEmits(['success', 'register']);
@ -17,7 +18,7 @@
const isUpdate = ref(true);
const rowId = ref('');
const [registerForm, { setFieldsValue, updateSchema, resetFields, validate }] = useForm({
const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({
labelWidth: 100,
baseColProps: { span: 24 },
schemas: accountFormSchema,
@ -46,10 +47,15 @@
try {
const values = await validate();
setModalProps({ confirmLoading: true });
const data = await addAccount(values)
// TODO custom api
closeModal();
emit('success', { isUpdate: unref(isUpdate), values: { ...values, id: rowId.value } });
const data = await addAccount(values);
if (data) {
// TODO custom api
closeModal();
emit('success', { isUpdate: unref(isUpdate), values: { ...values, id: rowId.value } });
return createMessage.success('成功');
} else {
return createMessage.error('失败');
}
} finally {
setModalProps({ confirmLoading: false });
}

View File

@ -9,14 +9,14 @@
</BasicModal>
</template>
<script lang="ts" setup>
import { onMounted, ref, computed, unref } from 'vue';
import { onMounted, ref, unref } from 'vue';
import { BasicModal, useModalInner } from '@/components/Modal';
import { BasicForm, useForm } from '@/components/Form';
import { accountFormSchema } from './account.data';
import { getRoleListByPage, userRoles } from '@/api/demo/system';
import { Select } from 'ant-design-vue';
import type { SelectProps } from 'ant-design-vue';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
defineOptions({ name: 'AssignRoleModal' });
const emit = defineEmits(['success', 'register']);
@ -24,7 +24,7 @@
const isUpdate = ref(true);
const rowId = ref('');
const valueSelect = ref < string[] > ([]);
const [registerForm, { setFieldsValue, updateSchema, resetFields, validate }] = useForm({
const [registerForm, { setFieldsValue, resetFields, validate }] = useForm({
labelWidth: 100,
baseColProps: { span: 24 },
schemas: [
@ -47,11 +47,8 @@
});
const roleList = ref < SelectProps['options'] > ([]);
async function getRole() {
var data = await getRoleListByPage({
page: 1,
limit: 999
})
const arr = []
var data = await getRoleListByPage()
const arr:any[] = []
data.items.forEach(element => {
arr.push({
label: element.name,
@ -73,8 +70,6 @@
}
});
const getTitle = computed(() => (!unref(isUpdate) ? '新增账号' : '编辑账号'));
async function handleSubmit() {
try {
const values = await validate();
@ -84,9 +79,14 @@
roleIds: valueSelect.value
}
const data = await userRoles(query)
// TODO custom api
closeModal();
emit('success', { isUpdate: unref(isUpdate), values: { ...values, id: rowId.value } });
if (data) {
// TODO custom api
closeModal();
emit('success', { isUpdate: unref(isUpdate), values: { ...values, id: rowId.value } });
return createMessage.success('成功');
} else {
return createMessage.error('失败');
}
} finally {
setModalProps({ confirmLoading: false });
}

View File

@ -8,7 +8,7 @@
<script lang="ts" setup>
import { onMounted, ref ,nextTick,unref} from 'vue';
import { BasicTree, TreeItem } from '@/components/Tree';
import { BasicTree, TreeItem ,TreeActionType} from '@/components/Tree';
import { getDeptList } from '@/api/demo/system';
defineOptions({ name: 'DeptTree' });

View File

@ -1,61 +1,70 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" title="分配部门和职级" @ok="handleSubmit">
<BasicTree ref="asyncExpandTreeRef" title="部门和职级列表" toolbar treeWrapperClassName="h-[calc(100%-35px)] overflow-auto"
loadData :clickRowToExpand="false" :treeData="treeData" :fieldNames="{ key: 'id', title: 'name' }"
:defaultExpandAll="true" :checkable="true" :checkStrictly="true" @check="handleSelect" />
<BasicTree
ref="asyncExpandTreeRef"
title="部门和职级列表"
toolbar
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto"
loadData
:clickRowToExpand="false"
:treeData="treeData"
:fieldNames="{ key: 'id', title: 'name' }"
:defaultExpandAll="true"
:checkable="true"
:checkStrictly="true"
@check="handleSelect"
/>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, computed, unref, onMounted, nextTick } from 'vue';
import { ref, unref, onMounted, nextTick } from 'vue';
import { BasicModal, useModalInner } from '@/components/Modal';
import { accountFormSchema } from './account.data';
import { BasicTree, TreeItem } from '@/components/Tree';
import { getOrgPositonTree,userOrgs } from '@/api/demo/system';
import { useMessage } from '/@/hooks/web/useMessage';
import { BasicTree, TreeItem, TreeActionType } from '@/components/Tree';
import { getOrgPositonTree, userOrgs } from '@/api/demo/system';
import { useMessage } from '@/hooks/web/useMessage';
defineOptions({ name: 'OrgPositonModal' });
const emit = defineEmits(['success', 'register', 'select']);
const treeData = ref < TreeItem[] > ([]);
const asyncExpandTreeRef = ref < Nullable < TreeActionType >> (null);
const { createConfirm, createMessage } = useMessage();
const checkedKeys = ref<number[]>([]);
const treeData = ref<TreeItem[]>([]);
const asyncExpandTreeRef = ref<Nullable<TreeActionType>>(null);
const { createMessage } = useMessage();
function treeIterator(tree) {
tree.forEach((node) => {
if (node.key == 0) {
node.name = "部门--" + node.name
node.name = '部门--' + node.name;
} else {
node.name = "职级--" + node.name
node.name = '职级--' + node.name;
}
node.children && treeIterator(node.children)
})
node.children && treeIterator(node.children);
});
}
async function fetch() {
const data = (await getOrgPositonTree()) as unknown as TreeItem[];
treeIterator(data)
treeData.value = await data
treeIterator(data);
treeData.value = await data;
//
nextTick(() => {
unref(asyncExpandTreeRef)?.expandAll(true);
});
}
let orgList = ref([])
let posList = ref([])
function handleSelect(checkedKeys, e: { checked: bool, checkedNodes, node, event }) {
const list = e.checkedNodes
orgList.value = []
posList.value = []
list.forEach(element => {
let orgList:any = ref([]);
let posList:any = ref([]);
function handleSelect(checkedKeys, e: { checked: boolean; checkedNodes; node; event }) {
const list = e.checkedNodes;
orgList.value = [];
posList.value = [];
list.forEach((element) => {
if (element.key > 0) {
posList.value.push({
orgId: Number(element.tag),
posId: element.id,
})
});
} else {
orgList.value.push({
orgId: element.id,
posId: 0,
})
});
}
});
}
@ -84,36 +93,41 @@
return createMessage.warn('一个部门只能选择一个职级');
}
}
var query = {}
const arrs = posList.value.map(item => {
const data = orgList.value.find(i => item.orgId == i.orgId)
var query = {};
const arrs = posList.value.map((item) => {
const data = orgList.value.find((i) => item.orgId == i.orgId);
return {
...data,
...item,
}
})
};
});
if (posList.value.length == 0) {
query = {
userId: rowId.value,
orgPoses: orgList.value
}
orgPoses: orgList.value,
};
} else if (orgList.length == 0) {
query = {
userId: rowId.value,
orgPoses: posList.value
}
orgPoses: posList.value,
};
} else {
query = {
userId: rowId.value,
orgPoses: arrs
}
orgPoses: arrs,
};
}
const data = await userOrgs(query);
if(data){
setModalProps({ confirmLoading: true });
closeModal();
emit('success');
return createMessage.success('成功');
}else{
return createMessage.error('失败');
}
const data = await userOrgs(query)
setModalProps({ confirmLoading: true });
closeModal();
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>
</script>

View File

@ -15,30 +15,26 @@
<script lang="ts" setup>
import { reactive } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { BasicTable, useTable } from '@/components/Table';
import { getAccountList, deleteAccount } from '@/api/demo/system';
import { PageWrapper } from '@/components/Page';
import DeptTree from './DeptTree.vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useModal } from '@/components/Modal';
import AccountModal from './AccountModal.vue';
import AssignRoleModal from './AssignRoleModal.vue';
import OrgPositonModal from './OrgPositonModal.vue';
const { createConfirm, createMessage } = useMessage();
import { DeptTree} from './page';
import { AccountModal} from './page';
import { AssignRoleModal} from './page';
import { OrgPositonModal} from './page';
import { columns, searchFormSchema } from './account.data';
import { useGo } from '@/hooks/web/usePage';
import PermissionBtn from '@/components/PermissionBtn/index.vue'
import {PermissionBtn} from '@/components/PermissionBtn/index';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage,createConfirm } = useMessage();
defineOptions({ name: 'AccountManagement' });
const go = useGo();
const [registerModal, { openModal:openAccountModal }] = useModal();
const [registerModal, { openModal: openAccountModal }] = useModal();
const [registerRoleModal, { openModal: openRoleModal }] = useModal();
const [registerOrgPositonModal, { openModal: openOrgPositonModal }] = useModal();
const searchInfo = reactive < Recordable > ({});
const [registerTable, { reload, updateTableDataRecord, getSelectRows, clearSelectedRowKeys }] = useTable({
const searchInfo = reactive<Recordable>({});
const [registerTable, { reload, getSelectRows, clearSelectedRowKeys }] = useTable({
title: '账号列表',
api: getAccountList,
rowKey: 'id',
@ -48,7 +44,8 @@
schemas: searchFormSchema,
autoSubmitOnEnter: true,
},
rowSelection: {//
rowSelection: {
//
// type: 'checkbox',
type: 'radio',
},
@ -71,7 +68,7 @@
if (rows.length == 0) {
return createMessage.warn('请勾选一个账号进行编辑');
}
const record = rows[0]
const record = rows[0];
openAccountModal(true, {
record,
isUpdate: true,
@ -83,20 +80,25 @@
if (rows.length == 0) {
return createMessage.warn('请勾选一个账号进行删除');
}
const query = [rows[0].id]
const query = [rows[0].id];
createConfirm({
iconType: 'info',
title: '删除',
content: '确定要删除当前账号吗',
onOk: async () => {
const data = await deleteAccount(query);
handleSuccess()
if (data) {
return createMessage.success('删除成功');
handleSuccess();
} else {
return createMessage.error('删除失败');
}
},
});
}
function handleSuccess() {
clearSelectedRowKeys()
clearSelectedRowKeys();
reload();
}
@ -105,21 +107,18 @@
reload();
}
function handleView(record: Recordable) {
go('/system/account_detail/' + record.id);
}
function onBtnClicked(domId) {
let rows = getSelectRows();
const record = rows[0]
const record = rows[0];
switch (domId) {
case 'btnAdd':
handleCreate()
handleCreate();
break;
case 'btnEdit':
handleEdit()
handleEdit();
break;
case 'btnDelete':
handleDelete()
handleDelete();
break;
case 'btnAssignRoles':
if (rows.length == 0) {
@ -130,7 +129,7 @@
isUpdate: true,
});
break;
case 'btnOrgPositon':
case 'btnOrgPositon':
if (rows.length == 0) {
return createMessage.warn('请勾选一个账号分配部门和职级');
}
@ -138,9 +137,10 @@
record,
isUpdate: true,
});
break;
break;
default:
break;
}
}
</script>
</script>
./page.ts

View File

@ -0,0 +1,7 @@
export { default as DeptTree } from './DeptTree.vue';
export { default as AccountDetail } from './AccountDetail.vue';
export { default as AccountModal } from './AccountModal.vue';
export { default as OrgPositonModal } from './OrgPositonModal.vue';
export { default as AssignRoleModal } from './AssignRoleModal.vue';

View File

@ -11,7 +11,7 @@
</template>
<script lang="ts" setup>
import { onMounted, ref, h, nextTick, unref } from 'vue';
import { BasicTree, TreeItem, TreeActionItem } from '@/components/Tree';
import { BasicTree, TreeItem, TreeActionItem ,TreeActionType} from '@/components/Tree';
import { getMenuList, deleteMenu } from '@/api/demo/system';
import { FormOutlined, DeleteOutlined } from '@ant-design/icons-vue';
import { BasicModal, useModal } from '@/components/Modal';

View File

@ -24,7 +24,7 @@
import MenuDrawer from './MenuDrawer.vue';
import { columns, searchFormSchema } from './menu.data';
import PermissionBtn from '@/components/PermissionBtn/index.vue'
import {PermissionBtn} from '@/components/PermissionBtn/index'
import { useMessage } from '@/hooks/web/useMessage';
const { createConfirm,createMessage } = useMessage();
defineOptions({ name: 'MenuManagement' });

View File

@ -0,0 +1,124 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" :canFullscreen="false" @ok="handleSubmit">
<BasicForm @register="registerForm">
<template #dbConnection="{ model, field }">
<a-input-search
v-model:value="dbConnection"
placeholder="请输入"
enter-button="测试连接"
@change="inputChange"
@search="connectClick"
>
</a-input-search>
</template>
</BasicForm>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, computed, unref } from 'vue';
import { BasicModal, useModalInner } from '@/components/Modal';
import { BasicForm, useForm } from '@/components/Form';
import { formSchema } from './index.data';
import {addDataBaseInfo,editDataBaseInfo,testDataBaseConnection } from '@/api/database';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
defineOptions({ name: 'DataBaseModal' });
const emit = defineEmits(['success', 'register']);
const isUpdate = ref(true);
const dbConnection = ref();
const detailValue = ref();
const [registerForm, { resetFields, setFieldsValue,getFieldsValue, validate }] = useForm({
labelWidth: 100,
baseColProps: { span: 24 },
schemas: formSchema,
showActionButtonGroup: false,
});
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
resetFields();
setModalProps({ confirmLoading: false });
isUpdate.value = !!data?.isUpdate;
detailValue.value = data.record;
if (unref(isUpdate)) {
dbConnection.value = data.record.dbConnection
setFieldsValue({
...data.record,
});
}else{
dbConnection.value = null
}
});
const getTitle = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
async function connectClick() {
console.log('click',detailValue)
console.log('dbConnection',dbConnection)
console.log('click123',getFieldsValue())
const formVlaue = getFieldsValue()
if(dbConnection.value){
if(formVlaue.dbType){
let param = {
connection: dbConnection.value,
dbType: formVlaue.dbType ,
}
testDataBaseConnection(param).then( res =>{
console.log('rrrreeee',res)
if(res){
createMessage.success('连接成功',2)
}else{
createMessage.error('连接失败',2)
}
})
}else{
createMessage.warning('请先选择数据库类型!',1)
}
}else{
createMessage.warning('请填写连接串!',1);
}
};
async function inputChange(e){
setFieldsValue({
dbConnection: dbConnection.value
})
};
async function handleSubmit() {
try {
const values = await validate();
let query = values;
//
if (!unref(isUpdate)) {
const data = await addDataBaseInfo(query);
if (data) {
setModalProps({ confirmLoading: true });
closeModal();
emit('success');
return createMessage.success('新增成功');
} else {
return createMessage.error('新增失败');
}
} else {
query.databaseLinkId = detailValue.value.databaseLinkId
const data = await editDataBaseInfo(query);
if (data) {
setModalProps({ confirmLoading: true });
closeModal();
emit('success');
return createMessage.success('编辑成功');
} else {
return createMessage.error('编辑失败');
}
}
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>

View File

@ -0,0 +1,103 @@
import { BasicColumn, FormSchema } from '@/components/Table';
import { h } from 'vue';
import { Tag } from 'ant-design-vue';
export const columns: BasicColumn[] = [
{
title: '名称',
dataIndex: 'dbName',
},
{
title: '编码',
dataIndex: 'dbAlias',
},
{
title: '类型',
dataIndex: 'dbType',
},
{
title: '数据库地址',
dataIndex: 'serverAddress',
},
];
export const searchFormSchema: FormSchema[] = [
{
field: 'keyWord',
label: '名称',
component: 'Input',
colProps: { span: 8 },
},
];
export const formSchema: FormSchema[] = [
{
field: 'dbAlias',
label: '编码',
component: 'Input',
required: true,
},
{
field: 'dbName',
label: '名称',
component: 'Input',
required: true,
},
{
field: 'dbType',
label: '类型',
component: 'Select',
componentProps: {
options: [
{
label: 'MySql',
value: 'MySql'
},
{
label: 'SqlServer',
value: 'SqlServer'
},
{
label: 'Oracle',
value: 'Oracle'
},
{
label: 'PostgreSQL',
value: 'PostgreSQL'
},
{
label: '达梦',
value: 'Dameng'
},
{
label: '人大金仓',
value: 'Kdbndp'
}
]
}
},
{
field: 'serverAddress',
label: '服务器地址',
component: 'Input',
required: true,
},
{
field: 'dbConnection',
label: '连接串',
colProps: {
span: 24,
},
rules: [
{
required: true,
message: '请输入连接串',
},
],
slot: 'dbConnection',
},
{
field: 'description',
label: '说明',
component: 'InputTextArea'
}
];

View File

@ -0,0 +1,118 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable
@register="registerTable"
:searchInfo="searchInfo"
>
<template #toolbar>
<PermissionBtn @btn-event="onBtnClicked" />
</template>
</BasicTable>
<DataBaseModal @register="registerModal" @success="handleSuccess" ></DataBaseModal>
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive, nextTick, ref, onMounted } from 'vue';
import DataBaseModal from './DataBaseModal.vue';
import { BasicTable, useTable } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { useMessage } from '@/hooks/web/useMessage';
import PermissionBtn from '@/components/PermissionBtn/index.vue';
import { useModal } from '@/components/Modal';
import { columns, searchFormSchema } from './index.data';
import {getDataBasePageList,delDataBaseInfo } from '@/api/database';
const { createConfirm, createMessage } = useMessage();
const searchInfo = reactive<Recordable>({});
//
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
title: '数据库连接列表',
api: getDataBasePageList,
columns,
rowKey: 'databaseLinkId',
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
},
//
showIndexColumn: true,
// 使
useSearchForm: true,
//
showTableSetting: true,
bordered: true,
rowSelection: {
//
type: 'radio',
},
handleSearchInfoFn(info) {
return info;
},
});
const [registerModal, { openModal }] = useModal();
function handleSuccess(){
reload()
}
//
function handleAddForm() {
openModal(true, {
isUpdate: false,
});
}
function handleEdit() {
let rows = getSelectRows();
console.log('rows',rows)
if (rows.length == 0) {
return createMessage.warn('请选择一条数据进行编辑');
}
openModal(true, {
record:rows[0],
isUpdate: true,
});
}
// -
function handleDelete() {
let rows = getSelectRows();
if (rows.length == 0) {
return createMessage.warn('请选择一条数据进行删除');
}
console.log('rrr',rows)
var query = {
id: rows[0].databaseLinkId,
};
createConfirm({
iconType: 'info',
title: '删除',
content: '确定要删除该条数据?',
onOk: async () => {
delDataBaseInfo(query).then(res =>{
if(res){
createMessage.success('删除成功',2);
}else{
createMessage.error('删除失败',2);
}
})
reload();
},
});
}
//
function onBtnClicked(domId) {
switch (domId) {
case 'btnAdd':
handleAddForm();
break;
case 'btnEdit':
handleEdit();
break;
case 'btnDelete':
handleDelete();
break;
default:
break;
}
}
</script>

View File

@ -9,8 +9,9 @@
import { BasicForm, useForm } from '@/components/Form';
import { formSchema } from './dept.data';
import { getDeptList, addDept ,updateDept} from '@/api/demo/system';
import { getDeptList, addDept, updateDept } from '@/api/demo/system';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
defineOptions({ name: 'DeptModal' });
const emit = defineEmits(['success', 'register']);
@ -38,7 +39,7 @@
updateSchema({
field: 'parentId',
componentProps: { treeData },
},);
});
});
const getTitle = computed(() => (!unref(isUpdate) ? '新增部门' : '编辑部门'));
@ -46,19 +47,31 @@
async function handleSubmit() {
try {
const values = await validate();
let query = values
let query = values;
//
if(!unref(isUpdate)){
if (!unref(isUpdate)) {
const data = await addDept(query);
}else{
if (data) {
setModalProps({ confirmLoading: true });
closeModal();
emit('success');
return createMessage.success('新增成功');
} else {
return createMessage.error('新增失败');
}
} else {
const data = await updateDept(query);
if (data) {
setModalProps({ confirmLoading: true });
closeModal();
emit('success');
return createMessage.success('编辑成功');
} else {
return createMessage.error('编辑失败');
}
}
setModalProps({ confirmLoading: true });
// TODO custom api
closeModal();
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>
</script>

View File

@ -9,7 +9,7 @@
<script lang="ts" setup>
import { onMounted, ref , nextTick, unref} from 'vue';
import { BasicTree, TreeItem } from '@/components/Tree';
import { BasicTree, TreeItem ,TreeActionType} from '@/components/Tree';
import { getDeptList } from '@/api/demo/system';
defineOptions({ name: 'DeptTree' });

View File

@ -4,18 +4,19 @@
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, computed, unref, defineProps } from 'vue';
import { ref } from 'vue';
import { BasicModal, useModalInner } from '@/components/Modal';
import { BasicForm, useForm } from '@/components/Form';
import { formGroupSchema } from './dept.data';
import { getDeptList, addDept ,orgPosGroup} from '@/api/demo/system';
import { orgPosGroup} from '@/api/demo/system';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
defineOptions({ name: 'PosGroupModal' });
const emit = defineEmits(['success', 'register']);
const [registerForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
labelWidth: 100,
baseColProps: { span: 24 },
schemas: formGroupSchema,
@ -42,10 +43,15 @@
}
//
const data = await orgPosGroup(query);
setModalProps({ confirmLoading: true });
// TODO custom api
closeModal();
emit('success');
if(data){
setModalProps({ confirmLoading: true });
// TODO custom api
closeModal();
emit('success');
return createMessage.success('成功');
}else{
return createMessage.error('失败');
}
} finally {
setModalProps({ confirmLoading: false });
}

View File

@ -15,16 +15,16 @@
<script lang="ts" setup>
import { reactive, ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { getDeptList, getOrgList, orgPosGroup, deleteDept } from '@/api/demo/system';
import { BasicTable, useTable } from '@/components/Table';
import { getOrgList, deleteDept } from '@/api/demo/system';
import { PageWrapper } from '@/components/Page';
import DeptTree from './DeptTree.vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { useModal } from '@/components/Modal';
import DeptModal from './DeptModal.vue';
import PosGroupModal from './PosGroupModal.vue';
import PermissionBtn from '@/components/PermissionBtn/index.vue'
import { useMessage } from '@/hooks/web/useMessage';
import {DeptTree} from './page';
import {DeptModal} from './page';
import {PosGroupModal} from './page';
import {PermissionBtn} from '@/components/PermissionBtn/index';
import { columns, searchFormSchema } from './dept.data';
defineOptions({ name: 'DeptManagement' });
@ -32,7 +32,7 @@
const [registerModal, { openModal: openDeptModal }] = useModal();
const [registerPosGroupModal, { openModal: openPosGroupModal }] = useModal();
const searchInfo = reactive < Recordable > ({});
const searchInfo = reactive<Recordable>({});
const [registerTable, { reload, getSelectRows }] = useTable({
title: '部门列表',
@ -43,7 +43,8 @@
labelWidth: 120,
schemas: searchFormSchema,
},
rowSelection: {//
rowSelection: {
//
// type: 'checkbox',
type: 'radio',
},
@ -59,13 +60,13 @@
if (!rows.length) {
return createMessage.warn('请选择一个部门');
}
var record = rows[0]
var record = rows[0];
openPosGroupModal(true, {
record,
isUpdate: false,
});
}
const childRef = ref < any > ()
const childRef = ref<any>();
function handleCreate() {
openDeptModal(true, {
@ -78,7 +79,7 @@
if (rows.length == 0) {
return createMessage.warn('请选择一个部门进行编辑');
}
const record = rows[0]
const record = rows[0];
openDeptModal(true, {
record,
isUpdate: true,
@ -90,30 +91,35 @@
if (rows.length == 0) {
return createMessage.warn('请选择一个部门进行删除');
}
const query = [rows[0].id]
const query = [rows[0].id];
createConfirm({
iconType: 'info',
title: '删除',
content: '确定要删除当前部门吗',
onOk: async () => {
const data = await deleteDept(query);
handleSuccess();
if (data) {
return createMessage.success('删除成功');
handleSuccess();
} else {
return createMessage.error('删除失败');
}
},
});
}
function onBtnClicked(domId) {
switch (domId) {
case 'btnAdd':
handleCreate()
handleCreate();
break;
case 'btnEdit':
handleEdit()
handleEdit();
break;
case 'btnDelete':
handleDelete()
handleDelete();
break;
case 'btnPoGroup':
handlePoGroup()
handlePoGroup();
break;
default:
break;
@ -127,4 +133,4 @@
childRef.value.fetch();
reload();
}
</script>
</script>

View File

@ -0,0 +1,5 @@
export { default as DeptTree } from './DeptTree.vue';
export { default as DeptModal } from './DeptModal.vue';
export { default as PosGroupModal } from './PosGroupModal.vue';

View File

@ -1,5 +1,12 @@
<template>
<BasicDrawer v-bind="$attrs" @register="registerDrawer" showFooter :title="getTitle" width="50%" @ok="handleSubmit">
<BasicDrawer
v-bind="$attrs"
@register="registerDrawer"
showFooter
:title="getTitle"
width="50%"
@ok="handleSubmit"
>
<BasicForm @register="registerForm" />
</BasicDrawer>
</template>
@ -10,7 +17,8 @@
import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
import { getMenuList, addMenu, editMenu, addButton, editButton } from '@/api/demo/system';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
defineOptions({ name: 'MenuDrawer' });
const emit = defineEmits(['success', 'register']);
@ -53,29 +61,52 @@
setDrawerProps({ confirmLoading: true });
// TODO custom api
if (values.type == '1') {
delete values.type
delete values.type;
//
if (!unref(isUpdate)) {
const data = await addMenu(values);
if (data) {
closeDrawer();
emit('success');
return createMessage.success('新增成功');
} else {
return createMessage.error('新增失败');
}
} else {
const data = await editMenu(values);
if (data) {
closeDrawer();
emit('success');
return createMessage.success('编辑成功');
} else {
return createMessage.error('编辑失败');
}
}
closeDrawer();
emit('success');
} else {
//
delete values.type
delete values.type;
if (!unref(isUpdate)) {
const data = await addButton(values);
if (data) {
closeDrawer();
emit('success');
return createMessage.info('创建成功');
} else {
return createMessage.error('创建失败');
}
} else {
const data = await editButton(values);
if (data) {
closeDrawer();
emit('success');
return createMessage.success('编辑成功');
} else {
return createMessage.error('编辑失败');
}
}
closeDrawer();
emit('success');
}
} finally {
setDrawerProps({ confirmLoading: false });
}
}
</script>
</script>

View File

@ -1,35 +1,56 @@
<template>
<div class="m-4 mr-0 overflow-hidden bg-white">
<BasicTree ref="asyncExpandTreeRef" title="菜单列表" toolbar search
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto" loadData :actionList="actionList"
:renderIcon="createIcon" :clickRowToExpand="false" :treeData="treeData" :fieldNames="{ key: 'id', title: 'name' }"
:defaultExpandAll="true" @select="handleSelect" />
<BasicModal @register="register" title="删除" :helpMessage="['提示1', '提示2']" @ok="handleSubmit">
<BasicTree
ref="asyncExpandTreeRef"
title="菜单列表"
toolbar
search
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto"
loadData
:actionList="actionList"
:renderIcon="createIcon"
:clickRowToExpand="false"
:treeData="treeData"
:fieldNames="{ key: 'id', title: 'name' }"
:defaultExpandAll="true"
@select="handleSelect"
/>
<BasicModal
@register="register"
title="删除"
:helpMessage="['提示1', '提示2']"
@ok="handleSubmit"
>
确认要删除菜单吗
</BasicModal>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref, h, nextTick, unref } from 'vue';
import { BasicTree, TreeItem, TreeActionItem } from '@/components/Tree';
import { BasicTree, TreeItem, TreeActionItem, TreeActionType } from '@/components/Tree';
import { getMenuList, deleteMenu } from '@/api/demo/system';
import { FormOutlined, DeleteOutlined } from '@ant-design/icons-vue';
import { BasicModal, useModal } from '@/components/Modal';
import { router } from '@/router';
const [register, { closeModal, openModal }] = useModal();
defineOptions({ name: 'DeptTree' });
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
const emit = defineEmits(['select', 'edit']);
const treeData = ref < TreeItem[] > ([]);
let selectItemId = ref('')
const asyncExpandTreeRef = ref < Nullable < TreeActionType >> (null);
const treeData = ref<TreeItem[]>([]);
let selectItemId = ref('');
const asyncExpandTreeRef = ref<Nullable<TreeActionType>>(null);
async function handleSubmit() {
var query = [selectItemId.value]
var query = [selectItemId.value];
const data = await deleteMenu(query);
closeModal();
if (data) {
closeModal();
return createMessage.success('删除成功');
} else {
return createMessage.info('删除失败');
}
}
async function fetch() {
@ -43,9 +64,9 @@
function handleSelect(keys) {
emit('select', keys[0]);
}
const btnList = router.currentRoute.value.meta.elements
const actionList: TreeActionItem[] = []
btnList.forEach(element => {
const btnList = router.currentRoute.value.meta.elements;
const actionList: TreeActionItem[] = [];
btnList.forEach((element) => {
if (element.domId == 'btnEdit') {
actionList.push({
render: (node) => {
@ -56,21 +77,21 @@
},
});
},
})
});
} else if (element.domId == 'btnDelete') {
actionList.push({
render: (node) => {
return h(DeleteOutlined, {
class: 'ml-2',
onClick: () => {
selectItemId.value = node.id
selectItemId.value = node.id;
openModal(true, {
isUpdate: false,
});
},
});
},
})
});
}
});
@ -90,6 +111,6 @@
fetch();
});
defineExpose({
fetch
})
</script>
fetch,
});
</script>

View File

@ -1,8 +1,12 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<MenuTree ref="childRef" class="w-1/4 xl:w-1/5" @select="handleSelect" @edit="editMenu" />
<BasicTable class="w-3/4 xl:w-4/5" @register="registerTable" @fetch-success="onFetchSuccess"
:searchInfo="searchInfo">
<BasicTable
class="w-3/4 xl:w-4/5"
@register="registerTable"
@fetch-success="onFetchSuccess"
:searchInfo="searchInfo"
>
<template #toolbar>
<!-- <a-button type="primary" @click="handleCreate"> </a-button> -->
<PermissionBtn @btnEvent="onBtnClicked"></PermissionBtn>
@ -10,32 +14,31 @@
</BasicTable>
<MenuDrawer @register="registerDrawer" @success="handleSuccess" />
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive, nextTick, ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { getMenuList, getButtonList, getMenuDetail, deleteButton } from '@/api/demo/system';
import { BasicTable, useTable } from '@/components/Table';
import { getButtonList, getMenuDetail, deleteButton } from '@/api/demo/system';
import { PageWrapper } from '@/components/Page';
import MenuTree from './MenuTree.vue';
import { useDrawer } from '@/components/Drawer';
import MenuDrawer from './MenuDrawer.vue';
import { MenuTree } from './page';
import { MenuDrawer } from './page';
import { columns, searchFormSchema } from './menu.data';
import PermissionBtn from '@/components/PermissionBtn/index.vue'
import { PermissionBtn } from '@/components/PermissionBtn/index';
import { useMessage } from '@/hooks/web/useMessage';
const { createConfirm,createMessage } = useMessage();
const { createConfirm, createMessage } = useMessage();
defineOptions({ name: 'MenuManagement' });
const searchInfo = reactive < Recordable > ({});
const searchInfo = reactive<Recordable>({});
const [registerDrawer, { openDrawer }] = useDrawer();
const [registerTable, { reload, expandAll, getSelectRows,clearSelectedRowKeys }] = useTable({
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
title: '按钮列表',
api: getButtonList,
columns,
rowKey:'id',
rowKey: 'id',
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
@ -46,7 +49,8 @@
showTableSetting: true,
bordered: true,
showIndexColumn: false,
rowSelection: {//
rowSelection: {
//
// type: 'checkbox',
type: 'radio',
},
@ -54,7 +58,7 @@
return info;
},
});
const childRef = ref < any > ()
const childRef = ref<any>();
function handleCreate() {
openDrawer(true, {
isUpdate: false,
@ -63,11 +67,11 @@
function handleEdit() {
let rows = getSelectRows();
if(rows.length == 0){
if (rows.length == 0) {
return createMessage.warn('请选择一个按钮进行编辑');
}
const record = rows[0]
record.type = '2'
const record = rows[0];
record.type = '2';
openDrawer(true, {
record,
isUpdate: true,
@ -75,10 +79,10 @@
}
async function editMenu(node) {
var query = {
id: node.id
}
id: node.id,
};
const record = await getMenuDetail(query);
record.type = '1'
record.type = '1';
openDrawer(true, {
record,
isUpdate: true,
@ -86,29 +90,34 @@
}
function handleSelect(ModuleId = '') {
searchInfo.ModuleId = ModuleId;
clearSelectedRowKeys()
clearSelectedRowKeys();
reload();
}
async function handleDelete(record: Recordable) {
async function handleDelete() {
let rows = getSelectRows();
if(rows.length == 0){
if (rows.length == 0) {
return createMessage.warn('请选择一个按钮进行删除');
}
const query = [rows[0].id]
const query = [rows[0].id];
createConfirm({
iconType: 'info',
title: '删除',
content: '确定要删除当前按钮吗',
onOk: async () => {
const data = await deleteButton(query);
reload();
if (data) {
reload();
return createMessage.success('成功');
} else {
return createMessage.error('失败');
}
},
});
}
function handleSuccess() {
childRef.value.fetch();
clearSelectedRowKeys()
clearSelectedRowKeys();
reload();
}
@ -119,16 +128,16 @@
function onBtnClicked(domId) {
switch (domId) {
case 'btnAdd':
handleCreate()
handleCreate();
break;
case 'btnEdit':
handleEdit()
handleEdit();
break;
case 'btnDelete':
handleDelete()
handleDelete();
break;
default:
break;
}
}
</script>
</script>

View File

@ -0,0 +1,4 @@
export { default as MenuDrawer } from './MenuDrawer.vue';
export { default as MenuTree } from './MenuTree.vue';

View File

@ -1,5 +1,12 @@
<template>
<BasicDrawer v-bind="$attrs" @register="registerDrawer" showFooter :title="getTitle" width="50%" @ok="handleSubmit">
<BasicDrawer
v-bind="$attrs"
@register="registerDrawer"
showFooter
:title="getTitle"
width="50%"
@ok="handleSubmit"
>
<BasicForm @register="registerForm" />
</BasicDrawer>
</template>
@ -8,8 +15,9 @@
import { BasicForm, useForm } from '@/components/Form';
import { formSchema } from './position.data';
import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
import { getPosGroupList, getPositionList, addPosGroup, editMenu, addPosition, editButton, getPositionsTree } from '@/api/demo/system';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
import { addPosGroup, editMenu, addPosition, editButton } from '@/api/demo/system';
defineOptions({ name: 'MenuDrawer' });
@ -17,7 +25,7 @@
const isUpdate = ref(true);
const [registerForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
labelWidth: 100,
schemas: formSchema,
showActionButtonGroup: false,
@ -36,7 +44,6 @@
}
});
const getTitle = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
async function handleSubmit() {
@ -45,29 +52,52 @@
setDrawerProps({ confirmLoading: true });
// TODO custom api
if (values.type == 1) {
delete values.type
delete values.type;
//
if (!unref(isUpdate)) {
const data = await addPosGroup(values);
if (data) {
closeDrawer();
emit('success');
return createMessage.success('新增成功');
} else {
return createMessage.error('新增失败');
}
} else {
const data = await editMenu(values);
if (data) {
closeDrawer();
emit('success');
return createMessage.success('编辑成功');
} else {
return createMessage.error('编辑失败');
}
}
closeDrawer();
emit('success');
} else {
//
delete values.type
delete values.type;
if (!unref(isUpdate)) {
const data = await addPosition(values);
if (data) {
closeDrawer();
emit('success');
return createMessage.success('新增成功');
} else {
return createMessage.error('新增失败');
}
} else {
const data = await editButton(values);
if (data) {
closeDrawer();
emit('success');
return createMessage.success('编辑成功');
} else {
return createMessage.error('编辑失败');
}
}
closeDrawer();
emit('success');
}
} finally {
setDrawerProps({ confirmLoading: false });
}
}
</script>
</script>

View File

@ -1,36 +1,57 @@
<template>
<div class="m-4 mr-0 overflow-hidden bg-white">
<BasicTree ref="asyncExpandTreeRef" title="职级组列表" toolbar search
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto" loadData :actionList="actionList"
:renderIcon="createIcon" :clickRowToExpand="false" :treeData="treeData" :fieldNames="{ key: 'id', title: 'name' }"
:defaultExpandAll="true" @select="handleSelect" />
<BasicModal @register="register" title="删除" :helpMessage="['提示1', '提示2']" @ok="handleSubmit">
<BasicTree
ref="asyncExpandTreeRef"
title="职级组列表"
toolbar
search
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto"
loadData
:actionList="actionList"
:renderIcon="createIcon"
:clickRowToExpand="false"
:treeData="treeData"
:fieldNames="{ key: 'id', title: 'name' }"
:defaultExpandAll="true"
@select="handleSelect"
/>
<BasicModal
@register="register"
title="删除"
:helpMessage="['提示1', '提示2']"
@ok="handleSubmit"
>
确认要删除菜单吗
</BasicModal>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref, h, nextTick, unref } from 'vue';
import { BasicTree, TreeItem, TreeActionItem } from '@/components/Tree';
import { BasicTree, TreeItem, TreeActionItem, TreeActionType } from '@/components/Tree';
import { getPosGroupList, deleteMenu } from '@/api/demo/system';
import { FormOutlined, DeleteOutlined } from '@ant-design/icons-vue';
import { BasicModal, useModal } from '@/components/Modal';
import { router } from '@/router';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
const [register, { closeModal, openModal }] = useModal();
defineOptions({ name: 'DeptTree' });
const emit = defineEmits(['select', 'edit']);
const treeData = ref < TreeItem[] > ([]);
let selectItemId = ref('')
const asyncExpandTreeRef = ref < Nullable < TreeActionType >> (null);
const treeData = ref<TreeItem[]>([]);
let selectItemId = ref('');
const asyncExpandTreeRef = ref<Nullable<TreeActionType>>(null);
async function handleSubmit() {
var query = [selectItemId.value]
var query = [selectItemId.value];
const data = await deleteMenu(query);
closeModal();
if (data) {
closeModal();
return createMessage.success('删除成功');
} else {
return createMessage.error('删除失败');
}
}
async function fetch() {
@ -44,9 +65,9 @@
function handleSelect(keys) {
emit('select', keys[0]);
}
const btnList = router.currentRoute.value.meta.elements
const actionList: TreeActionItem[] = []
btnList.forEach(element => {
const btnList = router.currentRoute.value.meta.elements;
const actionList: TreeActionItem[] = [];
btnList.forEach((element) => {
if (element.domId == 'btnEdit') {
actionList.push({
render: (node) => {
@ -57,21 +78,21 @@
},
});
},
})
});
} else if (element.domId == 'btnDelete') {
actionList.push({
render: (node) => {
return h(DeleteOutlined, {
class: 'ml-2',
onClick: () => {
selectItemId.value = node.id
selectItemId.value = node.id;
openModal(true, {
isUpdate: false,
});
},
});
},
})
});
}
});
@ -91,6 +112,6 @@
fetch();
});
defineExpose({
fetch
})
</script>
fetch,
});
</script>

View File

@ -15,14 +15,14 @@
<script lang="ts" setup>
import { reactive, nextTick,ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { getPositionList,getPositionsTree} from '@/api/demo/system';
import { BasicTable, useTable } from '@/components/Table';
import { getPositionsTree} from '@/api/demo/system';
import { PageWrapper } from '@/components/Page';
import PositionTree from './PositionTree.vue';
import PermissionBtn from '@/components/PermissionBtn/index.vue'
import {PermissionBtn} from '@/components/PermissionBtn/index'
import { useDrawer } from '@/components/Drawer';
import PositionDrawer from './PositionDrawer.vue';
import {PositionTree} from './page';
import {PositionDrawer} from './page';
import { columns, searchFormSchema } from './position.data';
import { useMessage } from '@/hooks/web/useMessage';
@ -31,7 +31,7 @@
const searchInfo = reactive < Recordable > ({});
const [registerDrawer, { openDrawer }] = useDrawer();
const [registerTable, { reload, expandAll, getSelectRows,clearSelectedRowKeys }] = useTable({
const [registerTable, { reload, expandAll, getSelectRows }] = useTable({
title: '职级列表',
api: getPositionsTree,
columns,
@ -84,12 +84,12 @@
searchInfo.GroupId = GroupId;
reload();
}
async function handleDelete(record: Recordable) {
async function handleDelete() {
let rows = getSelectRows();
if(rows.length == 0){
return createMessage.warn('请选择一个职级进行删除');
}
const query = [rows[0].id]
// const query = [rows[0].id]
createConfirm({
iconType: 'info',
title: '删除',

View File

@ -0,0 +1,4 @@
export { default as PositionDrawer } from './PositionDrawer.vue';
export { default as PositionTree } from './PositionTree.vue';

View File

@ -1,31 +1,27 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit">
<BasicTable @register="registerTable" :searchInfo="searchInfo"/>
<BasicModal v-bind="$attrs" @register="registerModal" title="查看账号">
<BasicTable @register="registerTable" :searchInfo="searchInfo" />
</BasicModal>
</template>
<script lang="ts" setup>
import { ref, computed, unref, reactive, onMounted } from 'vue';
import { ref, reactive, onMounted } from 'vue';
import { BasicModal, useModalInner } from '@/components/Modal';
import { BasicForm, useForm } from '@/components/Form';
import { formSchema } from './role.data';
import { loadByRole } from '@/api/demo/system';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { BasicTable, useTable } from '@/components/Table';
defineOptions({ name: 'DeptModal' });
const emit = defineEmits(['success', 'register']);
const rowId = ref('');
const searchInfo = reactive < Recordable > ({});
const searchInfo = reactive<Recordable>({});
const [registerModal, { setModalProps, closeModal, }] = useModalInner(async (data) => {
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
setModalProps({ confirmLoading: false });
rowId.value = data.record.id;
searchInfo.roleId = rowId.value
searchInfo.roleId = rowId.value;
});
const [registerTable, { reload, getPaginationRef, }] = useTable({
const [registerTable] = useTable({
api: loadByRole,
columns: [
{
@ -49,27 +45,6 @@
return info;
},
});
onMounted(() => {
});
async function handleSubmit() {
try {
const values = await validate();
let query = values
//
if (!unref(isUpdate)) {
const data = await addRole(query);
} else {
const data = await updateRole(query);
}
setModalProps({ confirmLoading: true });
// TODO custom api
closeModal();
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>
onMounted(() => {});
</script>

View File

@ -2,49 +2,76 @@
<div>
<BasicModal v-bind="$attrs" @register="registerModal" title="分配菜单" @ok="handleSubmit">
<template #insertFooter>
<a-button type="primary" @click="upBtn" :disabled="loading" v-if='step == 2'>上一步</a-button>
<a-button type="primary" @click="upBtn" :disabled="loading" v-if="step == 2"
>上一步</a-button
>
</template>
<BasicTree ref="asyncExpandTreeRef" title="菜单树" toolbar treeWrapperClassName="h-[calc(100%-35px)] overflow-auto"
loadData :clickRowToExpand="false" :treeData="treeData" :fieldNames="{ key: 'id', title: 'name' }"
:defaultExpandAll="true" :checkable="true" :checkStrictly="true" @check="handleSelect" v-if='step == 1' />
<BasicTree ref="asyncBtnExpandTreeRef" title="按钮树" toolbar
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto" loadData :clickRowToExpand="false" :treeData="btnData"
:fieldNames="{ key: 'id', title: 'name' ,children:'elements'}" :defaultExpandAll="true" :checkable="true"
:checkStrictly="true" @check="handleBntSelect" v-else />
<BasicTree
ref="asyncExpandTreeRef"
title="菜单树"
toolbar
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto"
loadData
:clickRowToExpand="false"
:treeData="treeData"
:fieldNames="{ key: 'id', title: 'name' }"
:defaultExpandAll="true"
:checkable="true"
:checkStrictly="true"
@check="handleSelect"
v-if="step == 1"
/>
<BasicTree
ref="asyncBtnExpandTreeRef"
title="按钮树"
toolbar
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto"
loadData
:clickRowToExpand="false"
:treeData="btnData"
:fieldNames="{ key: 'id', title: 'name', children: 'elements' }"
:defaultExpandAll="true"
:checkable="true"
:checkStrictly="true"
@check="handleBntSelect"
v-else
/>
</BasicModal>
</div>
</template>
<script lang="ts" setup>
import { ref, computed, unref, onMounted, nextTick } from 'vue';
import { ref, unref, onMounted, nextTick } from 'vue';
import { BasicModal, useModalInner } from '@/components/Modal';
import { accountFormSchema } from './account.data';
import { BasicTree, TreeItem } from '@/components/Tree';
import { BasicTree, TreeItem, TreeActionType } from '@/components/Tree';
import { getMenuList } from '@/api/sys/menu';
import { assignModule, loadForRole } from '@/api/demo/system'
import { useMessage } from '/@/hooks/web/useMessage';
import { assignModule, loadForRole } from '@/api/demo/system';
import { useMessage } from '@/hooks/web/useMessage';
defineOptions({ name: 'ModulesModal' });
const emit = defineEmits(['success', 'register', 'select']);
const treeData = ref < TreeItem[] > ([]);
const btnData = ref < TreeItem[] > ([]);
const step = ref(1)
const asyncExpandTreeRef = ref < Nullable < TreeActionType >> (null);
const asyncBtnExpandTreeRef = ref < Nullable < TreeActionType >> (null);
const { createConfirm, createMessage } = useMessage();
const checkedKeys = ref < number[] > ([]);
const treeData = ref<TreeItem[]>([]);
const btnData = ref<any[]>([]);
const step = ref(1);
interface dataType {
moduleIds?: any;
elementIds?: any;
}
const checkData: dataType = {};
const asyncExpandTreeRef = ref<Nullable<TreeActionType>>(null);
const asyncBtnExpandTreeRef = ref<Nullable<TreeActionType>>(null);
const { createMessage } = useMessage();
function upBtn() {
step.value = 1
getMenusForRol(rowId.value)
step.value = 1;
getMenusForRol(rowId.value);
}
function treeIterator(tree) {
tree.forEach((node) => {
node.name = node.item.name
node.id = node.item.id
node.elements = node.item.elements
node.children && treeIterator(node.children)
})
node.name = node.item.name;
node.id = node.item.id;
node.elements = node.item.elements;
node.children && treeIterator(node.children);
});
}
function btnIterator(moduleId, tree) {
tree.forEach((node) => {
@ -53,17 +80,17 @@
name: node.item.name,
id: node.item.id,
elements: node.item.elements,
disabled: true
})
disabled: true,
});
}
node.children && btnIterator(moduleId, node.children)
})
node.children && btnIterator(moduleId, node.children);
});
}
async function fetch() {
step.value = 1
step.value = 1;
const data = (await getMenuList()) as unknown as TreeItem[];
treeIterator(data)
treeData.value = await data
treeIterator(data);
treeData.value = await data;
//
nextTick(() => {
unref(asyncExpandTreeRef)?.expandAll(true);
@ -72,36 +99,36 @@
}
async function getMenusForRol(id) {
var menusForRol = await loadForRole({
roleId: id
})
roleId: id,
});
// var forRole = await loadForRole()
btnData.value = []
menusForRol.moduleIds.forEach(element => {
btnIterator(element, treeData.value)
btnData.value = [];
menusForRol.moduleIds.forEach((element) => {
btnIterator(element, treeData.value);
});
unref(asyncExpandTreeRef)?.setCheckedKeys(menusForRol.moduleIds);
nextTick(() => {
unref(asyncBtnExpandTreeRef)?.setCheckedKeys(menusForRol.elementIds);
});
checkData.moduleIds = menusForRol.moduleIds
checkData.elementIds = menusForRol.elementIds
}
let moduleIds = ref([])
let elementIds = ref([])
function handleSelect(checkedKeys, e: { checked: bool, checkedNodes, node, event }) {
const list = e.checkedNodes
moduleIds.value = []
list.forEach(element => {
element.disabled = true
element.name = element.item.name
element.children = []
moduleIds.value.push(element.item.id)
let moduleIds = ref([]);
let elementIds = ref([]);
function handleSelect(checkedKeys, e: { checked: boolean; checkedNodes; node; event }) {
const list = e.checkedNodes;
moduleIds.value = [];
list.forEach((element:any) => {
element.disabled = true;
element.name = element.item.name;
element.children = [];
moduleIds.value.push(element.item.id);
});
btnData.value = list
btnData.value = list;
}
function handleBntSelect(checkedKeys, e: { checked: bool, checkedNodes, node, event }) {
const list = e.checkedNodes
elementIds.value = []
list.forEach(element => {
elementIds.value.push(element.id)
function handleBntSelect(checkedKeys, e: { checked: boolean; checkedNodes; node; event }) {
const list = e.checkedNodes;
elementIds.value = [];
list.forEach((element:any) => {
elementIds.value.push(element.id);
});
}
@ -111,27 +138,32 @@
const rowId = ref('');
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
rowId.value = data.record.id;
step.value = 1
getMenusForRol(rowId.value)
step.value = 1;
getMenusForRol(rowId.value);
setModalProps({ confirmLoading: false });
});
async function handleSubmit() {
try {
if (step.value == 1) {
step.value = 2
step.value = 2;
} else {
var query = {
roleId: rowId.value,
moduleIds: moduleIds.value,
elementIds: elementIds.value
elementIds: elementIds.value,
};
const data = await assignModule(query);
if (data) {
setModalProps({ confirmLoading: true });
closeModal();
emit('success');
return createMessage.success('成功');
} else {
return createMessage.error('失败');
}
const data = await assignModule(query)
setModalProps({ confirmLoading: true });
closeModal();
emit('success');
}
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>
</script>

View File

@ -9,7 +9,9 @@
import { BasicForm, useForm } from '@/components/Form';
import { formSchema } from './role.data';
import { addRole,updateRole } from '@/api/demo/system';
import { addRole, updateRole } from '@/api/demo/system';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
defineOptions({ name: 'DeptModal' });
@ -17,7 +19,7 @@
const isUpdate = ref(true);
const [registerForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
labelWidth: 100,
baseColProps: { span: 24 },
schemas: formSchema,
@ -41,21 +43,33 @@
async function handleSubmit() {
try {
const values = await validate();
let query = values
let query = values;
//
if(!unref(isUpdate)){
if (!unref(isUpdate)) {
const data = await addRole(query);
}else{
if (data) {
setModalProps({ confirmLoading: true });
// TODO custom api
closeModal();
emit('success');
return createMessage.success('新增成功');
} else {
return createMessage.error('新增失败');
}
} else {
const data = await updateRole(query);
if (data) {
setModalProps({ confirmLoading: true });
// TODO custom api
closeModal();
emit('success');
return createMessage.success('编辑成功');
} else {
return createMessage.error('编辑失败');
}
}
setModalProps({ confirmLoading: true });
// TODO custom api
closeModal();
emit('success');
} finally {
setModalProps({ confirmLoading: false });
}
}
</script>
</script>

View File

@ -29,12 +29,12 @@
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { getRoleListByPage, deleteRole } from '@/api/demo/system';
import { useMessage } from '/@/hooks/web/useMessage';
import { useMessage } from '@/hooks/web/useMessage';
import { useModal } from '@/components/Modal';
import RoleModal from './RoleModal.vue';
import ModulesModal from './ModulesModal.vue';
import AccountModal from './AccountModal.vue';
import PermissionBtn from '@/components/PermissionBtn/index.vue'
import {RoleModal} from './page';
import {ModulesModal} from './page';
import {AccountModal} from './page';
import {PermissionBtn} from '@/components/PermissionBtn/index'
import { columns, searchFormSchema } from './role.data';
@ -95,17 +95,6 @@
});
}
async function handleItem() {
let rows = getSelectRows();
if (!rows.length) {
return createMessage.warn('请勾选对应项');
}
let idList = [] as any;
rows.forEach((item) => {
idList.push(item.id);
});
}
function handleEdit() {
let rows = getSelectRows();
if (rows.length == 0) {
@ -130,7 +119,12 @@
content: '确定要删除当前角色吗',
onOk: async () => {
const data = await deleteRole(query);
handleSuccess()
if(data){
handleSuccess()
return createMessage.success('删除成功');
}else{
return createMessage.error('删除失败');
}
},
});
}

View File

@ -0,0 +1,6 @@
export { default as AccountModal } from './AccountModal.vue';
export { default as ModulesModal } from './ModulesModal.vue';
export { default as RoleDrawer } from './RoleDrawer.vue';
export { default as RoleModal } from './RoleModal.vue';

View File

@ -1,11 +1,11 @@
<template>
<PageWrapper :class="prefixCls">
<div :class="`${prefixCls}__content`" v-for="item in cardList">
<div :class="`${prefixCls}__content`" v-for="(item,index) in cardList" :key="index">
<div :class="`${prefixCls}__list-title`">{{item.category}}{{item.data.length}}</div>
<List>
<Row :gutter="16">
<template v-for="itemchild in item.data" :key="item.id">
<Col :span="6">
<template v-for="itemchild in item.data" :key="itemchild.id">
<Col :span="6" >
<List.Item>
<Card :hoverable="true" :class="`${prefixCls}__card`" @click="launch(itemchild.code)">
<div :class="`${prefixCls}__card-title`">
@ -23,10 +23,10 @@
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import Icon from '@/components/Icon/Icon.vue';
import {Icon} from '@/components/Icon/index';
import { PageWrapper } from '@/components/Page';
import { Card, Row, Col, List } from 'ant-design-vue';
import { getInfoList } from '@/api/sys/WFSchemeInfo.ts'
import { getInfoList } from '@/api/sys/WFSchemeInfo'
import { useGo } from '@/hooks/web/usePage';
const go = useGo();
const prefixCls = 'list-card';
@ -43,7 +43,7 @@
})
let list = [];
Object.keys(newArr).forEach(v => {
let obj = {};
let obj:any = {};
obj.category = v;
obj.data = newArr[v]
list.push(obj);

View File

@ -1,64 +1,100 @@
<template>
<PageWrapper :class="prefixCls">
<div class="btn-box">
<a-button type="primary" :icon="h(SendOutlined)" @click="handleCreateFlow" class="ml-2">发起流程 </a-button>
<a-button type="primary" :icon="h(SaveOutlined)" @click="handleSaveDraft" class="ml-2">保存草稿 </a-button>
<a-button type="primary" :icon="h(CloseCircleOutlined)" @click="closePreview" class="ml-2" danger>关闭 </a-button>
<a-button type="primary" :icon="h(SendOutlined)" @click="handleCreateFlow" class="ml-2"
>发起流程
</a-button>
<a-button type="primary" :icon="h(SaveOutlined)" @click="handleSaveDraft" class="ml-2"
>保存草稿
</a-button>
<a-button
type="primary"
:icon="h(CloseCircleOutlined)"
@click="closePreview"
class="ml-2"
danger
>关闭
</a-button>
</div>
<a-tabs v-model:activeKey="activeName">
<a-tab-pane key="form" tab="表单信息">
</a-tab-pane>
<a-tab-pane key="form" tab="表单信息"> </a-tab-pane>
<a-tab-pane key="flow" tab="流程信息" force-render>
<div class="process-design" :style="'display: flex; height:' + designerData.height">
<process-viewer :key="`designer-${code}`" :xml="flowContent" />
<div class="form-box"
v-if="designerData.isCustmerTitle || (designerData.delegateUsers && designerData.delegateUsers.length >0)">
<a-form ref="formRef" :model="formData" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-form-item ref="title" label="流程标题" name="title" v-if="designerData.isCustmerTitle">
<div
class="form-box"
v-if="
designerData.isCustmerTitle ||
(designerData.delegateUsers && designerData.delegateUsers.length > 0)
"
>
<a-form
ref="formRef"
:model="formData"
:rules="rules"
:label-col="labelCol"
:wrapper-col="wrapperCol"
>
<a-form-item
ref="title"
label="流程标题"
name="title"
v-if="designerData.isCustmerTitle"
>
<a-input v-model:value="formData.title" />
</a-form-item>
<a-form-item label="流程发起人" name="userId"
v-if="designerData.delegateUsers && designerData.delegateUsers.length >0">
<a-select v-model:value="formData.userId" placeholder="请选择" :options="delegateUsers"></a-select>
<a-form-item
label="流程发起人"
name="userId"
v-if="designerData.delegateUsers && designerData.delegateUsers.length > 0"
>
<a-select
v-model:value="formData.userId"
placeholder="请选择"
:options="delegateUsers"
></a-select>
</a-form-item>
</a-form>
</div>
</div>
</a-tab-pane>
</a-tabs>
</PageWrapper>
</template>
<script lang="ts" setup>
import { h, ref, provide, reactive, onMounted, defineProps, computed, defineEmits, onBeforeMount } from 'vue';
import ProcessViewer from '@/components/ProcessViewer/index.vue';
import { h, ref, reactive, onBeforeMount } from 'vue';
import { ProcessViewer } from '@/components/ProcessViewer/index';
import { PageWrapper } from '@/components/Page';
import { SendOutlined, SaveOutlined, CloseCircleOutlined, ZoomInOutlined, RotateLeftOutlined, RotateRightOutlined, ClearOutlined } from '@ant-design/icons-vue';
import { getDetail } from '@/api/sys/WFSchemeInfo'
import { create, saveDraft } from '@/api/sys/WFProcess'
import { getLoadMyUserList } from '@/api/sys/WFDelegate'
import { useRoute } from 'vue-router'
import {
SendOutlined,
SaveOutlined,
CloseCircleOutlined,
ZoomInOutlined,
RotateLeftOutlined,
RotateRightOutlined,
ClearOutlined,
} from '@ant-design/icons-vue';
import { getDetail } from '@/api/sys/WFSchemeInfo';
import { create, saveDraft } from '@/api/sys/WFProcess';
import { getLoadMyUserList } from '@/api/sys/WFDelegate';
import { useRoute } from 'vue-router';
import { useMultipleTabStore } from '@/store/modules/multipleTab';
import { useRouter } from 'vue-router';
import { useUserStore } from '@/store/modules/user';
import { buildGUID } from '@/utils/uuid';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm, createMessage } = useMessage();
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
const userStore = useUserStore();
const userInfo = userStore.getUserInfo
const prefixCls = 'preview-box'
const userInfo: any = userStore.getUserInfo;
const prefixCls = 'preview-box';
const tabStore = useMultipleTabStore();
const router = useRouter();
const content = ref('')
const flowContent = ref('')
const route = useRoute()
const code = route.query.code
const designerOpen = ref(false)
const flowContent = ref('');
const route = useRoute();
const code: any = route.query.code;
const formRef = ref();
const labelCol = { span: 7 };
const wrapperCol = { span: 13 };
@ -69,66 +105,58 @@
controlForm: {
prefix: 'flowable',
},
height: document.documentElement.clientHeight - 230.5 + "px;",
height: document.documentElement.clientHeight - 230.5 + 'px;',
midVisible: false,
isCustmerTitle: false,
nodeUsers: [],
selectUsersVisible: false,
isDraft: false,
delegateUsers: []
})
const activeName = ref('flow')
const modelDesigner = ref < any > ()
delegateUsers: [],
});
const activeName = ref('flow');
const formData = reactive({
userId: '',
title: ''
})
title: '',
});
const rules = reactive({
title: [
{ required: true, message: '请选择流程标题', trigger: 'blur' }
],
userId: [
{ required: true, message: '请选择流程发起人', trigger: 'blur' }
],
})
title: [{ required: true, message: '请选择流程标题', trigger: 'blur' }],
userId: [{ required: true, message: '请选择流程发起人', trigger: 'blur' }],
});
async function getDetailInfo() {
let data = await getDetail({ code: code })
flowContent.value = data.scheme.flowContent
formData.userId = userInfo.id
let content = JSON.parse(data.scheme.content)
let wfData = content.wfData
const currentNode = wfData.find(t => t.type == "bpmn:StartEvent")
designerData.isCustmerTitle = currentNode.isCustmerTitle
let data = await getDetail({ code: code });
flowContent.value = data.scheme.flowContent;
formData.userId = userInfo.id;
let content = JSON.parse(data.scheme.content);
let wfData = content.wfData;
const currentNode = wfData.find((t) => t.type == 'bpmn:StartEvent');
designerData.isCustmerTitle = currentNode.isCustmerTitle;
}
async function getDelegateUsers() {
const data = await getLoadMyUserList({
code: code
})
designerData.delegateUsers = data
}
async function handleSaveDraft() {
code: code,
});
designerData.delegateUsers = data;
}
async function handleSaveDraft() {}
async function handleCreateFlow() {
var querys = {
schemeCode: designerData.isDraft ? '' : code,
userId: formData.userId,
title: formData.title,
processId: buildGUID()
}
processId: buildGUID(),
};
if (!designerData.isDraft) {
await saveDraft(querys)
querys.schemeCode = ''
designerData.isDraft = true
await saveDraft(querys);
querys.schemeCode = '';
designerData.isDraft = true;
}
const data = await create(querys)
const data = await create(querys);
if (data) {
closePreview()
return createMessage.info('创建成功');
closePreview();
return createMessage.success('新增成功');
} else {
return createMessage.error('创建失败');
return createMessage.error('新增失败');
}
}
@ -141,9 +169,9 @@
}
}
onBeforeMount(() => {
getDetailInfo()
getDelegateUsers()
})
getDetailInfo();
getDelegateUsers();
});
</script>
<style lang="less" scoped>
.preview-box {
@ -153,11 +181,10 @@
padding: 10px;
justify-content: flex-end;
display: flex;
}
}
.form-box {
width: 480px;
}
</style>
</style>

View File

@ -1,56 +1,60 @@
<template>
<div>
<BasicDrawer v-bind="$attrs" @register="registerDrawer" showFooter title="历史记录" width="60%" @ok="handleSubmit">
<BasicDrawer v-bind="$attrs" @register="registerDrawer" showFooter title="历史记录" width="60%">
<BasicTable @register="registerTable" :searchInfo="searchInfo">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction :actions="[
<TableAction
:actions="[
{
label:'预览',
label: '预览',
onClick: handleHistory.bind(null, record),
}
]" />
},
]"
/>
</template>
</template>
</BasicTable>
</BasicDrawer>
<a-modal width="70%" height="80%" v-model:open="postOpen" title="流程模板预览" @ok="postHandleOk">
<process-designer :key="designerOpen" style="border:1px solid rgba(0, 0, 0, 0.1);" ref="modelDesigner"
v-loading="designerData.loading" :pageFlow="flowContent" :pageView="content" :pageType="'detail'"
@save="onSaveDesigner" />
<a-modal wrap-class-name="full-modal" width="70%" v-model:open="postOpen" title="流程模板预览">
<process-designer
style="border: 1px solid rgba(0, 0, 0, 0.1);height:100%;"
ref="modelDesigner"
v-loading="designerData.loading"
:pageFlow="flowContent"
:pageView="content"
:pageType="'detail'"
/>
</a-modal>
</div>
</template>
<script lang="ts" setup>
import { ref, computed, unref, reactive, onMounted, h } from 'vue';
import { ref, reactive, onMounted, h } from 'vue';
import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
import { getLoadHistoryPage, updateScheme } from '@/api/sys/WFSchemeInfo';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { Tag, Switch } from 'ant-design-vue';
import { useMessage } from '@/hooks/web/useMessage';
import ProcessDesigner from '@/components/ProcessDesigner/index.vue';
import ProcessDesigner from '@/components/ProcessDesigner/index.vue';
const { createConfirm, createMessage } = useMessage();
defineOptions({ name: 'HistoryDrawer' });
const emit = defineEmits(['success', 'register']);
let postOpen = ref(false)
const rowId = ref('');
const searchInfo = reactive < Recordable > ({});
const schemeId = ref('')
const content = ref('')
const flowContent = ref('')
let postOpen = ref(false);
const searchInfo = reactive<Recordable>({});
const schemeId = ref('');
const content = ref('');
const flowContent = ref('');
const designerData = reactive({
loading: false,
})
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
setDrawerProps({ confirmLoading: false });
searchInfo.id = data.record.id
schemeId.value = data.record.schemeId
reload()
});
const [registerTable, { reload, getPaginationRef, }] = useTable({
const [registerDrawer, { setDrawerProps }] = useDrawerInner(async (data) => {
setDrawerProps({ confirmLoading: false });
searchInfo.id = data.record.id;
schemeId.value = data.record.schemeId;
reload();
});
const [registerTable, { reload }] = useTable({
api: getLoadHistoryPage,
columns: [
{
@ -74,7 +78,7 @@
const text = '草稿';
return h(Tag, { color: color }, () => text);
}
}
},
},
{
title: '当前版本',
@ -93,8 +97,8 @@
updateScheme({ schemeId: record.id, id: searchInfo.id })
.then((data) => {
createMessage.success('版本切换成功');
schemeId.value = record.id
reload()
schemeId.value = record.id;
reload();
})
.catch((err) => {
createMessage.success('版本切换失败');
@ -125,30 +129,25 @@
},
});
function handleHistory(record) {
postOpen.value = true
content.value = record.content
flowContent.value=record.flowContent
postOpen.value = true;
content.value = record.content;
flowContent.value = record.flowContent;
}
onMounted(() => {
});
async function handleSubmit() {
try {
const values = await validate();
let query = values
//
if (!unref(isUpdate)) {
const data = await addRole(query);
} else {
const data = await updateRole(query);
}
onMounted(() => {});
</script>
<style lang="less">
.full-modal {
.ant-modal {
max-width: 100%;
}
setModalProps({ confirmLoading: true });
// TODO custom api
closeModal();
emit('success');
} finally {
setModalProps({ confirmLoading: false });
.ant-modal-content {
height: calc(80vh);
}
.ant-modal-body {
height: 80%;
}
}
}
</script>
</style>

View File

@ -10,15 +10,15 @@
import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
import { postAdd, update } from '@/api/sys/sysDataItemDetail';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm, createMessage } = useMessage();
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
defineOptions({ name: 'SchemeDrawer' });
const emit = defineEmits(['success', 'register']);
const isUpdate = ref(true);
const detail = ref({})
const [registerForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
labelWidth: 90,
baseColProps: { span: 24 },
schemas: formSchema,
@ -39,13 +39,19 @@
});
const getTitle = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
interface querysType{
description?:string,
enabledMark?:number,
itemName?:string,
itemValue?:string,
sortCode?:number,
}
async function handleSubmit() {
try {
const values = await validate();
setDrawerProps({ confirmLoading: true });
if (isUpdate.value) {
var querys = detail.value
const querys:querysType = detail.value
querys.description = values.description
querys.enabledMark = values.enabledMark
querys.itemName = values.itemName
@ -55,19 +61,18 @@
if (data) {
closeDrawer();
emit('success');
return createMessage.info('编辑成功');
return createMessage.success('编辑成功');
} else {
return createMessage.error('编辑失败');
}
} else {
const data = await postAdd('FlowSort', values);
if (data) {
closeDrawer();
emit('success');
return createMessage.info('创建成功');
return createMessage.success('新增成功');
} else {
return createMessage.error('创建失败');
return createMessage.error('新增失败');
}
}

View File

@ -1,41 +1,62 @@
<template>
<div class="m-4 mr-0 overflow-hidden bg-white">
<BasicTree ref="asyncExpandTreeRef" title="流程分类" toolbar search
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto" loadData :actionList="actionList"
:renderIcon="createIcon" :clickRowToExpand="false" :treeData="treeData"
:fieldNames="{ key: 'itemDetailId', title: 'itemName' }" :defaultExpandAll="true" @select="handleSelect" />
<BasicModal @register="register" title="删除" :helpMessage="['提示1', '提示2']" @ok="handleSubmit">
<BasicTree
ref="asyncExpandTreeRef"
title="流程分类"
toolbar
search
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto"
loadData
:actionList="actionList"
:renderIcon="createIcon"
:clickRowToExpand="false"
:treeData="treeData"
:fieldNames="{ key: 'itemDetailId', title: 'itemName' }"
:defaultExpandAll="true"
@select="handleSelect"
/>
<BasicModal
@register="register"
title="删除"
:helpMessage="['提示1', '提示2']"
@ok="handleSubmit"
>
确认要删除流程分类吗
</BasicModal>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref, h, nextTick, unref, createVNode } from 'vue';
import { BasicTree, TreeItem, TreeActionItem } from '@/components/Tree';
import { BasicTree, TreeItem, TreeActionItem, TreeActionType } from '@/components/Tree';
import { getLoad, del } from '@/api/sys/sysDataItemDetail';
import { PlusOutlined, FormOutlined, DeleteOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { Card, Row, Col, Spin, Modal } from 'ant-design-vue';
import {
PlusOutlined,
FormOutlined,
DeleteOutlined,
ExclamationCircleOutlined,
} from '@ant-design/icons-vue';
import { Modal } from 'ant-design-vue';
import { BasicModal, useModal } from '@/components/Modal';
import { router } from '@/router';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm, createMessage } = useMessage();
const [register, { closeModal, openModal }] = useModal();
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
const [register] = useModal();
defineOptions({ name: 'DeptTree' });
const emit = defineEmits(['select', 'edit', 'success']);
const treeData = ref < TreeItem[] > ([]);
let selectItemId = ref('')
const asyncExpandTreeRef = ref < Nullable < TreeActionType >> (null);
const treeData = ref<TreeItem[]>([]);
let selectItemId = ref('');
const asyncExpandTreeRef = ref<Nullable<TreeActionType>>(null);
const treeLoading = ref(false);
async function handleSubmit() {
var query = {
id: selectItemId.value
}
id: selectItemId.value,
};
const data = await del(query);
if (data) {
emit('success')
return createMessage.info('删除成功');
emit('success');
return createMessage.success('删除成功');
} else {
return createMessage.error('删除失败');
}
@ -52,18 +73,18 @@
}
function handleSelect(keys) {
var itemDetailId = keys[0]
var itemName
treeData.value.forEach(element => {
var itemDetailId = keys[0];
var itemName;
treeData.value.forEach((element) => {
if (itemDetailId == element.itemDetailId) {
itemName = element.itemName
itemName = element.itemName;
}
});
emit('select', itemName);
}
const btnList = router.currentRoute.value.meta.elements
const actionList: TreeActionItem[] = []
btnList.forEach(element => {
const btnList: any = router.currentRoute.value.meta.elements;
const actionList: TreeActionItem[] = [];
btnList.forEach((element) => {
if (element.domId == 'btnAdd') {
actionList.push({
render: (node) => {
@ -74,14 +95,14 @@
},
});
},
})
});
} else if (element.domId == 'btnEdit') {
actionList.push({
render: (node) => {
let data = {}
treeData.value.forEach(element => {
let data = {};
treeData.value.forEach((element) => {
if (element.itemDetailId == node.itemDetailId) {
data = element
data = element;
}
});
return h(FormOutlined, {
@ -91,14 +112,14 @@
},
});
},
})
});
} else if (element.domId == 'btnDelete') {
actionList.push({
render: (node) => {
return h(DeleteOutlined, {
class: 'ml-2',
onClick: () => {
selectItemId.value = node.itemDetailId
selectItemId.value = node.itemDetailId;
Modal.confirm({
title: '删除?',
icon: createVNode(ExclamationCircleOutlined),
@ -108,7 +129,7 @@
cancelText: '取消',
onOk() {
console.log('OK');
handleSubmit()
handleSubmit();
},
onCancel() {
console.log('Cancel');
@ -117,7 +138,7 @@
},
});
},
})
});
}
});
@ -137,6 +158,6 @@
fetch();
});
defineExpose({
fetch
})
</script>
fetch,
});
</script>

View File

@ -1,45 +1,54 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<SchemeTree ref="childRef" class="w-1/4 xl:w-1/5" @select="handleSelect" @edit="classifyEdit" @add='handleCreate'
@success="handleSuccess" />
<BasicTable class="w-3/4 xl:w-4/5" @register="registerTable" @fetch-success="onFetchSuccess"
:searchInfo="searchInfo">
<SchemeTree
ref="childRef"
class="w-1/4 xl:w-1/5"
@select="handleSelect"
@edit="classifyEdit"
@add="handleCreate"
@success="handleSuccess"
/>
<BasicTable
class="w-3/4 xl:w-4/5"
@register="registerTable"
@fetch-success="onFetchSuccess"
:searchInfo="searchInfo"
>
<template #toolbar>
<!-- <a-button type="primary" @click="handleCreate"> </a-button> -->
<PermissionBtn @btnEvent="onBtnClicked"></PermissionBtn>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction :actions="[
<TableAction
:actions="[
{
label:'历史记录',
label: '历史记录',
onClick: handleHistory.bind(null, record),
}
]" />
},
]"
/>
</template>
</template>
</BasicTable>
<SchemeDrawer @register="registerDrawer" @success="handleSuccess" />
<HistoryDrawer @register="registerHistoryDrawer" @success="handleSuccess" />
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive, nextTick, ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { getButtonList, getMenuDetail, deleteButton } from '@/api/demo/system';
import { getLoadPage, del } from '@/api/sys/WFSchemeInfo';
import { PageWrapper } from '@/components/Page';
import SchemeTree from './SchemeTree.vue';
import { useDrawer } from '@/components/Drawer';
import SchemeDrawer from './SchemeDrawer.vue';
import HistoryDrawer from './HistoryDrawer.vue'
import { PermissionBtn } from '@/components/PermissionBtn/index';
import { SchemeTree } from './page';
import { SchemeDrawer } from './page';
import { HistoryDrawer } from './page';
import { columns, searchFormSchema } from './scheme.data';
import PermissionBtn from '@/components/PermissionBtn/index.vue'
import { useMessage } from '@/hooks/web/useMessage';
const { createConfirm, createMessage } = useMessage();
import { flowStore } from '@/store/modules/flow';
@ -48,7 +57,7 @@
const go = useGo();
defineOptions({ name: 'SchemeManagement' });
const searchInfo = reactive < Recordable > ({});
const searchInfo = reactive<Recordable>({});
const [registerHistoryDrawer, { openDrawer: openHistoryDrawer }] = useDrawer();
const [registerDrawer, { openDrawer }] = useDrawer();
@ -67,7 +76,8 @@
showTableSetting: true,
bordered: true,
showIndexColumn: false,
rowSelection: {//
rowSelection: {
//
// type: 'checkbox',
type: 'radio',
},
@ -81,27 +91,24 @@
// slots: { customRender: 'action' },
},
});
const childRef = ref < any > ()
const childRef = ref<any>();
function handleCreate() {
openDrawer(true, {
isUpdate: false,
});
}
function handleView(record: Recordable) {
go('/dashboard/scheme_preview/' + record.id);
}
//
function handleHistory(record) {
openHistoryDrawer(true, {
record
})
record,
});
}
function handleEdit() {
let rows = getSelectRows();
if (rows.length == 0) {
return createMessage.warn('请选择一个模板进行编辑');
}
const record = rows[0]
const record = rows[0];
go('/dashboard/scheme_preview/add?code=' + record.code);
}
async function classifyEdit(record) {
@ -112,17 +119,17 @@
}
function handleSelect(category = '') {
searchInfo.category = category;
clearSelectedRowKeys()
clearSelectedRowKeys();
reload();
}
async function handleDelete(record: Recordable) {
async function handleDelete() {
let rows = getSelectRows();
if (rows.length == 0) {
return createMessage.warn('请选择一个模板进行删除');
}
const query = {
id: rows[0].id
}
id: rows[0].id,
};
createConfirm({
iconType: 'info',
title: '删除',
@ -131,9 +138,9 @@
const data = await del(query);
reload();
if (data) {
return createMessage.warn('删除成功');
return createMessage.success('删除成功');
} else {
return createMessage.warn('删除失败');
return createMessage.error('删除失败');
}
},
});
@ -141,7 +148,7 @@
function handleSuccess() {
childRef.value.fetch();
clearSelectedRowKeys()
clearSelectedRowKeys();
reload();
}
@ -152,17 +159,17 @@
function onBtnClicked(domId) {
switch (domId) {
case 'btnAdd':
flowWfDataStore.setWfDataAll([])
flowWfDataStore.setWfDataAll([]);
go('/dashboard/scheme_preview/add');
break;
case 'btnEdit':
handleEdit()
handleEdit();
break;
case 'btnDelete':
handleDelete()
handleDelete();
break;
default:
break;
}
}
</script>
</script>

View File

@ -0,0 +1,5 @@
export { default as HistoryDrawer } from './HistoryDrawer.vue';
export { default as SchemeDrawer } from './SchemeDrawer.vue';
export { default as SchemeTree } from './SchemeTree.vue';

View File

@ -1,50 +1,85 @@
<template>
<div class="preview-box">
<div class="btn-box">
<a-button type="primary" :icon="h(SaveOutlined)" @click="onSave(2)" class="ml-2">暂存 </a-button>
<a-button type="primary" :icon="h(SaveOutlined)" @click="onSave(1)" class="ml-2">保存 </a-button>
<a-button type="primary" :icon="h(CloseCircleOutlined)" @click="closePreview" class="ml-2" danger>关闭 </a-button>
<a-button type="primary" :icon="h(SaveOutlined)" @click="onSave(2)" class="ml-2"
>暂存
</a-button>
<a-button type="primary" :icon="h(SaveOutlined)" @click="onSave(1)" class="ml-2"
>保存
</a-button>
<a-button
type="primary"
:icon="h(CloseCircleOutlined)"
@click="closePreview"
class="ml-2"
danger
>关闭
</a-button>
</div>
<process-designer :key="designerOpen" style="border:1px solid rgba(0, 0, 0, 0.1);" ref="modelDesigner"
v-loading="designerData.loading" :schemeCode="schemeCode" @save="onSaveDesigner" />
<process-designer
:key="designerOpen"
style="border: 1px solid rgba(0, 0, 0, 0.1);"
ref="modelDesigner"
v-loading="designerData.loading"
:schemeCode="schemeCode"
@save="onSaveDesigner"
/>
</div>
</template>
<script lang="ts" setup>
import { h, ref, provide, reactive, onMounted, defineProps, computed, defineEmits } from 'vue';
import { h, ref, reactive } from 'vue';
import ProcessDesigner from '@/components/ProcessDesigner/index.vue';
import { SaveOutlined, CloseCircleOutlined, ZoomInOutlined, RotateLeftOutlined, RotateRightOutlined, ClearOutlined } from '@ant-design/icons-vue';
import { postAdd, update } from '@/api/sys/WFSchemeInfo'
import { useRoute } from 'vue-router'
import {
SaveOutlined,
CloseCircleOutlined,
ZoomInOutlined,
RotateLeftOutlined,
RotateRightOutlined,
ClearOutlined,
} from '@ant-design/icons-vue';
import { postAdd, update } from '@/api/sys/WFSchemeInfo';
import { useRoute } from 'vue-router';
import { useMultipleTabStore } from '@/store/modules/multipleTab';
import { useRouter } from 'vue-router';
import { flowStore } from '@/store/modules/flow';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
const flowWfDataStore = flowStore();
const tabStore = useMultipleTabStore();
const router = useRouter();
const route = useRoute()
const schemeCode = route.query.code
const designerOpen = ref(false)
const route = useRoute();
const schemeCode = route.query.code;
const designerOpen = ref(false);
const designerData = reactive({
loading: false,
})
const modelDesigner = ref < any > ()
});
const modelDesigner = ref<any>();
async function onSave(type) {
console.log(flowWfDataStore.getWfData)
let validateData = await modelDesigner.value.validateFlow()
console.log(flowWfDataStore.getWfData);
let validateData = await modelDesigner.value.validateFlow();
if (validateData) {
let formData = await modelDesigner.value.getFlow()
let formData = await modelDesigner.value.getFlow();
// 1 2稿
formData.scheme.type = Number(type)
formData.scheme.type = Number(type);
if (!schemeCode) {
let data = await postAdd(formData)
let data = await postAdd(formData);
if (data) {
closePreview();
return createMessage.success('新增成功');
} else {
return createMessage.error('新增失败');
}
} else {
let data = await update(formData)
let data = await update(formData);
if (data) {
closePreview();
return createMessage.success('编辑成功');
} else {
return createMessage.error('编辑失败');
}
}
closePreview()
}
}
function closePreview() {
@ -62,7 +97,6 @@
padding: 10px;
justify-content: flex-end;
display: flex;
}
}
</style>
</style>

View File

@ -1,122 +1,144 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable @register="registerTable" @fetch-success="onFetchSuccess" :searchInfo="searchInfo">
<template #toolbar>
<!-- <a-button type="primary" @click="handleCreate"> </a-button> -->
<PermissionBtn @btnEvent="onBtnClicked"></PermissionBtn>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction :actions="[
{
label:'详情',
onClick: handleDetail.bind(null, record),
},
{
label:'撤销',
onClick: handleRevocation.bind(null, record),
}
]" />
</template>
</template>
</BasicTable>
</PageWrapper>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable @register="registerTable" :searchInfo="searchInfo">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
{
label: '撤销',
color: 'error',
popConfirm: {
title: '是否确认撤销',
confirm: () => {
handleRevocation(record);
},
},
},
]"
/>
</template>
</template>
</BasicTable>
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyCompletedPage } from '@/api/sys/WFTask'
import { Tag, Switch } from 'ant-design-vue';
import { useGo } from '@/hooks/web/usePage';
const go = useGo();
const searchInfo = reactive < Recordable > ({});
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
api: getLoadMyCompletedPage,
columns: [
{
title: '任务',
dataIndex: 'unitName',
},
{
title: '标题',
dataIndex: 'processTitle',
},
{
title: '审核',
dataIndex: 'operationName',
},
{
title: '状态',
dataIndex: 'isFinished',
width: 80,
customRender: ({ record }) => {
if (record.isFinished == '1') {
const color = 'ref';
const text = '结束';
return h(Tag, { color: color }, () => text);
} else {
const color = 'green';
const text = '审批中';
return h(Tag, { color: color }, () => text);
}
},
},
{
title: '提交人',
dataIndex: 'processUserName',
},
{
title: '创建时间',
dataIndex: 'createDate',
},
],
rowKey: 'id',
formConfig: {
labelWidth: 120,
schemas: [
{
field: '[StartDate, EndDate]',
label: '日期范围',
component: 'RangePicker',
componentProps: {
format: 'YYYY-MM-DD',
placeholder: ['开始日期', '结束日期'],
},
colProps: { span: 8 },
},
{
field: 'keyWord',
label: '关键字',
component: 'Input',
colProps: { span: 8 },
},
],
import { reactive, h } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyCompletedPage } from '@/api/sys/WFTask';
import { revokeAudit } from '@/api/sys/WFProcess';
import { Tag } from 'ant-design-vue';
import { useGo } from '@/hooks/web/usePage';
const go = useGo();
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
import { getDetail } from '@/api/sys/WFSchemeInfo'
import { flowStore } from '@/store/modules/flow';
const flowWfDataStore = flowStore();
const searchInfo = reactive<Recordable>({});
const [registerTable, { reload }] = useTable({
api: getLoadMyCompletedPage,
columns: [
{
title: '任务',
dataIndex: 'unitName',
},
{
title: '标题',
dataIndex: 'processTitle',
},
{
title: '审核',
dataIndex: 'operationName',
},
{
title: '状态',
dataIndex: 'isFinished',
width: 80,
customRender: ({ record }) => {
if (record.isFinished == 1) {
const color = 'red';
const text = '结束';
return h(Tag, { color: color }, () => text);
} else {
const color = 'green';
const text = '审批中';
return h(Tag, { color: color }, () => text);
}
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
handleSearchInfoFn(info) {
return info;
},
{
title: '提交人',
dataIndex: 'processUserName',
},
{
title: '创建时间',
dataIndex: 'createDate',
},
],
rowKey: 'id',
formConfig: {
labelWidth: 120,
schemas: [
{
field: '[StartDate, EndDate]',
label: '日期范围',
component: 'RangePicker',
componentProps: {
format: 'YYYY-MM-DD',
placeholder: ['开始日期', '结束日期'],
},
colProps: { span: 8 },
},
actionColumn: {
width: 100,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
{
field: 'keyWord',
label: '关键字',
component: 'Input',
colProps: { span: 8 },
},
],
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
handleSearchInfoFn(info) {
return info;
},
actionColumn: {
width: 100,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
},
});
async function handleDetail(record) {
let data = await getDetail({ code: record.processCode });
let scheme = JSON.parse(data.scheme.content);
let wfData = scheme.wfData;
flowWfDataStore.setWfDataAll(wfData);
go(
'/dashboard/task_look_preview/detail?processId=' + record.processId + '&taskId=' + record.id,
);
// go('/dashboard/task_look_preview/detail?processId=' + record.processId);
}
async function handleRevocation(record) {
console.log(record);
const data = await revokeAudit({
taskId: record.id,
id: record.processId,
});
function handleDetail(record){
go('/dashboard/task_look_preview/detail?processId=' + record.id);
if (data) {
reload();
return createMessage.success('撤销成功');
} else {
return createMessage.error('撤销失败');
}
function handleRevocation(record){
console.log(record)
}
</script>
}
</script>

View File

@ -1,10 +1,6 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable @register="registerTable" @fetch-success="onFetchSuccess" :searchInfo="searchInfo">
<template #toolbar>
<!-- <a-button type="primary" @click="handleCreate"> </a-button> -->
<PermissionBtn @btnEvent="onBtnClicked"></PermissionBtn>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction :actions="[
@ -24,15 +20,15 @@
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import { reactive ,h} from 'vue'
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyDelegatePage } from '@/api/sys/WFTask'
import { Tag, Switch } from 'ant-design-vue';
import { Tag } from 'ant-design-vue';
import { useGo } from '@/hooks/web/usePage';
const go = useGo();
const searchInfo = reactive < Recordable > ({});
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
const [registerTable, { reload}] = useTable({
api: getLoadMyDelegatePage,
columns: [
{
@ -49,7 +45,7 @@
width: 80,
customRender: ({ record }) => {
if (record.isUrge == '1') {
const color = 'ref';
const color = 'red';
const text = '催办';
return h(Tag, { color: color }, () => text);
} else {
@ -111,6 +107,7 @@
}
function handleRevocation(record){
console.log(record)
// reload()
}

View File

@ -34,14 +34,13 @@
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyDraftPage, deleteDraft } from '@/api/sys/WFProcess'
import { Tag, Switch } from 'ant-design-vue';
const searchInfo = reactive < Recordable > ({});
import { useGo } from '@/hooks/web/usePage';
const go = useGo();
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm, createMessage } = useMessage();
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
const [registerTable, { reload }] = useTable({
api: getLoadMyDraftPage,
columns: [
{
@ -104,7 +103,7 @@
const data = await deleteDraft(query)
if (data) {
reload()
return createMessage.info('删除成功');
return createMessage.success('删除成功');
}else{
return createMessage.error('删除失败');
}

View File

@ -1,165 +1,161 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable @register="registerTable" @fetch-success="onFetchSuccess" :searchInfo="searchInfo">
<template #toolbar>
<!-- <a-button type="primary" @click="handleCreate"> </a-button> -->
<PermissionBtn @btnEvent="onBtnClicked"></PermissionBtn>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction :actions="[
{
label:'详情',
onClick: handleDetail.bind(null, record),
},
{
label:'催办',
onClick: handleUrge.bind(null, record),
},
{
label:'撤销',
popConfirm: {
title: '是否撤销流程',
confirm: () => {
handleRevocation(record);
},
},
}
]" />
</template>
</template>
</BasicTable>
</PageWrapper>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable @register="registerTable" @fetch-success="onFetchSuccess" :searchInfo="searchInfo">
<template #toolbar>
<!-- <a-button type="primary" @click="handleCreate"> </a-button> -->
<PermissionBtn @btnEvent="onBtnClicked"></PermissionBtn>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
{
label: '催办',
onClick: handleUrge.bind(null, record),
},
{
label: '撤销',
popConfirm: {
title: '是否撤销流程',
confirm: () => {
handleRevocation(record);
},
},
},
]"
/>
</template>
</template>
</BasicTable>
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive, h } from 'vue'
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyPage, urge, revoke, revokeAudit } from '@/api/sys/WFProcess'
import { Tag, Switch } from 'ant-design-vue';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm, createMessage } = useMessage();
const searchInfo = reactive < Recordable > ({});
import { useGo } from '@/hooks/web/usePage';
const go = useGo();
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
api: getLoadMyPage,
columns: [
{
title: '标题',
dataIndex: 'title',
},
{
title: '流程模版',
dataIndex: 'schemeName',
},
{
title: '状态',
dataIndex: 'isFinished',
width: 80,
customRender: ({ record }) => {
if (record.isFinished == '1') {
const color = 'ref';
const text = '结束';
return h(Tag, { color: color }, () => text);
} else if (record.isAgain == '1') {
const color = 'orange';
const text = '重新提交';
return h(Tag, { color: color }, () => text);
} else {
const color = 'green';
const text = '审批中';
return h(Tag, { color: color }, () => text);
}
},
},
{
title: '提交人',
dataIndex: 'createUserName',
},
{
title: '创建时间',
dataIndex: 'createDate',
},
],
rowKey: 'id',
formConfig: {
labelWidth: 120,
schemas: [
{
field: '[StartDate, EndDate]',
label: '日期范围',
component: 'RangePicker',
componentProps: {
format: 'YYYY-MM-DD',
placeholder: ['开始日期', '结束日期'],
},
colProps: { span: 8 },
},
{
field: 'keyWord',
label: '关键字',
component: 'Input',
colProps: { span: 8 },
},
],
import { reactive, h } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyPage, urge, revoke, revokeAudit } from '@/api/sys/WFProcess';
import { Tag } from 'ant-design-vue';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
const searchInfo = reactive<Recordable>({});
import { useGo } from '@/hooks/web/usePage';
const go = useGo();
const [registerTable, { reload }] = useTable({
api: getLoadMyPage,
columns: [
{
title: '标题',
dataIndex: 'title',
},
{
title: '流程模版',
dataIndex: 'schemeName',
},
{
title: '状态',
dataIndex: 'isFinished',
width: 80,
customRender: ({ record }) => {
if (record.isFinished == '1') {
const color = 'red';
const text = '结束';
return h(Tag, { color: color }, () => text);
} else if (record.isAgain == '1') {
const color = 'orange';
const text = '重新提交';
return h(Tag, { color: color }, () => text);
} else {
const color = 'green';
const text = '审批中';
return h(Tag, { color: color }, () => text);
}
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
handleSearchInfoFn(info) {
return info;
},
{
title: '提交人',
dataIndex: 'createUserName',
},
{
title: '创建时间',
dataIndex: 'createDate',
},
],
rowKey: 'id',
formConfig: {
labelWidth: 120,
schemas: [
{
field: '[StartDate, EndDate]',
label: '日期范围',
component: 'RangePicker',
componentProps: {
format: 'YYYY-MM-DD',
placeholder: ['开始日期', '结束日期'],
},
colProps: { span: 8 },
},
actionColumn: {
width: 200,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
{
field: 'keyWord',
label: '关键字',
component: 'Input',
colProps: { span: 8 },
},
});
function handleDetail(record) {
go('/dashboard/task_look_preview/detail?processId=' + record.id);
],
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
handleSearchInfoFn(info) {
return info;
},
actionColumn: {
width: 200,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
},
});
function handleDetail(record) {
go('/dashboard/task_look_preview/detail?processId=' + record.id);
}
async function handleUrge(record) {
var query = {
id: record.id,
};
const data = await urge(query);
if (data) {
reload();
return createMessage.success('催办成功');
} else {
return createMessage.error('催办失败');
}
async function handleUrge(record) {
var query = {
id: record.id
}
const data = await urge(query)
if (data) {
reload()
return createMessage.info('催办成功');
} else {
return createMessage.error('催办失败');
}
}
async function handleRevocation(record) {
var query = {
taskId: record.id,
id: record.processId,
};
if (record.isStart == 0) {
const data = await revoke(query);
if (data) {
reload();
return createMessage.success('撤销成功');
} else {
return createMessage.error('撤销失败');
}
} else if (record.isCancel == 1) {
const data = await revokeAudit(query);
if (data) {
reload();
return createMessage.success('撤销成功');
} else {
return createMessage.error('撤销失败');
}
}
async function handleRevocation(record) {
var query = {
id: record.id
}
if (record.isStart == 0) {
const data = await revoke(query)
if (data) {
reload()
return createMessage.info('撤销成功');
} else {
return createMessage.error('撤销失败');
}
}
else if (record.isCancel == 1) {
const data = await revokeAudit(query)
if (data) {
reload()
return createMessage.info('撤销成功');
} else {
return createMessage.error('撤销失败');
}
}
}
</script>
}
</script>

View File

@ -1,149 +1,215 @@
<template>
<PageWrapper :class="prefixCls">
<a-tabs v-model:activeKey="activeName">
<a-tab-pane key="form" tab="表单信息">
</a-tab-pane>
<a-tab-pane key="flow" tab="流程信息(审核)" force-render>
<div class="process-design" :style="'display: flex; height:' + designerData.height">
<process-viewer :key="`designer-${id}`" :events="[
'element.click',
]" @element-click="elementClick" :xml="flowContent" :flowViewer="flowViewer" />
<div class="info-box" v-if="designerData.nodeLogs.length>0" >
<a-drawer v-model:open="infoOpen" class="custom-class" title="记录信息" placement="right">
<a-timeline>
<a-timeline-item v-for="(item,index) in designerData.nodeLogs" :key="index">
<div class="title">{{item.time}}</div>
<a-card hoverable size="small">
<div class="type-title">{{item.name}}</div>
<div class="content">
<span class="link" v-for="(userName,index2) in item.userNames">{{userName}}</span>
<!-- <l-user v-for="(userId,index2) in item.userIds" :key="index2" :value="userId" ></l-user> -->
{{item.des}}
</div>
</a-card>
</a-timeline-item>
</a-timeline>
</a-drawer>
</div>
</div>
</a-tab-pane>
</a-tabs>
<a-layout>
<a-layout>
<a-layout-content>
<a-tabs v-model:activeKey="activeName">
<a-tab-pane key="form" tab="表单信息"> </a-tab-pane>
<a-tab-pane key="flow" tab="流程信息(审核)" force-render>
<div class="process-design" :style="'display: flex; height:' + designerData.height">
<process-viewer
:key="`designer-${id}`"
:events="['element.click']"
@element-click="elementClick"
:xml="flowContent"
:flowViewer="flowViewer"
/>
</div>
</a-tab-pane>
</a-tabs>
</a-layout-content>
<!-- <a-divider type="vertical" /> -->
<a-layout-sider>
<a-tabs v-model:activeKey="auditName">
<a-tab-pane key="audit" tab="审批栏">
<div class="approval-column">
<a-form
ref="formRef"
:rules="rules"
:model="formData"
labelAlign="left"
:label-col="labelCol"
:wrapper-col="wrapperCol"
>
<a-form-item :label="designerData.isCreateAgain ? '备注' : '审批意见'" name="des">
</a-form-item>
<a-form-item label="">
<a-textarea
v-model:value="formData.des"
placeholder="请输入"
:auto-size="{ minRows: 5, maxRows: 8 }"
/>
</a-form-item>
<a-form-item label="" class="l-task-btns">
<a-button
v-for="(btn, index) in designerData.taskBtns"
:key="index"
type="primary"
:color="btn.type"
@click="handleBtnClick(btn)"
>{{ btn.name }} -- {{ btn.code }}</a-button
>
</a-form-item>
</a-form>
<auditInfo :data="designerData.userLogs"></auditInfo>
</div>
</a-tab-pane>
</a-tabs>
</a-layout-sider>
</a-layout>
</a-layout>
<!-- 节点记录信息 -->
<div class="info-box" v-if="designerData.nodeLogs.length > 0">
<a-drawer v-model:open="infoOpen" class="custom-class" title="记录信息" placement="right">
<a-timeline>
<a-timeline-item v-for="(item, index) in designerData.nodeLogs" :key="index">
<div class="title">{{ item.time }}</div>
<a-card hoverable size="small">
<div class="type-title">{{ item.name }}</div>
<div class="content">
<span class="link" v-for="(userName, index2) in item.userNames" :key="index2">{{
userName
}}</span>
{{ item.des }}
</div>
</a-card>
</a-timeline-item>
</a-timeline>
</a-drawer>
</div>
</PageWrapper>
</template>
<script lang="ts" setup>
import { h, ref, provide, reactive, onMounted, defineProps, computed, defineEmits, onBeforeMount } from 'vue';
import ProcessViewer from '@/components/ProcessViewer/index.vue';
import { ref, reactive, onBeforeMount } from 'vue';
import { ProcessViewer } from '@/components/ProcessViewer';
import { PageWrapper } from '@/components/Page';
import { SendOutlined, SaveOutlined, CloseCircleOutlined, ZoomInOutlined, RotateLeftOutlined, RotateRightOutlined, ClearOutlined } from '@ant-design/icons-vue';
import { getBPMN } from '@/api/sys/WFProcess'
import { getLoadMyUserList } from '@/api/sys/WFDelegate'
import { getTaskDetail } from '@/api/sys/WFTask'
import { useRoute } from 'vue-router'
import { useMultipleTabStore } from '@/store/modules/multipleTab';
import { useRouter } from 'vue-router';
import { buildGUID } from '@/utils/uuid';
import { useMessage } from '/@/hooks/web/useMessage';
import { dateFormat } from '@/utils/base'
const { createConfirm, createMessage } = useMessage();
import { getBPMN, createAgain, signAudit, audit } from '@/api/sys/WFProcess';
import { getTaskDetail } from '@/api/sys/WFTask';
import { useRoute } from 'vue-router';
import { dateFormat } from '@/utils/base';
import { flowStore } from '@/store/modules/flow';
import {
designerDataType,
logsType,
taskBtnsType,
currentNodeObject,
nodeUsersType,
} from './processModel';
import auditInfo from './auditInfo.vue'
const prefixCls = 'preview-box'
const tabStore = useMultipleTabStore();
const router = useRouter();
const content = ref('')
const flowContent = ref('')
const flowViewer = ref({})
const route = useRoute()
const processId = route.query.processId
const taskId = route.query.taskId
const designerOpen = ref(false)
const flowWfDataStore = flowStore();
const prefixCls = 'preview-box';
const flowContent = ref('');
const flowViewer = ref({});
const route = useRoute();
const processId = route.query.processId;
const taskId: any = route.query.taskId;
const type: any = route.query.type;
const formRef = ref();
const labelCol = { span: 7 };
const wrapperCol = { span: 13 };
const infoOpen = ref(true)
const designerData = reactive({
const wrapperCol = { span: 24 };
const infoOpen = ref(true);
const formData = ref({
des: '',
});
const rules: any = ref({
des: [{ required: true, message: '请填写审批意见', trigger: 'blur' }],
});
if (type == 4) {
rules.value = {};
}
const designerData: designerDataType = reactive({
loading: false,
xmlString: '',
controlForm: {
prefix: 'flowable',
},
height: document.documentElement.clientHeight - 200.5 + "px;",
height: document.documentElement.clientHeight - 200.5 + 'px;',
midVisible: false,
isCustmerTitle: false,
nodeUsers: [],
selectUsersVisible: false,
selectTUserVisible: false,
tUserType: 1, // 1 2 ,
isDraft: false,
delegateUsers: [],
task: null,
process: null,
logs: [],//
nodeMap: {},//
userLogs: [],//
task: {},
process: {},
logs: [], //
nodeMap: {}, //
userLogs: [], //
nodeLogs: [],
taskBtns: [],
})
const activeName = ref('flow')
function elementClick(element) {
console.log('elementClick')
console.log(element)
currentNode: {},
stampList: [],
currentBtn: {
code: '',
name: '',
isNextAuditor: false,
},
wfData: [],
isCreateAgain: type == 4 ? true : false,
selectRejectNodeVisible: false,
selectSignVisible: false,
});
const activeName = ref('flow');
const auditName = ref('audit');
function elementClick(element: { id: string | number }) {
if (element) {
designerData.nodeLogs = designerData.nodeMap[element.id] || []
infoOpen.value = true
}
else {
designerData.nodeLogs = []
designerData.nodeLogs = designerData.nodeMap[element.id] || [];
infoOpen.value = true;
} else {
designerData.nodeLogs = [];
}
}
async function getDetailInfo() {
let data = await getBPMN({ id: processId })
flowContent.value = data.flowContent
flowViewer.value = data.flowViewer
let query: any = {
id: processId,
};
let data = await getBPMN(query);
flowContent.value = data.flowContent;
flowViewer.value = data.flowViewer;
}
async function getTaskInfo() {
let data = await getTaskDetail({ id: taskId })
designerData.process = data.process
designerData.task = data.task
setLogsAndTasks(data.logs, data.tasks)
let query: any = {
id: taskId,
};
let data = await getTaskDetail(query);
designerData.process = data.process;
designerData.task = data.task;
setLogsAndTasks(data.logs, data.tasks);
getBtns();
}
function setLogsAndTasks(logs, tasks) {
const res = []
const taskMap = {}
const nodeMap = {}
const userLogs = []
function setLogsAndTasks(logs: any[], tasks: any[]) {
const res: logsType[] = [];
const taskMap = {};
const nodeMap = {};
const userLogs: any[] = [];
tasks.forEach(task => {
nodeMap[task.unitId] = nodeMap[task.unitId] || [{
unitId: task.unitId,
name: task.unitName,
userIds: [],
userNames: [],
des: '正在审核',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
isFinish: false
}]
tasks.forEach(
(task: {
unitId: string | number;
unitName: any;
createDate: any;
type: number;
userId: any;
userName: any;
}) => {
nodeMap[task.unitId] = nodeMap[task.unitId] || [
{
unitId: task.unitId,
name: task.unitName,
userIds: [],
userNames: [],
des: '正在审核',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
isFinish: false,
},
];
if (task.type == 2) {
taskMap[task.unitId + task.type] = taskMap[task.unitId + task.type] || {
unitId: task.unitId,
name: task.unitName,
userIds: [],
userNames: [],
des: '正在查阅',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary'
}
taskMap[task.unitId + task.type].userIds.push(task.userId)
taskMap[task.unitId + task.type].userNames.push(task.userName)
if (nodeMap[task.unitId].length == 1) {
nodeMap[task.unitId].push({
if (task.type == 2) {
taskMap[task.unitId + task.type] = taskMap[task.unitId + task.type] || {
unitId: task.unitId,
name: task.unitName,
userIds: [],
@ -151,110 +217,278 @@
des: '正在查阅',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
isFinish: true
})
}
nodeMap[task.unitId][1].userIds.push(task.userId)
nodeMap[task.unitId][1].userNames.push(task.userName)
};
taskMap[task.unitId + task.type].userIds.push(task.userId);
taskMap[task.unitId + task.type].userNames.push(task.userName);
}
else {
taskMap[task.unitId] = taskMap[task.unitId] || {
unitId: task.unitId,
name: task.unitName,
userIds: [],
userNames: [],
des: '正在审核',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary'
if (nodeMap[task.unitId].length == 1) {
nodeMap[task.unitId].push({
unitId: task.unitId,
name: task.unitName,
userIds: [],
userNames: [],
des: '正在查阅',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
isFinish: true,
});
}
nodeMap[task.unitId][1].userIds.push(task.userId);
nodeMap[task.unitId][1].userNames.push(task.userName);
} else {
taskMap[task.unitId] = taskMap[task.unitId] || {
unitId: task.unitId,
name: task.unitName,
userIds: [],
userNames: [],
des: '正在审核',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
};
taskMap[task.unitId].userIds.push(task.userId);
nodeMap[task.unitId][0].userIds.push(task.userId);
taskMap[task.unitId].userNames.push(task.userName);
nodeMap[task.unitId][0].userNames.push(task.userName);
}
taskMap[task.unitId].userIds.push(task.userId)
nodeMap[task.unitId][0].userIds.push(task.userId)
taskMap[task.unitId].userNames.push(task.userName)
nodeMap[task.unitId][0].userNames.push(task.userName)
}
})
},
);
for (let key in taskMap) {
res.push(taskMap[key])
res.push(taskMap[key]);
}
for (let key in nodeMap) {
nodeMap[key] = nodeMap[key].filter(t => t.userIds.length > 0)
nodeMap[key] = nodeMap[key].filter((t: { userIds: string | any[] }) => t.userIds.length > 0);
}
logs.forEach(
(log: {
unitId: string;
unitName: any;
userId: string;
userName: string;
des: string;
f_OperationName: string;
createDate: any;
f_TaskType: number;
f_OperationCode: string;
f_UserName: any;
f_StampImg: any;
}) => {
res.push({
unitId: log.unitId,
name: log.unitName,
userIds: [log.userId],
userNames: [log.userName],
des: log.des ? log.des : log.f_OperationName,
time: dateFormat(log.createDate),
type: 'info',
});
nodeMap[log.unitId] = nodeMap[log.unitId] || [];
nodeMap[log.unitId].push({
unitId: log.unitId,
name: log.unitName,
userIds: [log.userId],
userNames: [log.userName],
time: dateFormat(log.createDate),
des: log.des ? log.des : log.f_OperationName,
type: 'info',
isFinish: true,
});
logs.forEach(log => {
res.push({
unitId: log.unitId,
name: log.unitName,
userIds: [log.userId],
userNames: [log.userName],
des: log.des ? log.des : log.f_OperationName,
time: dateFormat(log.createDate),
type: 'info'
})
nodeMap[log.unitId] = nodeMap[log.unitId] || []
nodeMap[log.unitId].push({
unitId: log.unitId,
name: log.unitName,
userIds: [log.userId],
userNames: [log.userName],
time: dateFormat(log.createDate),
des: log.des ? log.des : log.f_OperationName,
type: 'info',
isFinish: true
})
if (log.f_TaskType == 1 && !['sign'].includes(log.f_OperationCode)) { //
const userLogIndex = userLogs.findIndex(t => t.id == log.unitId)
if (userLogIndex == -1) {
userLogs.push({
id: log.unitId,
name: log.unitName,
user: log.f_UserName,
time: dateFormat(log.createDate),
des: log.des,
img: log.f_StampImg
})
if (log.f_TaskType == 1 && !['sign'].includes(log.f_OperationCode)) {
//
const userLogIndex = userLogs.findIndex((t) => t.id == log.unitId);
if (userLogIndex == -1) {
userLogs.push({
id: log.unitId,
name: log.unitName,
user: log.f_UserName,
time: dateFormat(log.createDate),
des: log.des,
img: log.f_StampImg,
});
}
}
}
})
},
);
designerData.logs = res
designerData.nodeMap = nodeMap
designerData.logs = res;
designerData.nodeMap = nodeMap;
designerData.userLogs = userLogs.sort(function (a, b) {
return b.time < a.time ? -1 : 1
})
return b.time < a.time ? -1 : 1;
});
//console.log(logs,'logs')
}
function closePreview() {
if (!id) {
tabStore.closeTabByKey('/dashboard/task_preview/detail', router);
async function validateForm() {
let res = await formRef.value
.validate()
.then((values: any) => {
return true;
})
.catch((error: any) => {
return false;
});
return res;
}
function getBtns() {
const wfData = flowWfDataStore.getWfData;
console.log(wfData);
designerData.wfData = wfData;
const currentNode: currentNodeObject = wfData.find((t) => t.id == designerData.task.unitId) || {};
designerData.currentNode = currentNode;
//
const btns: taskBtnsType[] = [];
if (currentNode.type == 'startEvent') {
btns.push({
code: 'learun_create',
name: '提交',
type: '',
});
} else {
// /dashboard/create_preview/add?id=1
tabStore.closeTabByKey('/dashboard/task_preview/detail?id=' + id, router);
currentNode.btnlist.forEach((btn: taskBtnsType) => {
if (btn.code == 'agree') {
btn.type = '';
} else if (btn.code == 'disagree') {
btn.type = 'error';
}
btns.push(btn);
});
if (currentNode.isAddSign) {
btns.push({
code: 'learun_sign',
name: '加签',
type: 'success',
});
}
if (currentNode.isTransfer) {
btns.push({
code: 'learun_transfer',
name: '转移',
type: 'success',
});
}
}
console.log(btns);
designerData.taskBtns = btns;
}
async function handleBtnClick(this: any, btn) {
const data = await validateForm();
if (!data) {
return;
}
const currentBtn = btn;
designerData.currentBtn = currentBtn;
let res: any;
switch (btn.code) {
case 'learun_create':
res = await createAgain({
processId: this.processId,
des: `重新提交${formData.value.des ? '-' : ''}${formData.value.des}`,
});
break;
case 'learun_sign':
designerData.tUserType = 2;
designerData.selectTUserVisible = true;
break;
case 'learun_transfer':
designerData.tUserType = 1;
designerData.selectTUserVisible = true;
break;
default:
if (designerData.task.type == 6) {
//
res = await signAudit(taskId, {
code: btn.code,
name: btn.name,
des: formData.value.des,
});
} else {
console.log(designerData.currentNode);
if (designerData.currentNode.rejectType == '2' && btn.code == 'disagree') {
designerData.selectRejectNodeVisible = true;
return;
}
if (btn.isSign) {
//
// const stampList = await this.$awaitWraper(apiStamp.getList(this.loginInfo.f_UserId));
// if (stampList && stampList.length > 0) {
// designerData.stampList = stampList;
// designerData.selectSignVisible = true;
// return;
// }
}
res = await auditFun();
}
break;
}
if (res) {
designerData.midVisible = false;
}
}
async function auditFun() {
//
if (designerData.currentBtn.isNextAuditor) {
const res = await getLoadNextAuditors({
processId: processId,
nodeId: designerData.currentNode.id,
});
const nodeUserMap = res.data.data;
const nodeUsers: nodeUsersType[] = [];
for (let key in nodeUserMap) {
const nodeUserItem = nodeUserMap[key];
if (nodeUserItem.length > 1) {
nodeUsers.push({
name: designerData.wfData.find((t) => t.id == key).name,
id: key,
options: nodeUserItem.map((t: { id: any; name: any }) => {
return { value: t.id, label: t.name };
}),
});
}
}
designerData.nodeUsers = nodeUsers;
if (designerData.nodeUsers.length > 0) {
designerData.selectUsersVisible = true;
return;
}
}
return await audit(taskId, {
code: designerData.currentBtn.code,
name: designerData.currentBtn.name,
des: formData.value.des,
});
}
// function closePreview() {
// if (!id) {
// tabStore.closeTabByKey('/dashboard/task_preview/detail', router);
// } else {
// // /dashboard/create_preview/add?id=1
// tabStore.closeTabByKey('/dashboard/task_preview/detail?id=' + id, router);
// }
// }
onBeforeMount(() => {
getDetailInfo()
getTaskInfo()
})
getDetailInfo();
getTaskInfo();
});
</script>
<style lang="less" scoped>
::v-deep .ant-divider-vertical {
height: 100%;
}
.info-box {
display: inline-block;
width: 300px;
position: absolute;
right: 0;
margin-top: 40px;
}
.ant-timeline-item-content {
@ -270,24 +504,48 @@
font-weight: bold;
margin-bottom: 8px;
}
.link{
color:#409EFF;
.link {
color: #409eff;
}
}
.preview-box {
background-color: @component-background;
height: 100%;
.btn-box {
padding: 10px;
justify-content: flex-end;
display: flex;
}
}
::v-deep .vben-page-wrapper-content {
height: 100%;
margin: 0 0 0 16px;
}
.form-box {
width: 480px;
}
</style>
.approval-column {
padding: 10px;
}
::v-deep .ant-layout .ant-layout-sider {
padding-left: 10px;
background-color: @component-background;
flex: 0 0 360px !important;
max-width: 360px !important;
min-width: 360px !important;
width: 360px !important;
}
::v-deep .vben-page-wrapper .vben-page-wrapper-content {
height: 98%;
}
.l-task-btns {
.ant-btn {
margin: 0;
margin-top: 8px;
margin-right: 8px;
}
}
</style>

View File

@ -0,0 +1,112 @@
<template>
<div class="l-wf-audit-info">
<div class="l-wf-audit-info--item" v-for="item in props.data" :key="item.id">
<div class="l-wf-audit-info--header">{{ item.name }}</div>
<div class="l-wf-audit-info--body">
<div style="position: relative; z-index: 2">{{ item.des }}</div>
<div class="l-wf-audit-info--imgdiv" v-if="item.img">
<img
class="l-wf-audit-info--img"
:src="`${apiUrl}system/stamp/wfimg/${item.img}?token=${token}`"
/>
</div>
<div class="l-wf-audit-info--user">
<div class="l-wf-audit-info--name">
<span>&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;</span>
<span>{{ item.user }}</span>
</div>
<div class="l-wf-audit-info--date">
<span>&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;</span>
<span>{{ item.time }}</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { defineProps } from 'vue';
const props = defineProps({
data: {
type: Array,
default: () => [],
},
});
console.log(props);
</script>
<style lang="scss" scoped>
.l-wf-audit-info {
position: relative;
box-sizing: border-box;
width: 100%;
&--item {
position: relative;
width: 100%;
border: 1px solid #ccc;
padding-left: 120px;
border-top: 0;
box-sizing: border-box;
min-height: 88px;
}
&--item:first-child {
border-top: 1px solid #ccc;
}
&--header {
position: absolute;
box-sizing: border-box;
top: 0;
left: 0;
height: 100%;
width: 120px;
border-right: 1px solid #ccc;
padding: 4px 0 0 4px;
}
&--body {
position: relative;
box-sizing: border-box;
width: 100%;
height: 100%;
padding: 4px;
}
&--imgdiv {
position: absolute;
box-sizing: border-box;
top: 0;
right: 0;
width: 80px;
}
&--img {
width: 100%;
}
&--user {
margin-top: 8px;
position: relative;
width: 100%;
height: 42px;
box-sizing: border-box;
}
&--name {
position: absolute;
bottom: 24px;
right: 0;
width: 180px;
text-align: left;
font-size: 12px;
}
&--date {
position: absolute;
right: 0;
width: 180px;
text-align: left;
bottom: 4px;
font-size: 12px;
}
}
</style>

View File

@ -1,229 +1,519 @@
<template>
<PageWrapper :class="prefixCls">
<a-tabs v-model:activeKey="activeName">
<a-tab-pane key="form" tab="表单信息">
</a-tab-pane>
<a-tab-pane key="flow" tab="流程信息" force-render>
<div class="process-design" :style="'display: flex; height:' + designerData.height">
<process-viewer :key="`designer-${id}`" :events="[
'element.click',
]" @element-click="elementClick" :xml="flowContent" :flowViewer="flowViewer" />
</div>
</a-tab-pane>
</a-tabs>
</PageWrapper>
</template>
<script lang="ts" setup>
import { h, ref, provide, reactive, onMounted, defineProps, computed, defineEmits, onBeforeMount } from 'vue';
import ProcessViewer from '@/components/ProcessViewer/index.vue';
import { PageWrapper } from '@/components/Page';
import { SendOutlined, SaveOutlined, CloseCircleOutlined, ZoomInOutlined, RotateLeftOutlined, RotateRightOutlined, ClearOutlined } from '@ant-design/icons-vue';
import { getBPMN } from '@/api/sys/WFProcess'
import { getLoadMyUserList } from '@/api/sys/WFDelegate'
import { getTaskDetail } from '@/api/sys/WFTask'
import { useRoute } from 'vue-router'
import { useMultipleTabStore } from '@/store/modules/multipleTab';
import { useRouter } from 'vue-router';
import { buildGUID } from '@/utils/uuid';
import { useMessage } from '/@/hooks/web/useMessage';
import {dateFormat} from '@/utils/base'
const { createConfirm, createMessage } = useMessage();
const prefixCls = 'preview-box'
const tabStore = useMultipleTabStore();
const router = useRouter();
const content = ref('')
const flowContent = ref('')
const flowViewer = ref({})
const route = useRoute()
const processId = route.query.processId
const taskId = route.query.taskId
const designerOpen = ref(false)
const formRef = ref();
const labelCol = { span: 7 };
const wrapperCol = { span: 13 };
const designerData = reactive({
loading: false,
xmlString: '',
controlForm: {
prefix: 'flowable',
},
height: document.documentElement.clientHeight - 230.5 + "px;",
midVisible: false,
isCustmerTitle: false,
nodeUsers: [],
selectUsersVisible: false,
isDraft: false,
delegateUsers: [],
task: null,
process: null,
logs: [],//
nodeMap: {},//
userLogs: [],//
nodeLogs: [],
taskBtns: [],
})
const activeName = ref('flow')
function elementClick(element) {
console.log('elementClick')
console.log(element)
<PageWrapper :class="prefixCls">
<a-layout>
<a-layout>
<a-layout-content>
<a-tabs v-model:activeKey="activeName">
<a-tab-pane key="form" tab="表单信息"> </a-tab-pane>
<a-tab-pane key="flow" tab="流程信息(审核)" force-render>
<div class="process-design" :style="'display: flex; height:' + designerData.height">
<process-viewer
:key="`designer-${id}`"
:events="['element.click']"
@element-click="elementClick"
:xml="flowContent"
:flowViewer="flowViewer"
/>
</div>
</a-tab-pane>
</a-tabs>
</a-layout-content>
<a-layout-sider>
<a-tabs v-model:activeKey="auditName">
<a-tab-pane key="audit" tab="审批信息">
<div class="approval-info">
<auditInfo :data="designerData.userLogs"></auditInfo>
</div>
</a-tab-pane>
</a-tabs>
</a-layout-sider>
</a-layout>
</a-layout>
<!-- 节点记录信息 -->
<div class="info-box" v-if="designerData.nodeLogs.length > 0">
<a-drawer v-model:open="infoOpen" class="custom-class" title="记录信息" placement="right">
<a-timeline>
<a-timeline-item v-for="(item, index) in designerData.nodeLogs" :key="index">
<div class="title">{{ item.time }}</div>
<a-card hoverable size="small">
<div class="type-title">{{ item.name }}</div>
<div class="content">
<span class="link" v-for="(userName, index2) in item.userNames" :key="index2">{{
userName
}}</span>
{{ item.des }}
</div>
</a-card>
</a-timeline-item>
</a-timeline>
</a-drawer>
</div>
</PageWrapper>
</template>
<script lang="ts" setup>
import { ref, reactive, onBeforeMount } from 'vue';
import { ProcessViewer } from '@/components/ProcessViewer';
import { PageWrapper } from '@/components/Page';
import { getBPMN, createAgain, signAudit, audit } from '@/api/sys/WFProcess';
import { getTaskDetail } from '@/api/sys/WFTask';
import { useRoute } from 'vue-router';
import { dateFormat } from '@/utils/base';
import { flowStore } from '@/store/modules/flow';
import {
designerDataType,
logsType,
taskBtnsType,
currentNodeObject,
nodeUsersType,
} from './processModel';
import auditInfo from './auditInfo.vue'
const flowWfDataStore = flowStore();
const prefixCls = 'preview-box';
const flowContent = ref('');
const flowViewer = ref({});
const route = useRoute();
const processId = route.query.processId;
const taskId: any = route.query.taskId;
const type: any = route.query.type;
const formRef = ref();
const infoOpen = ref(true);
const formData = ref({
des: '',
});
const rules: any = ref({
des: [{ required: true, message: '请填写审批意见', trigger: 'blur' }],
});
if (type == 4) {
rules.value = {};
}
const designerData: designerDataType = reactive({
loading: false,
xmlString: '',
height: document.documentElement.clientHeight - 200.5 + 'px;',
midVisible: false,
isCustmerTitle: false,
nodeUsers: [],
selectUsersVisible: false,
selectTUserVisible: false,
tUserType: 1, // 1 2 ,
isDraft: false,
delegateUsers: [],
task: {},
process: {},
logs: [], //
nodeMap: {}, //
userLogs: [], //
nodeLogs: [],
taskBtns: [],
currentNode: {},
stampList: [],
currentBtn: {
code: '',
name: '',
isNextAuditor: false,
},
wfData: [],
isCreateAgain: type == 4 ? true : false,
selectRejectNodeVisible: false,
selectSignVisible: false,
});
const activeName = ref('flow');
const auditName = ref('audit');
function elementClick(element: { id: string | number }) {
if (element) {
designerData.nodeLogs = designerData.nodeMap[element.id] || [];
infoOpen.value = true;
} else {
designerData.nodeLogs = [];
}
async function getDetailInfo() {
let data = await getBPMN({ id: processId })
flowContent.value = data.flowContent
flowViewer.value = data.flowViewer
}
async function getTaskInfo() {
let data = await getTaskDetail({ id: taskId })
designerData.process = data.process
designerData.task = data.task
setLogsAndTasks(data.logs, data.tasks)
}
function setLogsAndTasks(logs, tasks) {
const res = []
const taskMap = {}
const nodeMap = {}
const userLogs = []
tasks.forEach(task => {
nodeMap[task.unitId] = nodeMap[task.unitId] || [{
unitId: task.unitId,
name: task.unitName,
userIds: [],
des: '正在审核',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
isFinish: false
}]
}
async function getDetailInfo() {
let query: any = {
id: processId,
};
let data = await getBPMN(query);
flowContent.value = data.flowContent;
flowViewer.value = data.flowViewer;
}
async function getTaskInfo() {
let query: any = {
id: taskId,
};
let data = await getTaskDetail(query);
designerData.process = data.process;
designerData.task = data.task;
setLogsAndTasks(data.logs, data.tasks);
getBtns();
}
function setLogsAndTasks(logs: any[], tasks: any[]) {
const res: logsType[] = [];
const taskMap = {};
const nodeMap = {};
const userLogs: any[] = [];
tasks.forEach(
(task: {
unitId: string | number;
unitName: any;
createDate: any;
type: number;
userId: any;
userName: any;
}) => {
nodeMap[task.unitId] = nodeMap[task.unitId] || [
{
unitId: task.unitId,
name: task.unitName,
userIds: [],
userNames: [],
des: '正在审核',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
isFinish: false,
},
];
if (task.type == 2) {
taskMap[task.unitId + task.type] = taskMap[task.unitId + task.type] || {
unitId: task.unitId,
name: task.unitName,
userIds: [],
userNames: [],
des: '正在查阅',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary'
}
taskMap[task.unitId + task.type].userIds.push(task.userId)
type: 'primary',
};
taskMap[task.unitId + task.type].userIds.push(task.userId);
taskMap[task.unitId + task.type].userNames.push(task.userName);
if (nodeMap[task.unitId].length == 1) {
nodeMap[task.unitId].push({
unitId: task.unitId,
name: task.unitName,
userIds: [],
userNames: [],
des: '正在查阅',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
isFinish: true
})
isFinish: true,
});
}
nodeMap[task.unitId][1].userIds.push(task.userId)
}
else {
nodeMap[task.unitId][1].userIds.push(task.userId);
nodeMap[task.unitId][1].userNames.push(task.userName);
} else {
taskMap[task.unitId] = taskMap[task.unitId] || {
unitId: task.unitId,
name: task.unitName,
userIds: [],
userNames: [],
des: '正在审核',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary'
}
taskMap[task.unitId].userIds.push(task.userId)
nodeMap[task.unitId][0].userIds.push(task.userId)
type: 'primary',
};
taskMap[task.unitId].userIds.push(task.userId);
nodeMap[task.unitId][0].userIds.push(task.userId);
taskMap[task.unitId].userNames.push(task.userName);
nodeMap[task.unitId][0].userNames.push(task.userName);
}
})
for (let key in taskMap) {
res.push(taskMap[key])
}
for (let key in nodeMap) {
nodeMap[key] = nodeMap[key].filter(t => t.userIds.length > 0)
}
logs.forEach(log => {
},
);
for (let key in taskMap) {
res.push(taskMap[key]);
}
for (let key in nodeMap) {
nodeMap[key] = nodeMap[key].filter((t: { userIds: string | any[] }) => t.userIds.length > 0);
}
logs.forEach(
(log: {
unitId: string;
unitName: any;
userId: string;
userName: string;
des: string;
operationName: string;
createDate: any;
taskType: number;
operationCode: string;
stampImg: any;
}) => {
res.push({
unitId: log.unitId,
name: log.unitName,
userIds: [log.userId],
des: log.des ? log.des : log.f_OperationName,
userNames: [log.userName],
des: log.des ? log.des : log.operationName,
time: dateFormat(log.createDate),
type: 'info'
})
nodeMap[log.unitId] = nodeMap[log.unitId] || []
type: 'info',
});
nodeMap[log.unitId] = nodeMap[log.unitId] || [];
nodeMap[log.unitId].push({
unitId: log.unitId,
name: log.unitName,
userIds: [log.userId],
userNames: [log.userName],
time: dateFormat(log.createDate),
des: log.des ? log.des : log.f_OperationName,
des: log.des ? log.des : log.operationName,
type: 'info',
isFinish: true
})
if (log.f_TaskType == 1 && !['sign'].includes(log.f_OperationCode)) { //
const userLogIndex = userLogs.findIndex(t => t.id == log.unitId)
isFinish: true,
});
if (log.taskType == 1 && !['sign'].includes(log.operationCode)) {
//
const userLogIndex = userLogs.findIndex((t) => t.id == log.unitId);
if (userLogIndex == -1) {
userLogs.push({
id: log.unitId,
name: log.unitName,
user: log.f_UserName,
user: log.userName,
time: dateFormat(log.createDate),
des: log.des,
img: log.f_StampImg
})
img: log.stampImg,
});
}
}
},
);
designerData.logs = res;
designerData.nodeMap = nodeMap;
designerData.userLogs = userLogs.sort(function (a, b) {
return b.time < a.time ? -1 : 1;
});
//console.log(logs,'logs')
}
async function validateForm() {
let res = await formRef.value
.validate()
.then((values: any) => {
return true;
})
designerData.logs = res
designerData.nodeMap = nodeMap
designerData.userLogs = userLogs.sort(function (a, b) {
return b.time < a.time ? -1 : 1
})
//console.log(logs,'logs')
}
function closePreview() {
if (!id) {
tabStore.closeTabByKey('/dashboard/task_preview/detail', router);
} else {
// /dashboard/create_preview/add?id=1
tabStore.closeTabByKey('/dashboard/task_preview/detail?id=' + id, router);
.catch((error: any) => {
return false;
});
return res;
}
function getBtns() {
const wfData = flowWfDataStore.getWfData;
console.log(wfData);
designerData.wfData = wfData;
const currentNode: currentNodeObject = wfData.find((t) => t.id == designerData.task.unitId) || {};
designerData.currentNode = currentNode;
//
const btns: taskBtnsType[] = [];
if (currentNode.type == 'startEvent') {
btns.push({
code: 'learun_create',
name: '提交',
type: '',
});
} else {
currentNode.btnlist.forEach((btn: taskBtnsType) => {
if (btn.code == 'agree') {
btn.type = '';
} else if (btn.code == 'disagree') {
btn.type = 'error';
}
btns.push(btn);
});
if (currentNode.isAddSign) {
btns.push({
code: 'learun_sign',
name: '加签',
type: 'success',
});
}
if (currentNode.isTransfer) {
btns.push({
code: 'learun_transfer',
name: '转移',
type: 'success',
});
}
}
onBeforeMount(() => {
getDetailInfo()
getTaskInfo()
})
</script>
<style lang="less" scoped>
.preview-box {
background-color: @component-background;
.btn-box {
padding: 10px;
justify-content: flex-end;
display: flex;
console.log(btns);
designerData.taskBtns = btns;
}
async function handleBtnClick(this: any, btn) {
const data = await validateForm();
if (!data) {
return;
}
const currentBtn = btn;
designerData.currentBtn = currentBtn;
let res: any;
switch (btn.code) {
case 'learun_create':
res = await createAgain({
processId: this.processId,
des: `重新提交${formData.value.des ? '-' : ''}${formData.value.des}`,
});
break;
case 'learun_sign':
designerData.tUserType = 2;
designerData.selectTUserVisible = true;
break;
case 'learun_transfer':
designerData.tUserType = 1;
designerData.selectTUserVisible = true;
break;
default:
if (designerData.task.type == 6) {
//
res = await signAudit(taskId, {
code: btn.code,
name: btn.name,
des: formData.value.des,
});
} else {
console.log(designerData.currentNode);
if (designerData.currentNode.rejectType == '2' && btn.code == 'disagree') {
designerData.selectRejectNodeVisible = true;
return;
}
if (btn.isSign) {
//
// const stampList = await this.$awaitWraper(apiStamp.getList(this.loginInfo.f_UserId));
// if (stampList && stampList.length > 0) {
// designerData.stampList = stampList;
// designerData.selectSignVisible = true;
// return;
// }
}
res = await auditFun();
}
break;
}
if (res) {
designerData.midVisible = false;
}
}
async function auditFun() {
//
if (designerData.currentBtn.isNextAuditor) {
const res = await getLoadNextAuditors({
processId: processId,
nodeId: designerData.currentNode.id,
});
const nodeUserMap = res.data.data;
const nodeUsers: nodeUsersType[] = [];
for (let key in nodeUserMap) {
const nodeUserItem = nodeUserMap[key];
if (nodeUserItem.length > 1) {
nodeUsers.push({
name: designerData.wfData.find((t) => t.id == key).name,
id: key,
options: nodeUserItem.map((t: { id: any; name: any }) => {
return { value: t.id, label: t.name };
}),
});
}
}
designerData.nodeUsers = nodeUsers;
if (designerData.nodeUsers.length > 0) {
designerData.selectUsersVisible = true;
return;
}
}
.form-box {
width: 480px;
return await audit(taskId, {
code: designerData.currentBtn.code,
name: designerData.currentBtn.name,
des: formData.value.des,
});
}
// function closePreview() {
// if (!id) {
// tabStore.closeTabByKey('/dashboard/task_preview/detail', router);
// } else {
// // /dashboard/create_preview/add?id=1
// tabStore.closeTabByKey('/dashboard/task_preview/detail?id=' + id, router);
// }
// }
onBeforeMount(() => {
getDetailInfo();
getTaskInfo();
});
</script>
<style lang="less" scoped>
::v-deep .ant-divider-vertical {
height: 100%;
}
.info-box {
display: inline-block;
width: 300px;
position: absolute;
right: 0;
margin-top: 40px;
}
.ant-timeline-item-content {
.title {
color: #909399;
line-height: 1;
margin-bottom: 8px;
font-size: 13px;
}
</style>
.type-title {
font-size: 12px;
font-weight: bold;
margin-bottom: 8px;
}
.link {
color: #409eff;
}
}
.preview-box {
height: 100%;
.btn-box {
padding: 10px;
justify-content: flex-end;
display: flex;
}
}
::v-deep .vben-page-wrapper-content {
height: 100%;
margin: 0 0 0 16px;
}
.form-box {
width: 480px;
}
.approval-column {
padding: 10px;
}
::v-deep .ant-layout .ant-layout-sider {
padding-left: 10px;
background-color: @component-background;
flex: 0 0 360px !important;
max-width: 360px !important;
min-width: 360px !important;
width: 360px !important;
}
::v-deep .vben-page-wrapper .vben-page-wrapper-content {
height: 98%;
}
.l-task-btns {
.ant-btn {
margin: 0;
margin-top: 8px;
margin-right: 8px;
}
}
</style>

View File

@ -0,0 +1,57 @@
export interface logsType {
unitId: string,
name: string,
userIds: Array<string>,
userNames: Array<string>,
des: string,
time: string,
type: string,
}
export interface nodeUsersType {
id: string,
name: string,
options: {
value: string,
label: string
}
}
export interface taskBtnsType {
code: string,
name: string,
type: string
}
export interface currentNodeObject {
[key: string]: any;
}
export interface designerDataType {
loading: Boolean;
xmlString: '',
height: string,
midVisible: Boolean,
isCustmerTitle: Boolean,
nodeUsers: nodeUsersType[],
selectUsersVisible: Boolean,
selectTUserVisible: Boolean,
tUserType: Number, // 1 转移 2 加签,
isDraft: Boolean,
delegateUsers: [],
task: currentNodeObject,
process: currentNodeObject,
logs: logsType[], // 流程日志信息
nodeMap: {}, // 需要处理的任务
userLogs: currentNodeObject[], // 人员日志信息
nodeLogs: currentNodeObject[],
taskBtns: taskBtnsType[],
currentNode: currentNodeObject,
stampList: [],
currentBtn: {
code: string,
name: string,
isNextAuditor:boolean
},
wfData: currentNodeObject[],
isCreateAgain: Boolean,
selectRejectNodeVisible:Boolean,
selectSignVisible:Boolean,
}

View File

@ -1,118 +1,107 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable @register="registerTable" @fetch-success="onFetchSuccess" :searchInfo="searchInfo">
<template #toolbar>
<!-- <a-button type="primary" @click="handleCreate"> </a-button> -->
<PermissionBtn @btnEvent="onBtnClicked"></PermissionBtn>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction :actions="[
{
label:'详情',
onClick: handleDetail.bind(null, record),
},
{
label:'撤销',
onClick: handleRevocation.bind(null, record),
}
]" />
</template>
</template>
</BasicTable>
</PageWrapper>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable @register="registerTable" @fetch-success="onFetchSuccess" :searchInfo="searchInfo">
<template #toolbar>
<!-- <a-button type="primary" @click="handleCreate"> </a-button> -->
<PermissionBtn @btnEvent="onBtnClicked"></PermissionBtn>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
]"
/>
</template>
</template>
</BasicTable>
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyReadPage } from '@/api/sys/WFTask'
import { Tag, Switch } from 'ant-design-vue';
const searchInfo = reactive < Recordable > ({});
import { useGo } from '@/hooks/web/usePage';
const go = useGo();
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
api: getLoadMyReadPage,
columns: [
{
title: '任务',
dataIndex: 'unitName',
},
{
title: '标题',
dataIndex: 'processTitle',
},
{
title: '状态',
dataIndex: 'state',
width: 80,
customRender: ({ record }) => {
if (record.state == '1') {
const color = 'ref';
const text = '未阅';
return h(Tag, { color: color }, () => text);
} else {
const color = 'green';
const text = '已阅';
return h(Tag, { color: color }, () => text);
}
},
},
{
title: '提交人',
dataIndex: 'processUserName',
},
{
title: '创建时间',
dataIndex: 'createDate',
},
],
rowKey: 'id',
formConfig: {
labelWidth: 120,
schemas: [
{
field: '[StartDate, EndDate]',
label: '日期范围',
component: 'RangePicker',
componentProps: {
format: 'YYYY-MM-DD',
placeholder: ['开始日期', '结束日期'],
},
colProps: { span: 8 },
},
{
field: 'keyWord',
label: '关键字',
component: 'Input',
colProps: { span: 8 },
},
],
import { reactive, h } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyReadPage } from '@/api/sys/WFTask';
import { Tag } from 'ant-design-vue';
const searchInfo = reactive<Recordable>({});
import { useGo } from '@/hooks/web/usePage';
const go = useGo();
const [registerTable] = useTable({
api: getLoadMyReadPage,
columns: [
{
title: '任务',
dataIndex: 'unitName',
},
{
title: '标题',
dataIndex: 'processTitle',
},
{
title: '状态',
dataIndex: 'state',
width: 80,
customRender: ({ record }) => {
if (record.state == '1') {
const color = 'red';
const text = '未阅';
return h(Tag, { color: color }, () => text);
} else {
const color = 'green';
const text = '已阅';
return h(Tag, { color: color }, () => text);
}
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
handleSearchInfoFn(info) {
return info;
},
{
title: '提交人',
dataIndex: 'processUserName',
},
{
title: '创建时间',
dataIndex: 'createDate',
},
],
rowKey: 'id',
formConfig: {
labelWidth: 120,
schemas: [
{
field: '[StartDate, EndDate]',
label: '日期范围',
component: 'RangePicker',
componentProps: {
format: 'YYYY-MM-DD',
placeholder: ['开始日期', '结束日期'],
},
colProps: { span: 8 },
},
actionColumn: {
width: 100,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
{
field: 'keyWord',
label: '关键字',
component: 'Input',
colProps: { span: 8 },
},
});
function handleDetail(record){
go('/dashboard/task_look_preview/detail?processId=' + record.id);
}
function handleRevocation(record){
console.log(record)
}
</script>
],
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
handleSearchInfoFn(info) {
return info;
},
actionColumn: {
width: 100,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
},
});
function handleDetail(record) {
go('/dashboard/task_look_preview/detail?processId=' + record.id);
}
</script>

View File

@ -7,28 +7,31 @@
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction :actions="[
<TableAction :actions="[
{
label:'详情',
label:'审核',
onClick: handleDetail.bind(null, record),
}
]" />
</template>
</template>
</template>
</BasicTable>
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive ,h} from 'vue'
import { reactive, h } from 'vue'
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyUncompletedPage } from '@/api/sys/WFTask'
import { Tag, Switch } from 'ant-design-vue';
import { getDetail } from '@/api/sys/WFSchemeInfo'
import { Tag } from 'ant-design-vue';
import { flowStore } from '@/store/modules/flow';
const flowWfDataStore = flowStore();
const searchInfo = reactive < Recordable > ({});
import { useGo } from '@/hooks/web/usePage';
const go = useGo();
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
const [registerTable] = useTable({
api: getLoadMyUncompletedPage,
columns: [
{
@ -45,7 +48,7 @@
width: 80,
customRender: ({ record }) => {
if (record.isUrge == '1') {
const color = 'ref';
const color = 'red';
const text = '催办';
return h(Tag, { color: color }, () => text);
} else {
@ -102,8 +105,12 @@
// slots: { customRender: 'action' },
},
});
function handleDetail(record){
go('/dashboard/task_audit_preview/detail?processId=' + record.processId+"&taskId="+record.id);
async function handleDetail(record) {
let data = await getDetail({ code: record.processCode })
let scheme = JSON.parse(data.scheme.content);
let wfData = scheme.wfData
flowWfDataStore.setWfDataAll(wfData)
go('/dashboard/task_audit_preview/detail?processId=' + record.processId + "&taskId=" + record.id+"&type="+record.type);
}