Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
37964e74
authored
Jan 16, 2025
by
Lesan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 审批签名代码评审
parent
8e5271a6
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
42 additions
and
44 deletions
+42
-44
src/api/bpm/processInstance/index.ts
+1
-1
src/utils/download.ts
+27
-0
src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue
+8
-8
src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue
+3
-3
src/views/bpm/processInstance/detail/SignDialog.vue
+3
-32
No files found.
src/api/bpm/processInstance/index.ts
View file @
37964e74
...
@@ -36,7 +36,7 @@ export type ApprovalTaskInfo = {
...
@@ -36,7 +36,7 @@ export type ApprovalTaskInfo = {
assigneeUser
:
User
assigneeUser
:
User
status
:
number
status
:
number
reason
:
string
reason
:
string
sign
:
string
// TODO @lesan:字段改成 signPicUrl 签名照片。只有 sign 感觉是签名文本哈。
sign
PicUrl
:
string
}
}
// 审批节点信息
// 审批节点信息
...
...
src/utils/download.ts
View file @
37964e74
...
@@ -65,6 +65,33 @@ const download = {
...
@@ -65,6 +65,33 @@ const download = {
a
.
download
=
'image.png'
a
.
download
=
'image.png'
a
.
click
()
a
.
click
()
}
}
},
base64ToFile
:
(
base64
,
fileName
)
=>
{
// 将base64按照 , 进行分割 将前缀 与后续内容分隔开
const
data
=
base64
.
split
(
','
)
// 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等)
const
type
=
data
[
0
].
match
(
/:
(
.*
?)
;/
)[
1
]
// 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp)
const
suffix
=
type
.
split
(
'/'
)[
1
]
// 使用atob()对base64数据进行解码 结果是一个文件数据流 以字符串的格式输出
const
bstr
=
window
.
atob
(
data
[
1
])
// 获取解码结果字符串的长度
let
n
=
bstr
.
length
// 根据解码结果字符串的长度创建一个等长的整形数字数组
// 但在创建时 所有元素初始值都为 0
const
u8arr
=
new
Uint8Array
(
n
)
// 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元
while
(
n
--
)
{
// charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元
u8arr
[
n
]
=
bstr
.
charCodeAt
(
n
)
}
// 利用构造函数创建File文件对象
// new File(bits, name, options)
const
file
=
new
File
([
u8arr
],
`
${
fileName
}
.
${
suffix
}
`
,
{
type
:
type
})
// 将File文件对象返回给方法的调用者
return
file
}
}
}
}
...
...
src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue
View file @
37964e74
...
@@ -47,15 +47,15 @@
...
@@ -47,15 +47,15 @@
<el-form-item
<el-form-item
v-if=
"runningTask.signEnable"
v-if=
"runningTask.signEnable"
label=
"签名"
label=
"签名"
prop=
"sign"
prop=
"sign
PicUrl
"
ref=
"approveSignFormRef"
ref=
"approveSignFormRef"
>
>
<el-button
@
click=
"signRef.open()"
>
点击签名
</el-button>
<el-button
@
click=
"signRef.open()"
>
点击签名
</el-button>
<el-image
<el-image
class=
"w-90px h-40px ml-5px"
class=
"w-90px h-40px ml-5px"
v-if=
"approveReasonForm.sign"
v-if=
"approveReasonForm.sign
PicUrl
"
:src=
"approveReasonForm.sign"
:src=
"approveReasonForm.sign
PicUrl
"
:preview-src-list=
"[approveReasonForm.sign]"
:preview-src-list=
"[approveReasonForm.sign
PicUrl
]"
/>
/>
</el-form-item>
</el-form-item>
<el-form-item>
<el-form-item>
...
@@ -553,11 +553,11 @@ const signRef = ref()
...
@@ -553,11 +553,11 @@ const signRef = ref()
const
approveSignFormRef
=
ref
()
const
approveSignFormRef
=
ref
()
const
approveReasonForm
=
reactive
({
const
approveReasonForm
=
reactive
({
reason
:
''
,
reason
:
''
,
sign
:
''
sign
PicUrl
:
''
})
})
const
approveReasonRule
=
reactive
<
FormRules
<
typeof
approveReasonForm
>>
({
const
approveReasonRule
=
reactive
<
FormRules
<
typeof
approveReasonForm
>>
({
reason
:
[{
required
:
true
,
message
:
'审批意见不能为空'
,
trigger
:
'blur'
}],
reason
:
[{
required
:
true
,
message
:
'审批意见不能为空'
,
trigger
:
'blur'
}],
sign
:
[{
required
:
true
,
message
:
'签名不能为空'
,
trigger
:
'change'
}]
sign
PicUrl
:
[{
required
:
true
,
message
:
'签名不能为空'
,
trigger
:
'change'
}]
})
})
// 拒绝表单
// 拒绝表单
const
rejectFormRef
=
ref
<
FormInstance
>
()
const
rejectFormRef
=
ref
<
FormInstance
>
()
...
@@ -705,7 +705,7 @@ const handleAudit = async (pass: boolean, formRef: FormInstance | undefined) =>
...
@@ -705,7 +705,7 @@ const handleAudit = async (pass: boolean, formRef: FormInstance | undefined) =>
}
}
// 签名
// 签名
if
(
runningTask
.
value
.
signEnable
)
{
if
(
runningTask
.
value
.
signEnable
)
{
data
.
sign
=
approveReasonForm
.
sign
data
.
sign
PicUrl
=
approveReasonForm
.
signPicUrl
}
}
// 多表单处理,并且有额外的 approveForm 表单,需要校验 + 拼接到 data 表单里提交
// 多表单处理,并且有额外的 approveForm 表单,需要校验 + 拼接到 data 表单里提交
// TODO 芋艿 任务有多表单这里要如何处理,会和可编辑的字段冲突
// TODO 芋艿 任务有多表单这里要如何处理,会和可编辑的字段冲突
...
@@ -1002,7 +1002,7 @@ const getUpdatedProcessInstanceVariables = () => {
...
@@ -1002,7 +1002,7 @@ const getUpdatedProcessInstanceVariables = () => {
/** 处理签名完成 */
/** 处理签名完成 */
const
handleSignFinish
=
(
url
:
string
)
=>
{
const
handleSignFinish
=
(
url
:
string
)
=>
{
approveReasonForm
.
sign
=
url
approveReasonForm
.
sign
PicUrl
=
url
approveSignFormRef
.
value
.
validate
(
'change'
)
approveSignFormRef
.
value
.
validate
(
'change'
)
}
}
...
...
src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue
View file @
37964e74
...
@@ -124,14 +124,14 @@
...
@@ -124,14 +124,14 @@
审批意见:{{ task.reason }}
审批意见:{{ task.reason }}
</div>
</div>
<div
<div
v-if=
"task.sign && activity.nodeType === NodeType.USER_TASK_NODE"
v-if=
"task.sign
PicUrl
&& activity.nodeType === NodeType.USER_TASK_NODE"
class=
"text-#a5a5a5 text-13px mt-1 w-full bg-#f8f8fa p2 rounded-md"
class=
"text-#a5a5a5 text-13px mt-1 w-full bg-#f8f8fa p2 rounded-md"
>
>
签名:
签名:
<el-image
<el-image
class=
"w-90px h-40px ml-5px"
class=
"w-90px h-40px ml-5px"
:src=
"task.sign"
:src=
"task.sign
PicUrl
"
:preview-src-list=
"[task.sign]"
:preview-src-list=
"[task.sign
PicUrl
]"
/>
/>
</div>
</div>
</teleport>
</teleport>
...
...
src/views/bpm/processInstance/detail/SignDialog.vue
View file @
37964e74
...
@@ -2,9 +2,8 @@
...
@@ -2,9 +2,8 @@
<el-dialog
v-model=
"signDialogVisible"
title=
"签名"
width=
"935"
>
<el-dialog
v-model=
"signDialogVisible"
title=
"签名"
width=
"935"
>
<div
class=
"position-relative"
>
<div
class=
"position-relative"
>
<Vue3Signature
class=
"b b-solid b-gray"
ref=
"signature"
w=
"900px"
h=
"400px"
/>
<Vue3Signature
class=
"b b-solid b-gray"
ref=
"signature"
w=
"900px"
h=
"400px"
/>
<!-- @lesan:建议改成 unocss 哈 -->
<el-button
<el-button
style=
"position: absolute; bottom: 20px; right:
10px"
class=
"pos-absolute bottom-20px right-
10px"
type=
"primary"
type=
"primary"
text
text
size=
"small"
size=
"small"
...
@@ -26,6 +25,7 @@
...
@@ -26,6 +25,7 @@
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
Vue3Signature
from
'vue3-signature'
import
Vue3Signature
from
'vue3-signature'
import
*
as
FileApi
from
'@/api/infra/file'
import
*
as
FileApi
from
'@/api/infra/file'
import
download
from
'@/utils/download'
const
message
=
useMessage
()
// 消息弹窗
const
message
=
useMessage
()
// 消息弹窗
const
signDialogVisible
=
ref
(
false
)
const
signDialogVisible
=
ref
(
false
)
...
@@ -40,40 +40,11 @@ const emits = defineEmits(['success'])
...
@@ -40,40 +40,11 @@ const emits = defineEmits(['success'])
const
submit
=
async
()
=>
{
const
submit
=
async
()
=>
{
message
.
success
(
'签名上传中请稍等。。。'
)
message
.
success
(
'签名上传中请稍等。。。'
)
const
res
=
await
FileApi
.
updateFile
({
const
res
=
await
FileApi
.
updateFile
({
file
:
base64ToFile
(
signature
.
value
.
save
(
'image/png'
),
'签名'
)
file
:
download
.
base64ToFile
(
signature
.
value
.
save
(
'image/png'
),
'签名'
)
})
})
emits
(
'success'
,
res
.
data
)
emits
(
'success'
,
res
.
data
)
signDialogVisible
.
value
=
false
signDialogVisible
.
value
=
false
}
}
// TODO @lesan:这个要不抽到 download.js 里,让这个组件更简洁干净?
const
base64ToFile
=
(
base64
,
fileName
)
=>
{
// 将base64按照 , 进行分割 将前缀 与后续内容分隔开
let
data
=
base64
.
split
(
','
)
// 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等)
let
type
=
data
[
0
].
match
(
/:
(
.*
?)
;/
)[
1
]
// 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp)
let
suffix
=
type
.
split
(
'/'
)[
1
]
// 使用atob()对base64数据进行解码 结果是一个文件数据流 以字符串的格式输出
const
bstr
=
window
.
atob
(
data
[
1
])
// 获取解码结果字符串的长度
let
n
=
bstr
.
length
// 根据解码结果字符串的长度创建一个等长的整形数字数组
// 但在创建时 所有元素初始值都为 0
const
u8arr
=
new
Uint8Array
(
n
)
// 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元
while
(
n
--
)
{
// charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元
u8arr
[
n
]
=
bstr
.
charCodeAt
(
n
)
}
// 利用构造函数创建File文件对象
// new File(bits, name, options)
const
file
=
new
File
([
u8arr
],
`
${
fileName
}
.
${
suffix
}
`
,
{
type
:
type
})
// 将File文件对象返回给方法的调用者
return
file
}
</
script
>
</
script
>
<
style
scoped
></
style
>
<
style
scoped
></
style
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment