ddy-process-h5
v1.0.1-rc.3.271
Published
> app端 流程插件
Readme
ddy-process-h5
App 端 流程、附件上传、附件列表、送审插件
bladex 新流程用法
第1步:安装新流程插件:npm install ddy-process-h5 -D
第2步:修改接口请求的文件,比如request.js,获取bladex的token
// request.js
import axios from 'axios';
import errorCode from './errorCode';
import { tansParams } from './top';
import JSONbig from "json-bigint";
import { checkIsAppleDevice ,checkIsHarmonyOS } from './common.js'
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8';
const opts = {
baseURL: '/' + process.env.VUE_APP_BASE_API,
timeout: 999999999,
errorTip: true,
transformResponse: [function (data) {
if (typeof data === 'string') {
try {
data = JSONbig.parse(data);
} catch (e) { console.log(e) }
}
return data;
}]
};
opts.headers = {
'X-Tag': process.env.VUE_APP_TAG
};
const service = axios.create(opts);
// 🆘获取bladex token
const loginByToken = (grant_type = 'top_token', Authorization = 'Basic c2FiZXIzOnNhYmVyM19zZWNyZXQ=') => {
return service({
url: '/bladex/blade-auth/oauth/token',
method: 'post',
headers: {
// 'blade-auth': '',
'Authorization': Authorization,
},
params: {
grant_type: grant_type,
top_token: uni.getStorageSync('token'),
},
});
}
service.interceptors.request.use(
async (config) => {
// const isToken = (config.headers || {}).isToken === false;
// if (getToken() && !isToken) {
// config.headers['Authorization'] = 'Bearer ' + getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
// }
let advice = ''
if (checkIsAppleDevice()) {
advice = 3;
} else if (checkIsHarmonyOS()) {
advice = 4;
} else {
advice = 2;
}
/* 请求之前拦截器。可以使用async await 做异步操作 */
let token = uni.getStorageSync('token');
console.log('token',token)
// 🆘bladex token接口,做一下拦截
if (config.url.includes('/blade-auth/oauth/token')) {
return config
}
if (config.url === '/auth/login') {
return config;
}
// 🆘非bladex接口,做一下拦截
// console.log(config.url, 'config', config.url.includes('/bladex/'))
if (!config.url.includes('/bladex/')) {
config.headers['advice'] = advice;
config.headers['Authorization'] = 'Bearer ' + token; // 让每个请求携带自定义token 请根据实际情况自行修改
config.headers['subjectId'] = uni.getStorageSync('subjectId')
config.errorTip = config.params?.errorTip != undefined || !config.data?.errorTip ? config.params?.errorTip || config.data?.errorTip : true
if (config.method === 'get' && config.params) {
let url = config.url + '?' + tansParams(config.params);
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
return config;
}
// 🆘新流程bladex的接口
const tokenv2 = localStorage.getItem('tokenv2');
// console.log(config.url, tokenv2, 'tokenv2')
config.headers['blade-requested-with'] = 'BladeHttpRequest'
config.headers['Authorization'] = 'Basic c2FiZXIzOnNhYmVyM19zZWNyZXQ='
if (false && tokenv2) {
config.headers['blade-auth'] = 'bearer ' + tokenv2;
} else {
const myToken = await loginByToken();
// console.log(myToken.access_token, 'my')
localStorage.setItem('tokenv2', (myToken || {}).access_token);
config.headers['blade-auth'] = 'bearer ' + myToken.access_token;
}
return config;
},
(error) => {
Promise.reject(error);
}
);
// 响应拦截器
service.interceptors.response.use(
(response) => {
if (Object.prototype.toString.call(response.data) === '[object Blob]') {
return response;
}
const { data, config } = response;
let code;
let success
// 🆘兼容bladex的返回结果,top-ui和bladex项目的返回结构不一致,需要处理
if (response.data.code) {
code = data.code
success = data.success
} else {
code = response.status
success = code == 200 ? true : false
}
const message = response.data.msg || errorCode[code] || errorCode['default'];
// 增加失败判断
data.fail = code !== 200 && success !== true;
if (code === 401) {
uni.showToast({
icon: 'none',
title: '请退出后重新打开'
});
return data;
} else if (code !== 200 && code !== '0' && config.errorTip) {
uni.showToast({
icon: 'none',
title: message
});
return data;
}
return data;
},
(error) => {
let { message, response } = error;
// 🆘bladex错误拦截处理,top-ui和bladex项目的返回结构不一致,需要处理
if (response && response.data && (response.data.message || response.data.msg)) {
message = response.data.message || response.data.msg
} else if (message === 'Network Error') {
message = '后端接口连接异常';
} else if (message.includes('timeout')) {
message = '系统接口请求超时';
} else if (message.includes('Request failed with status code')) {
message = '系统接口' + message.substr(message.length - 3) + '异常';
}
uni.showToast({
icon: 'none',
title: message
});
// if (config.errorTip) {
// Message({
// message: message,
// type: 'error',
// duration: 5 * 1000
// });
// }
return Promise.reject(error);
}
);
export default service;
第3步:引入组件,对于发起和审批流程,应该也和以前一致,只需要替换包名即可
<template>
<TopProcess
:processInstId="formData.processInstId"
:processDefId="formData.processDefId"
:formData="formData"
:appId="appId"
:uid="formData.uid"
:request="request"
:tapList="tapList"
:endFunction="endFunction"
:beforeFunction="beforeFunction"
:restartData="restartData"
:selfBtn="selfBtn"
:isQuickReply="true"
:isMsg="true"
:isView="false"
:isRequire="true"
>
<!-- :isDocument="true" -->
<!-- :isAdditional="true" -->
<!-- :getVars="getVars" -->
<template #default>
<div>
<!-- 操作按钮 -->
<button @click="onSubmit" class="btns-common cmf-btn">提交</button>
<TopSumbitPopup :visible.sync="actionVisible" ref="actionPop" :request="request" :businessSubjectId="formData.subjectId" :businessDeptId="formData.deptId"
appId="com.awspaas.user.apps.leave" :id="processBusinessKey" :businessType="businessType" :isSelectFirst="false"
:todoParameter="todoParameter" :title="title" :resubmit="resubmit" :extraParams="{...formData, ...vars, businessDeptId: formData.deptId}"
:beforeFunction="saveFn" :manual="true" @successFn="back"></TopSumbitPopup>
</div>
</template>
<template #attch>attch</template>
<template #fsList>fsList</template>
<template #documentPage>documentPage</template>
<!-- <template #completeSlot>completeSlot</template> -->
<template v-slot:btn="data">
<div>123{{ data.data.status }}</div>
</template>
</TopProcess>
</template>
<script>
import { TopProcess, TopSumbitPopup } from "@/packages/index.js";
import request from "@/assets/js/request";
import { defineComponent } from "vue-demi";
import { setToken, setSubject, setProject } from "@/assets/js/auth";
// import departPerson from "@/packages/checked-pick-app";
// import { TopProcess } from "ddy-process-h5";
export default {
data() {
return {
// http://localhost:1027/#/pages/apply/ask-for-leave/process?token=536d5915-762c-4689-81b6-78c6291799b3&subjectId=9f13a9c9c400fa6e6228848ce1f131ee&bizId=70364f045d17457f8145841da5d4a63c
actionVisible: false,
businessType: '9',
processBusinessKey: '',
todoParameter: {},
title: '请假申请',
// 是否重新提交
resubmit: false,
vars: {
title: '陈松松' + '发起了日常请假,请你审批',
name: '请假申请',
businessType: '9',
deptId: '',
},
formData: {
deptId: '',
businessKey: "74efb9a48dc176806e1185b8ce9845e8",
processInstId: "bladex-ad12dd3e-7757-11f0-97a7-000c291b8d5e",
processDefId: "obj_5402fe691cad48b3ae39da0699d53be1",
title: "测试",
subjectId: "3a4ef115e32c85a78239e3f5f76b9637",
tel: "15107910151",
userId: "8c7d012761a680dff78b19e10e794c99",
userName: "刘博文",
uid: "3712fea770669effdf95ac56c6f1f846",
},
appId: "com.awspaas.user.apps.recevie.document",
isView: false,
info: {},
bizId: "",
style: {
color: "#333",
disableColor: "#F7F6F6",
},
param: {
realStartTime: "",
realEndTime: "",
estimateHours: 0,
estimateMinutes: 0,
},
realDays: "",
timeLoading: false,
processIDS: "",
request: request,
// 选人组件
visible: false,
entity: {
source: "0",
type: "5",
request: this.request, //'http://59.53.91.231:2100' 0002
businessId: "0003",
codeType: [1, 2, 3], // 可选类型 1-主体 2-部门 3-人员
multiple: true, // 是否多选
},
tapList: [
{
label: "附件",
key: "attch",
type: "slot",
sort: 2,
slot: "attch",
},
{
label: "分送记录",
key: "fsList",
type: "slot",
slot: "fsList",
},
{
label: "正文",
key: "documentPage",
type: "slot",
sort: 3,
slot: "documentPage",
},
],
restartData: {
businessType: "4",
title: "测试送审",
showType: "all",
processName: "",
},
selfBtn: [
{
name: "测试",
type: "danger",
click: () => {
},
},
{
name: "测试2",
type: "default",
click: () => {
},
},
],
userData: false,
};
},
components: {
TopSumbitPopup,
/* topProcess, */
TopProcess,
// departPerson,
},
onLoad(e) {
this.bizId = e.bizId;
this.getInfo();
this.processIDS = e.processId;
},
mounted() {
setToken("37538643-c934-4563-946f-d6dbc7f13388");
// 7369abf4-e2b4-44d0-87b2-7c46a444d3b5
// da6bab4f-fa42-4730-b0fe-c5e022123c0c
setSubject("9f13a9c9c400fa6e6228848ce1f131ee");
/* setProject("4b23dd7dcb9cf7cb548fbd087ce9d748"); */
console.log(this.request, 'res')
this.entity.request = this.request
},
methods: {
// 回调
handleCallback(data) {
console.log(data, 'data')
},
// 发起流程
onSubmit() {
this.actionVisible = true
},
// 保存
saveFn() {
// this.processBusinessKey = data.businessKey
// this.title = data.title
// this.businessType = data.businessType
this.$nextTick(() => {
this.$refs.actionPop.handleSongshen()
})
},
// 流程完成后 回调
back() {
console.log('back')
},
// 发起流程
getVars() {
return true;
},
endFunction(val) {
/* location.reload(); */
},
async beforeFunction() {
let res = await this.request.get("/app/user/info");
if (res.code === 200) {
return true
} else {
return false
}
// return false
},
},
};
</script>
<style lang="scss">
* {
margin: 0;
padding: 0;
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
width: 100vw;
height: 100vh;
}
.info-box {
background-color: #fff;
padding: 10px;
.info {
display: flex;
justify-content: space-between;
font-size: 14px;
margin-bottom: 10px;
b {
font-weight: 400;
color: #959595;
}
}
.time-info {
background-color: #f6f6f6;
padding: 10px;
border-radius: 10px;
margin-bottom: 10px;
div {
margin-bottom: 10px;
font-size: 14px;
display: flex;
justify-content: space-between;
i {
color: #000;
font-style: normal;
font-weight: bold;
}
em {
font-style: normal;
font-size: 12px;
color: #4e87d4;
}
}
}
}
::v-deep .uni-date-x--border {
border: none;
}
em {
font-style: normal;
font-size: 12px;
color: #4e87d4;
}
.ren-title {
font-weight: bold;
font-size: 16px;
margin-bottom: 18px;
}
</style>
安装
vue2.7 以上版本安装指令
npm i ddy-process-h5 -D
vue2.7 以下版本安装指令
npm i @vue/composition-api -D npm i ddy-process-h5 -D
使用
在需要使用的组件内引入
import {
TopProcess,
attchViews,
TopSumbitPopup,
ViewAttchList,
} from "ddy-process-h5";
export default {
components: { TopProcess, attchViews, TopSumbitPopup, ViewAttchList },
};<template>
<TopProcess
:processInstId="processInstId"
:processDefId="processDefId"
:formData="formData"
:isView="isView"
:userId="userId"
:request="request"
:tapList="tapList"
:selfTapList="selfTapList"
:endFunction="endFunction"
:isDocument="isDocument"
>
<slot></slot>
</TopProcess>
<attchViews
v-if="labels == '1'"
:limit="limit ? limit : -1"
:requires="requires"
:request="param.request"
:linkUrl="param.linkUrl"
@getValue="getValues"
/>
<ViewAttchList :inList="inList"></ViewAttchList>
<TopSumbitPopup
:visible="visible"
:request="request"
:appId="appId"
:resubmit="resubmit"
:id="businessKey"
:businessType="businessType"
:todoParameter="todoParameter"
:title="title"
@successFn="successFn"
:beforeFunction="beforeFunction"
></TopSumbitPopup>
</template>
<script>
import "ddy-process-h5/style.css";
import {
TopProcess,
attchViews,
TopSumbitPopup,
ViewAttchList,
} from "ddy-process-h5";
export default {
components: { TopProcess, attchViews, TopSumbitPopup, ViewAttchList },
data() {
return {
formData: {
businessKey: businessKey,
processInstId: processInstId,
processDefId: processDefId,
title: title,
subjectId: subjectId,
userId: userId,
userName: userName,
reason: reason,
meetingTheme: meetingTheme,
},
selfBtn: [
{
name: "测试",
type: "danger",
click: () => {
console.log("当前::");
},
},
{
name: "测试2",
type: "default",
click: () => {
console.log("当前::");
},
},
],
};
},
methods: {
endFunction() {
console.log("endFunction");
},
beforeFunction() {
console.log("beforeFunction");
},
},
};
</script>属性-Attributes (TopProcess)
| 参数 | 类型 | 默认值 | 说明 | | -------------- | -------- | ----------------- | --------------------------------------------------- | | tapList | Array | [] | tab 节点插入、自定义附件等信息 | | selfTapList | Array | [] | 自定义 tab 节点,传入后覆盖原本参数 | | request | Object | null | axios 接口请求方法 [需要包含 get post 请求方式] | | processInstId | String | '' | 流程实例 ID [必填] | | formData | Object | {} | 集合数据 内部存储流程相关信息 businessKey[必填] | | isAdditional | boolean | false | 自定义按钮开关 开启后可使用按钮插槽 | | getVars | Function | null | 业务方法 | | endFunction | Function | null | 弹窗结束后执行方法 | | beforeFunction | Function | null | 弹窗开启前执行方法 | | restartData | Object | null | 重新提交参数 | | isDocument | Boolean | false | 公文独立配置 | | selfList | Array | {id,name} | 自定义流程列表 | | selfBtn | Array | {name,type,click} | 自定义流程按钮(查看案例 data) | | uid | String | "" | 炎黄 uid 若业务流程不需要催办,撤回,可以不使用该参数 | | isCheckType | String | "0" | 选人类型 传入后默认所有选人都为该类型 | | isMsg | Boolean | false | 意见是否展示 |
属性-Attributes (attchViews)
| 参数 | 类型 | 默认值 | 说明 | | -------- | ---------------- | ------ | ----------------------------------------------- | | request | Object | null | axios 接口请求方法 [需要包含 get post 请求方式] | | limit | [String, Number] | 4 | 最大上传数 | | getValue | Function | null | 返回上传数据 url | | requires | Boolean | false | 必填 | | inComing | Array | Array | 回显已上传列表 | | deletFn | Function | null | 组件本身提供静态删除功能,动态删除需传入相应方法 |
属性-Attributes (ViewAttchList)
| 参数 | 类型 | 默认值 | 说明 | | ------ | ----- | ------ | ------------ | | inList | Array | [] | 附件列表展示 |
属性-Attributes (TopSumbitPopup)
| 参数 | 类型 | 默认值 | 说明 | | -------------- | ---------------- | --------- | ----------------------------------------------- | | visible | Boolean | false | 展示参数 | | | title | String | "" | 送审提交标题参数 | | todoParameter | Object | {} | 发起流程时的其他参数 | | businessType | [String, Number] | null | 业务类型 | | id | String | "" | 业务 Id | | resubmit | Boolean | false | 是否为重新提交 | | request | Object | null | axios 接口请求方法 [需要包含 get post 请求方式] | | appId | String | '' | appId | | beforeFunction | Function | null | 提交前执行事件 | | successFn | Function | null | 成功后回调 | | manual | Boolean | false | 手动执行启动(ref 绑定后执行 handleSongshen()) | | selfList | Array | {id,name} | 自定义流程列表 | | isCheckType | String | "0" | 选人类型 uid |
tapList-对象说明
| 属性名 | 类型 | 说明 | | ------ | ------ | ---------------------------------------------------------------------------- | | label | String | 选项卡 title | | key | String | 选项卡 ID 请勿重复 defaultTabList 内已拥有的默认 key(a、b、c 为默认节点 key) | | type | String | 插槽类型 默认 default 插槽 slot | | slot | String | 插槽名 | | sort | Number | 排序参数,无参数默认插入末尾 |
selfTapList-对象说明 同上
formData-对象说明
| 属性名 | 类型 | 说明 | | ------------------------- | ------ | ------- | | businessKey | String | 业务 ID [必填] | | title reason meetingTheme | String | 标题 | | uid | String | 角色 id |
附件相关列表,参考 getValue 回调参数
restartData-对象说明
| 属性名 | 类型 | 说明 | | ------------ | ------ | -------------------- | | businessType | String | 业务 类型 | | showType | String | 流程类型(all,pc,app) | | processName | String | 流程查询字段 |
