first commit

This commit is contained in:
2026-01-08 14:58:16 +08:00
commit 556e5d64aa
9575 changed files with 1621095 additions and 0 deletions
@@ -0,0 +1,350 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<title>流程设计器</title>
<script src="/assets/platform/plugins/vue/vue.js"></script>
<script src="/assets/platform/plugins/jquery/jquery.js"></script>
<script src="/assets/platform/plugins/element-ui/lib/index.js"></script>
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/index.css"/>
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/index.css"/>
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/override.css"/>
<!-- 引入 core 包和对应 css-->
<script src="/assets/platform/plugins/logicflow/logic-flow.js"></script>
<link rel="stylesheet" href="/assets/platform/plugins/logicflow/index.css"/>
<script src="https://cdn.jsdelivr.net/npm/@logicflow/extension@2.1.4/dist/index.min.js"></script>
<script src="/assets/platform/plugins/snaker/SnakerflowDesigner.umd.js"></script>
<style>
#snaker-flow-preview {
height: 100vh;
}
.approval-card {
position: absolute;
width: 320px;
background: #ffffff;
border-radius: 8px;
border: 1px solid #d9e3f0;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
z-index: 1000;
font-family: "Microsoft YaHei", "PingFang SC", sans-serif;
transform: translate(10px, 10px);
overflow: hidden;
}
.tab-container {
border-bottom: 1px solid #e8e8e8;
}
.tab-header {
display: flex;
background: #fafafa;
}
.tab-item {
padding: 8px 16px;
cursor: pointer;
border-right: 1px solid #e8e8e8;
font-size: 12px;
color: #666;
background: #fafafa;
transition: all 0.2s;
}
.tab-item:last-child {
border-right: none;
}
.tab-item.active {
background: #fff;
color: #333;
border-bottom: 2px solid #1890ff;
margin-bottom: -1px;
}
.tab-item:hover {
background: #f0f0f0;
color: #333;
}
/* 卡片标题栏(OA风格顶部色条) */
.approval-card .card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
background: #1a73e8;
color: white;
}
.approval-card .card-header h3 {
margin: 0;
font-size: 15px;
font-weight: 500;
letter-spacing: 0.5px;
}
.approval-card .card-header button {
background: rgba(255, 255, 255, 0.2);
border: none;
width: 24px;
height: 24px;
border-radius: 50%;
color: white;
font-size: 16px;
line-height: 1;
cursor: pointer;
transition: all 0.2s;
}
.approval-card .card-header button:hover {
background: rgba(255, 255, 255, 0.3);
}
/* 卡片内容区域 */
.approval-card .card-body {
padding: 16px;
}
/* 信息行样式 */
.approval-card .info-row {
display: flex;
margin-bottom: 12px;
align-items: flex-start;
}
.approval-card .info-label {
width: 80px;
color: #666;
font-size: 13px;
line-height: 1.5;
}
.approval-card .info-value {
flex: 1;
color: #333;
font-size: 13px;
line-height: 1.5;
word-break: break-all;
}
/*!* 分隔线 *!*/
/*.approval-card .divider {*/
/* height: 1px;*/
/* background: #f0f0f0;*/
/* margin: 12px 0;*/
/*}*/
</style>
</head>
<body>
<div id="snaker-flow-preview">
<snaker-flow-designer
ref="designer"
v-model="flowData"
:show-doc="false"
:viewer="true"
node-render-type="html"
:high-light="highLight"
></snaker-flow-designer>
<div
v-if="showApprovalCard"
class="approval-card"
:style="{
left: cardPosition.x+'px',
top: cardPosition.y+'px'
}"
>
<div class="card-header">
<h3>详情</h3>
<button @click="closeCard">×</button>
</div>
<!-- Tab切换 -->
<div class="tab-container" v-if="approvalInfos.length > 1">
<div class="tab-header">
<div
v-for="(item, index) in approvalInfos"
:key="index"
class="tab-item"
:class="{active: activeTabIndex === index}"
@click="activeTabIndex = index"
>
记录{{index + 1}}
</div>
</div>
</div>
<div class="card-body">
<div v-for="(approvalInfo, index) in approvalInfos" :key="index" v-show="activeTabIndex === index">
<div class="info-row">
<span class="info-label">节点类型:</span>
<span class="info-value">{{approvalInfo.displayName}}</span>
</div>
<div class="info-row">
<span class="info-label">审批人:</span>
<span class="info-value" v-if="currentNode.id === 'startTask'">
{{approvalInfo.ext?.initiatorName}}({{approvalInfo.ext?.initiatorAccount}})
</span>
<span class="info-value"
v-else>{{approvalInfo.taskFormData.userName}}({{approvalInfo.taskFormData?.loginName}})</span>
</div>
<div class="info-row">
<span class="info-label">审核状态:</span>
<span class="info-value">{{getTaskStateText(approvalInfo.taskState)}}</span>
</div>
<div class="info-row">
<span class="info-label">提交结果:</span>
<span class="info-value">{{getSubmitTypeText(approvalInfo.ext.submitType)}}</span>
</div>
<div class="info-row">
<span class="info-label">提交意见:</span>
<span class="info-value">{{approvalInfo.taskFormData.opinion}}</span>
</div>
<!-- <div class="divider"></div>-->
<div class="info-row">
<span class="info-label">提交时间:</span>
<span class="info-value">{{approvalInfo.finishTime}}</span>
</div>
</div>
</div>
</div>
</div>
</body>
<script nonce="${cspNonce!}">
Vue.use(SnakerflowDesigner.default)
const vue = new Vue({
el: "#snaker-flow-preview",
data() {
return {
// 流程定义ID
defineId: "${defineId!}",
// 流程实例ID
instanceId: "${instanceId!}",
// 流程定义数据
flowData: {},
// 高亮数据
highLight: {},
// 历史审批记录
hisApproval: [],
// 展示已审核信息
showApprovalCard: false,
// 审批信息卡片位置
cardPosition: {x: 0, y: 0},
// 当前节点
currentNode: [],
// 审批信息数组
approvalInfos: [],
// 当前选中的tab索引
activeTabIndex: 0
}
},
computed: {
// approvalInfo() {
// if (this.currentNode) {
// return this.hisApproval.find((item) => item.taskName === this.currentNode.id)
// }
// }
},
methods: {
getDetail() {
$.get("/flow/define/detail", {id: this.defineId}).then((res) => {
if (res.code === 0) {
this.flowData = res.data.content
this.initNodeEvent()
}
})
},
getHighLight() {
$.get("/flow/common/instanceHighLight", {instanceId: this.instanceId}).then((res) => {
if (res.code === 0) {
this.highLight = res.data
}
})
},
getHisApproval() {
$.get("/flow/common/approvalRecord", {instanceId: this.instanceId}).then((res) => {
if (res.code === 0) {
this.hisApproval = res.data
}
})
},
initNodeEvent() {
this.$nextTick(() => {
console.log(this.$refs.designer.lf.graphModel.eventCenter)
this.$refs.designer.lf.graphModel.eventCenter.on("node:click", ({e, data}) => {
console.log(data)
console.log(e)
// 获取点击位置(考虑页面滚动情况)
const scrollX = window.scrollX || window.pageXOffset
const scrollY = window.scrollY || window.pageYOffset
this.cardPosition = {
x: e.clientX + scrollX,
y: e.clientY + scrollY
}
if (data.type !== "snaker:task") return
const approvalInfos = this.hisApproval.filter((item) => item.taskName === data.id && item.taskState === 20)
if (approvalInfos && approvalInfos.length > 0) {
this.approvalInfos = approvalInfos
this.currentNode = data
this.activeTabIndex = 0
this.showApprovalCard = true
}
})
this.$refs.designer.lf.graphModel.eventCenter.on("blank:click", (args) => {
this.closeCard()
})
})
},
closeCard() {
this.showApprovalCard = false
this.activeTabIndex = 0
},
// 获取任务状态文本
getTaskStateText(taskState) {
const stateMap = {
10: "进行中",
20: "已完成",
30: "已撤回"
}
return stateMap[taskState] || taskState
},
// 获取提交结果文本
getSubmitTypeText(submitType) {
const typeMap = {
0: "发起申请",
1: "同意申请",
2: "拒绝申请",
3: "退回上一步",
4: "跳转",
5: "重新提交",
6: "退回发起人",
20: "拒绝申请"
}
return typeMap[submitType] || submitType
}
},
mounted() {
if (this.defineId) {
this.getDetail()
}
if (this.instanceId) {
this.getHighLight()
this.getHisApproval()
}
}
})
</script>
</html>