初始提交
293
pages/workFlow/allAppWorkFlow/index.vue
Normal file
@@ -0,0 +1,293 @@
|
||||
<template>
|
||||
<view class="allApp-v">
|
||||
<view class="notice-warp">
|
||||
<view class="search-box">
|
||||
<u-search :placeholder="$t('app.apply.pleaseKeyword')" v-model="keyword" height="72"
|
||||
:show-action="false" @change="search" bg-color="#f0f2f6" shape="square">
|
||||
</u-search>
|
||||
</view>
|
||||
</view>
|
||||
<mescroll-uni ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption"
|
||||
:up="upOption" :bottombar="false" :sticky="false">
|
||||
<view>
|
||||
<view class="usualList">
|
||||
<view class=" caption u-m-b-20">常用流程</view>
|
||||
<view class="u-flex u-flex-wrap">
|
||||
<view class="item u-flex-col u-col-center" v-for="(item,i) in usualList" :key="i">
|
||||
<text class="u-font-40 item-icon" :class="item.icon"
|
||||
:style="{'background':item.iconBackground||'#008cff'}" @click="Jump(item)" />
|
||||
<text class="u-font-24 u-line-1 item-text">{{item.fullName}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<u-sticky>
|
||||
<CommonTabs :list="categoryList" @change="change" :current="current" ref="CommonTabs" isBoxShadow>
|
||||
</CommonTabs>
|
||||
</u-sticky>
|
||||
<view class="allList u-m-t-20" v-if="allList.length">
|
||||
<view v-for="(item,i) in allList" :key="i">
|
||||
<view class="u-flex childList-item ">
|
||||
<text class="u-font-40 item-icon" :class="item.icon"
|
||||
:style="{'background':item.iconBackground||'#008cff'}" @click="Jump(item)" />
|
||||
<text class="item-text u-m-l-28 u-m-r-28 u-line-2">{{item.fullName}}</text>
|
||||
<view class="btnBox">
|
||||
<u-button :custom-style="customStyle" @click="handelAdd(item)"
|
||||
v-if="!item.isCommonFlow">添加
|
||||
</u-button>
|
||||
<u-button :custom-style="customStyle" type="error" @click="handelDel(item)" v-else>
|
||||
移除
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<JnpfEmpty v-else />
|
||||
</view>
|
||||
</mescroll-uni>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
|
||||
import CommonTabs from '@/components/CommonTabs'
|
||||
import {
|
||||
getFlowList,
|
||||
getDataList,
|
||||
getFlowUsualList,
|
||||
setCommonFlow,
|
||||
delUsual
|
||||
} from '@/api/apply/apply.js'
|
||||
import resources from '@/libs/resources.js'
|
||||
export default {
|
||||
mixins: [MescrollMixin], // 使用mixin
|
||||
components: {
|
||||
CommonTabs
|
||||
},
|
||||
props: {
|
||||
categoryList: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
usualList: [],
|
||||
current: 0,
|
||||
customStyle: {
|
||||
width: "128rpx",
|
||||
fontSize: "24rpx",
|
||||
height: '60rpx'
|
||||
},
|
||||
downOption: {
|
||||
use: true,
|
||||
auto: true
|
||||
},
|
||||
upOption: {
|
||||
page: {
|
||||
num: 0,
|
||||
size: 20,
|
||||
time: null
|
||||
},
|
||||
empty: {
|
||||
use: false,
|
||||
icon: resources.message.nodata,
|
||||
tip: this.$t('common.noData'),
|
||||
fixed: true,
|
||||
top: "860rpx",
|
||||
},
|
||||
textNoMore: this.$t('app.apply.noMoreData'),
|
||||
},
|
||||
category: '',
|
||||
allList: [],
|
||||
type: '1',
|
||||
fullName: '',
|
||||
keyword: ''
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.userInfo = uni.getStorageSync('userInfo') || {}
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
search() {
|
||||
this.searchTimer && clearTimeout(this.searchTimer);
|
||||
this.searchTimer = setTimeout(() => {
|
||||
this.list = [];
|
||||
this.menuList = [];
|
||||
this.mescroll.resetUpScroll();
|
||||
}, 300);
|
||||
},
|
||||
init() {
|
||||
this.getFlowUsualList()
|
||||
},
|
||||
getFlowUsualList() {
|
||||
let query = {
|
||||
category: 'commonFlow',
|
||||
flowType: 0,
|
||||
systemId: this.userInfo.systemId
|
||||
}
|
||||
getFlowUsualList(query).then(res => {
|
||||
this.usualList = res.data.list.map(o => {
|
||||
const objectData = o.objectData ? JSON.parse(o.objectData) : {}
|
||||
return {
|
||||
...o,
|
||||
...objectData
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
upCallback(page) {
|
||||
let query = {
|
||||
currentPage: page.num,
|
||||
pageSize: page.size,
|
||||
category: this.category == 0 ? '' : this.category,
|
||||
flowType: 0,
|
||||
keyword: this.keyword,
|
||||
systemId: this.userInfo.systemId
|
||||
}
|
||||
getFlowList(query, {
|
||||
load: page.num == 1
|
||||
}).then(res => {
|
||||
this.mescroll.endSuccess(res.data.list.length);
|
||||
if (page.num == 1) this.allList = [];
|
||||
const list = res.data.list || [];
|
||||
this.allList = this.allList.concat(list);
|
||||
}).catch(() => {
|
||||
this.mescroll.endSuccess(0);
|
||||
this.mescroll.endErr();
|
||||
})
|
||||
},
|
||||
Jump(item) {
|
||||
const config = {
|
||||
id: "",
|
||||
flowId: item.id,
|
||||
opType: "-1",
|
||||
};
|
||||
uni.navigateTo({
|
||||
url: "/pages/workFlow/flowBefore/index?config=" +
|
||||
this.jnpf.base64.encode(JSON.stringify(config))
|
||||
});
|
||||
},
|
||||
handelAdd(item) {
|
||||
setCommonFlow(item.id).then(res => {
|
||||
this.usualList.push(item)
|
||||
item.isCommonFlow = true
|
||||
uni.$emit('updateUsualList')
|
||||
uni.showToast({
|
||||
title: res.msg
|
||||
})
|
||||
})
|
||||
},
|
||||
handelDel(item) {
|
||||
setCommonFlow(item.id).then(res => {
|
||||
item.isCommonFlow = false
|
||||
this.getFlowUsualList()
|
||||
uni.$emit('updateUsualList')
|
||||
uni.showToast({
|
||||
title: res.msg
|
||||
})
|
||||
})
|
||||
},
|
||||
change(index) {
|
||||
this.current = index;
|
||||
this.keyword = ""
|
||||
this.category = !this.categoryList[index].id ? '' : this.categoryList[index].id
|
||||
this.allList = [];
|
||||
this.mescroll.resetUpScroll()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f0f2f6;
|
||||
}
|
||||
|
||||
.allApp-v {
|
||||
.notice-warp {
|
||||
height: 114rpx;
|
||||
|
||||
.search-box {
|
||||
padding: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.caption {
|
||||
font-size: 36rpx;
|
||||
line-height: 80rpx;
|
||||
padding: 0 32rpx;
|
||||
|
||||
.tip {
|
||||
margin-left: 20rpx;
|
||||
font-size: 24rpx;
|
||||
color: #c6c6c6;
|
||||
}
|
||||
}
|
||||
|
||||
.tabs_box {
|
||||
width: 100%;
|
||||
|
||||
.sticky {
|
||||
width: 750rpx;
|
||||
height: 120rpx;
|
||||
color: #fff;
|
||||
padding-right: 32rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.usualList {
|
||||
margin-top: 4.2rem;
|
||||
margin-bottom: 20rpx;
|
||||
background-color: #FFFFFF;
|
||||
|
||||
.item {
|
||||
margin-bottom: 32rpx;
|
||||
width: 25%;
|
||||
|
||||
.item-icon {
|
||||
width: 88rpx;
|
||||
height: 88rpx;
|
||||
margin-bottom: 8rpx;
|
||||
line-height: 88rpx;
|
||||
text-align: center;
|
||||
border-radius: 30rpx;
|
||||
color: #fff;
|
||||
font-size: 40rpx;
|
||||
}
|
||||
|
||||
.item-text {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 0 16rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.allList {
|
||||
padding: 0rpx 32rpx 28rpx;
|
||||
background-color: #FFFFFF;
|
||||
|
||||
.childList-item {
|
||||
align-items: center;
|
||||
padding: 28rpx 0 0 0;
|
||||
|
||||
.item-text {
|
||||
width: calc(100% - 216rpx);
|
||||
}
|
||||
|
||||
.item-icon {
|
||||
width: 88rpx;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
text-align: center;
|
||||
border-radius: 30rpx;
|
||||
color: #FFFFFF;
|
||||
flex-shrink: 0;
|
||||
font-size: 40rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
165
pages/workFlow/assistantMsg/viewData.vue
Normal file
@@ -0,0 +1,165 @@
|
||||
<template>
|
||||
<view class="viewData-v">
|
||||
<view class="notice-warp">
|
||||
<view class="search-box">
|
||||
<u-search v-model="keyword" height="72" :show-action="false" @change="search" bg-color="#f0f2f6"
|
||||
shape="square">
|
||||
</u-search>
|
||||
</view>
|
||||
</view>
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :sticky="true"
|
||||
:down="downOption" :up="upOption" top="60">
|
||||
<view class="u-flex-col tableList">
|
||||
<view class="u-flex list-card" v-for="(item,index) in list" :key="index">
|
||||
<view class="u-flex-col fieldContent u-m-l-10">
|
||||
<view v-for="(column,c) in onLoadData.columnOptions" :key="c" class="fieldList u-line-1 u-flex">
|
||||
<view class="val" v-if="column.ifShow">{{column.label+':'}} {{item[column.value]}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</mescroll-body>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
getPopSelect
|
||||
} from '@/api/common.js'
|
||||
import resources from '@/libs/resources.js'
|
||||
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
|
||||
export default {
|
||||
mixins: [MescrollMixin],
|
||||
data() {
|
||||
return {
|
||||
downOption: {
|
||||
use: true,
|
||||
auto: true
|
||||
},
|
||||
upOption: {
|
||||
page: {
|
||||
num: 0,
|
||||
size: 20,
|
||||
time: null
|
||||
},
|
||||
empty: {
|
||||
use: true,
|
||||
icon: resources.message.nodata,
|
||||
tip: this.$t('common.noData'),
|
||||
fixed: true,
|
||||
top: "300rpx",
|
||||
},
|
||||
textNoMore: this.$t('app.apply.noMoreData'),
|
||||
},
|
||||
list: [],
|
||||
columnOptions: '',
|
||||
onLoadData: {},
|
||||
keyword: '',
|
||||
listQuery: {
|
||||
keyword: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
onLoad(e) {
|
||||
this.onLoadData = JSON.parse(decodeURIComponent(e.data));
|
||||
this.columnOptions = this.onLoadData.columnOptions.map(o => o.value).join(',')
|
||||
},
|
||||
methods: {
|
||||
upCallback(page) {
|
||||
const paramList = this.onLoadData.templateJson
|
||||
let query = {
|
||||
...this.listQuery,
|
||||
currentPage: page.num,
|
||||
pageSize: 20,
|
||||
interfaceId: this.onLoadData.interfaceId,
|
||||
columnOptions: this.columnOptions,
|
||||
paramList
|
||||
}
|
||||
getPopSelect(this.onLoadData.interfaceId, query, {
|
||||
load: page.num == 1
|
||||
}).then(res => {
|
||||
this.mescroll.endSuccess(res.data.list.length);
|
||||
if (page.num == 1) this.list = [];
|
||||
this.list = this.list.concat(res.data.list);
|
||||
}).catch(() => {
|
||||
this.mescroll.endErr();
|
||||
})
|
||||
},
|
||||
search() {
|
||||
// 节流,避免输入过快多次请求
|
||||
this.searchTimer && clearTimeout(this.searchTimer)
|
||||
this.searchTimer = setTimeout(() => {
|
||||
this.list = [];
|
||||
this.listQuery.keyword = this.keyword
|
||||
this.listQuery.currentPage = 1
|
||||
this.mescroll.resetUpScroll();
|
||||
}, 300)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f0f2f6;
|
||||
}
|
||||
|
||||
.viewData-v {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding-bottom: 106rpx;
|
||||
|
||||
|
||||
.notice-warp {
|
||||
height: 3.5rem;
|
||||
}
|
||||
|
||||
.tableList {
|
||||
padding: 0 20rpx;
|
||||
|
||||
.list-card {
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
border-radius: 8rpx;
|
||||
margin-top: 20rpx;
|
||||
padding: 20rpx 20rpx;
|
||||
|
||||
.fieldContent {
|
||||
width: 100%;
|
||||
margin-top: -14rpx;
|
||||
|
||||
.fieldList {
|
||||
// width: 752rpx;
|
||||
|
||||
.key {
|
||||
width: 136rpx;
|
||||
margin-right: 10rpx;
|
||||
text-align: right;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
line-height: 60rpx;
|
||||
}
|
||||
|
||||
.val {
|
||||
flex: 0.85;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nodata {
|
||||
margin-top: 258rpx;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 280rpx;
|
||||
height: 215rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
291
pages/workFlow/candiDateUserSelect/index.vue
Normal file
@@ -0,0 +1,291 @@
|
||||
<template>
|
||||
<view class="candidateForm-v">
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :sticky="true"
|
||||
:down="downOption" :up="upOption" :bottombar="false">
|
||||
<view class="treeSelect-search search-box_sticky">
|
||||
<u-search :placeholder="$t('app.apply.pleaseKeyword')" v-model="keyword" height="72"
|
||||
:show-action="false" @change="search" bg-color="#f0f2f6" shape="square">
|
||||
</u-search>
|
||||
<view class="alreadySelect">
|
||||
<view class="alreadySelect__box u-flex-col">
|
||||
<view class="alreadySelect_hd u-flex">
|
||||
<view>{{$t('component.jnpf.common.selected')}}</view>
|
||||
<view v-if="multiple" @click="setCheckAll" style="color: #2979ff;">
|
||||
{{$t('component.jnpf.common.clearAll')}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="select__box u-flex-col">
|
||||
<scroll-view scroll-y="true" style="max-height: 200px;">
|
||||
<view class="u-flex select__list">
|
||||
<view class="u-selectTag u-flex" v-for="(list,index) in selectList" :key="index">
|
||||
<view class="avatar">
|
||||
<u-avatar :src="baseURL+list.headIcon" mode="circle" size="mini">
|
||||
</u-avatar>
|
||||
</view>
|
||||
<view class="u-font-24 content">
|
||||
<view class="nameSty u-flex">
|
||||
<view class="nameUp">
|
||||
{{list.fullName}}
|
||||
</view>
|
||||
<u-icon name="close" class="close" @click='delSelect(index)'>
|
||||
</u-icon>
|
||||
</view>
|
||||
<view class="organizeSty">{{list.organize}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="listTitle">全部数据</view>
|
||||
</view>
|
||||
<view class="mescroll_body">
|
||||
<view style="" class="lists_box">
|
||||
<view class="list-cell-txt u-border-bottom" v-for="(list,index) in list" :key="index"
|
||||
@click="onSelect(list)">
|
||||
<view class="avatar">
|
||||
<u-avatar :src="baseURL+list.headIcon" mode="circle" size="default"></u-avatar>
|
||||
</view>
|
||||
<view class="u-font-30 content">
|
||||
<view class="nameSty">{{list.fullName}}</view>
|
||||
<view class="organizeSty">{{list.organize}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</mescroll-body>
|
||||
<!-- 底部按钮 -->
|
||||
<view class="flowBefore-actions">
|
||||
<u-button class="buttom-btn" @click="getResult('cancel')">{{$t('common.cancelText')}}</u-button>
|
||||
<u-button class="buttom-btn" type="primary"
|
||||
@click.stop="getResult('confirm')">{{$t('common.okText')}}</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
CandidateUser
|
||||
} from '@/api/workFlow/flowBefore'
|
||||
import resources from '@/libs/resources.js'
|
||||
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
|
||||
export default {
|
||||
mixins: [MescrollMixin],
|
||||
data() {
|
||||
return {
|
||||
downOption: {
|
||||
use: true,
|
||||
auto: true
|
||||
},
|
||||
upOption: {
|
||||
page: {
|
||||
num: 0,
|
||||
size: 20,
|
||||
time: null
|
||||
},
|
||||
empty: {
|
||||
use: true,
|
||||
icon: resources.message.nodata,
|
||||
tip: this.$t('common.noData'),
|
||||
fixed: true,
|
||||
top: "300rpx",
|
||||
},
|
||||
textNoMore: this.$t('app.apply.noMoreData'),
|
||||
},
|
||||
onLoadData: {},
|
||||
list: [],
|
||||
show: false,
|
||||
keyword: '',
|
||||
selectList: [],
|
||||
multiple: true
|
||||
}
|
||||
},
|
||||
onLoad(e) {
|
||||
this.show = true
|
||||
this.onLoadData = JSON.parse(decodeURIComponent(e.data));
|
||||
this.selectList = this.onLoadData.selectList
|
||||
this.delegateUser = this.onLoadData.delegateUser
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
upCallback(page) {
|
||||
let query = {
|
||||
currentPage: page.num,
|
||||
pageSize: page.size,
|
||||
keyword: this.keyword,
|
||||
...this.onLoadData.formData,
|
||||
nodeCode: this.onLoadData.nodeCode,
|
||||
delegateUser: this.delegateUser
|
||||
}
|
||||
CandidateUser(this.onLoadData.taskId || 0, query, {
|
||||
load: page.num == 1
|
||||
}).then(res => {
|
||||
this.mescroll.endSuccess(res.data.list.length);
|
||||
if (page.num == 1) this.list = [];
|
||||
const list = res.data.list;
|
||||
this.list = this.list.concat(list);
|
||||
}).catch(() => {
|
||||
this.mescroll.endErr();
|
||||
})
|
||||
},
|
||||
search() {
|
||||
// 节流,避免输入过快多次请求
|
||||
this.searchTimer && clearTimeout(this.searchTimer)
|
||||
this.searchTimer = setTimeout(() => {
|
||||
this.list = [];
|
||||
this.mescroll.resetUpScroll();
|
||||
}, 300)
|
||||
},
|
||||
onSelect(list) {
|
||||
let flag = false;
|
||||
for (let i = 0; i < this.selectList.length; i++) {
|
||||
if (this.selectList[i].id === list.id) {
|
||||
flag = true;
|
||||
return
|
||||
}
|
||||
};
|
||||
!flag && this.selectList.push(list)
|
||||
this.selectList = this.selectList.map(o => ({
|
||||
nodeCode: this.onLoadData.nodeCode,
|
||||
...o
|
||||
}))
|
||||
},
|
||||
delSelect(index) {
|
||||
this.selectList.splice(index, 1);
|
||||
},
|
||||
close() {
|
||||
this.list = []
|
||||
this.$emit('input', false);
|
||||
},
|
||||
getResult(type) {
|
||||
uni.$emit(type, this.selectList, this.onLoadData.nodeCode);
|
||||
uni.navigateBack()
|
||||
},
|
||||
setCheckAll() {
|
||||
this.selectList = []
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.candidateForm-v {
|
||||
padding-bottom: 88rpx;
|
||||
|
||||
.treeSelect-search {
|
||||
padding: 20rpx 30rpx 20rpx;
|
||||
|
||||
.alreadySelect {
|
||||
width: 100%;
|
||||
padding: 30rpx 0rpx 0;
|
||||
border-bottom: 1rpx solid #c0c4cc;
|
||||
|
||||
.alreadySelect__box {
|
||||
.alreadySelect_hd {
|
||||
width: 100%;
|
||||
height: 60rpx;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.select__box {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
|
||||
.select__list {
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.u-selectTag {
|
||||
width: 310rpx;
|
||||
border: 1px solid #2194fa;
|
||||
background-color: #e8f4fe;
|
||||
line-height: 40rpx;
|
||||
margin: 10rpx;
|
||||
padding-left: 10rpx;
|
||||
align-items: center;
|
||||
border-radius: 8rpx;
|
||||
|
||||
.content {
|
||||
width: 74%;
|
||||
margin-left: 10rpx;
|
||||
|
||||
.nameSty {
|
||||
color: #353535;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
||||
.nameUp {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.close {
|
||||
width: 26px;
|
||||
padding-right: 8rpx;
|
||||
justify-content: flex-end;
|
||||
color: #2194fa;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.organizeSty {
|
||||
color: #a0a1a1;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.u-size-default {
|
||||
padding: 6rpx 12rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.listTitle {
|
||||
// height: 100rpx;
|
||||
padding: 22rpx 0;
|
||||
font-size: 36rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.lists_box {
|
||||
height: 100%;
|
||||
|
||||
.list-cell-txt {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
padding: 20rpx 32rpx;
|
||||
overflow: hidden;
|
||||
color: $u-content-color;
|
||||
font-size: 28rpx;
|
||||
line-height: 24px;
|
||||
background-color: #fff;
|
||||
|
||||
.content {
|
||||
width: 85%;
|
||||
margin-left: 15rpx;
|
||||
|
||||
.nameSty {}
|
||||
|
||||
.organizeSty {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
400
pages/workFlow/comment/comment-file/index.vue
Normal file
@@ -0,0 +1,400 @@
|
||||
<template>
|
||||
<view class="jnpf-file">
|
||||
<view class="jnpf-file-box" :style="{textAlign:align}">
|
||||
<view v-if="!detailed &&!disabled " class="jnpf-file-box-line">
|
||||
<!-- #ifndef APP-HARMONY -->
|
||||
<CommentLsjUpload :ref="lsjUpload" :childId="childId" :width="width" :height="height" :option="option"
|
||||
:size="fileSize" :formats="getFormats" :instantly="instantly" @uploadEnd="onuploadEnd"
|
||||
:lsjUpload="lsjUpload" v-if="!disabled" :currentCount="currentCount">
|
||||
<view class="icon-ym icon-ym-comment-file" size="mini"></view>
|
||||
</CommentLsjUpload>
|
||||
<view class="icon-ym icon-ym-comment-file" size="mini" v-else @click="onCountOver"></view>
|
||||
<!-- #endif -->
|
||||
|
||||
|
||||
<!-- #ifdef APP-HARMONY -->
|
||||
<view @click="chooseFile">
|
||||
<view class="icon-ym icon-ym-comment-file" size="mini"></view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
</view>
|
||||
<view class="icon-ym icon-ym-comment-file" size="mini" v-if="disabled" @click="onCountOver"></view>
|
||||
<view class="tipText u-p-l-20">
|
||||
{{tipText}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CommentLsjUpload from './lsj-upload/lsj-upload.vue'
|
||||
|
||||
import {
|
||||
getDownloadUrl
|
||||
} from '@/api/common'
|
||||
import jnpf from '@/utils/jnpf'
|
||||
const units = {
|
||||
KB: 1024,
|
||||
MB: 1024 * 1024,
|
||||
GB: 1024 * 1024 * 1024,
|
||||
};
|
||||
const imgTypeList = ['png', 'jpg', 'jpeg', 'bmp', 'gif']
|
||||
export default {
|
||||
components: {
|
||||
CommentLsjUpload
|
||||
},
|
||||
name: 'jnpf-upload-img',
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: () => ([])
|
||||
},
|
||||
limit: {
|
||||
type: [Number, String],
|
||||
default: 9
|
||||
},
|
||||
fileSize: {
|
||||
type: Number,
|
||||
default: 10
|
||||
},
|
||||
sizeUnit: {
|
||||
type: String,
|
||||
default: 'MB'
|
||||
},
|
||||
accept: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
pathType: {
|
||||
type: String,
|
||||
default: 'defaultPath'
|
||||
},
|
||||
tipText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isAccount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
folder: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
vModel: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
detailed: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
align: {
|
||||
type: String,
|
||||
default: 'right'
|
||||
},
|
||||
currentCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
percent: '',
|
||||
fileList: [],
|
||||
// 上传接口参数
|
||||
option: {},
|
||||
params: {
|
||||
pathType: this.pathType,
|
||||
isAccount: this.isAccount,
|
||||
folder: this.folder
|
||||
},
|
||||
// 选择文件后是否立即自动上传,true=选择后立即上传
|
||||
instantly: true,
|
||||
size: 30,
|
||||
list: [],
|
||||
deletable: false,
|
||||
childId: 'upload' + this.$u.guid(3, false, 2),
|
||||
lsjUpload: 'lsjUpload' + this.$u.guid(3, false, 2),
|
||||
width: '48rpx',
|
||||
height: '48rpx',
|
||||
disabled: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
},
|
||||
comUploadUrl() {
|
||||
return this.define.comUploadUrl
|
||||
},
|
||||
getFormats() {
|
||||
let formats = this.accept
|
||||
formats = formats.replace("image/*", 'png,jpg,jpeg,bmp,gif,webp,psd,svg,tiff')
|
||||
formats = formats.replace("video/*", 'avi,wmv,mpg,mpeg,mov,rm,ram,swf,flv,mp4,wma,rm,rmvb,flv,mpg,mkv')
|
||||
formats = formats.replace("audio/*", 'mp3,wav,aif,midi,m4a')
|
||||
return formats
|
||||
},
|
||||
},
|
||||
created() {
|
||||
const token = uni.getStorageSync('token')
|
||||
this.option = {
|
||||
url: this.baseURL + '/api/file/Uploader/annex',
|
||||
name: 'file',
|
||||
header: {
|
||||
'Authorization': token,
|
||||
'uid': '27682',
|
||||
'client': 'app',
|
||||
'accountid': 'DP',
|
||||
},
|
||||
data: this.params
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
modelValue: {
|
||||
handler(val) {
|
||||
this.fileList = JSON.parse(JSON.stringify(val));
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 鸿蒙上传附件
|
||||
chooseFile() {
|
||||
if (this.limit === this.fileList.length) return this.toast(`只允许上传${this.limit}个文件`);
|
||||
uni.chooseFile({
|
||||
count: 1, //默认100
|
||||
success: (res) => {
|
||||
const tempFilePaths = res.tempFilePaths;
|
||||
const token = uni.getStorageSync('token')
|
||||
const file = res.tempFiles[0]
|
||||
// 限制文件大小
|
||||
if (file.size > units[this.sizeUnit] * Math.abs(this.fileSize)) {
|
||||
this.toast(`文件大小超过${this.fileSize}${this.sizeUnit}`)
|
||||
return;
|
||||
}
|
||||
uni.uploadFile({
|
||||
url: this.baseURL + '/api/file/Uploader/annex',
|
||||
filePath: tempFilePaths[0],
|
||||
name: 'file',
|
||||
formData: {
|
||||
...this.params,
|
||||
fileName: file.name
|
||||
},
|
||||
header: {
|
||||
'Authorization': token,
|
||||
'uid': '27682',
|
||||
'client': 'app',
|
||||
'accountid': 'DP',
|
||||
},
|
||||
success: (response) => {
|
||||
let item = JSON.parse(response.data)
|
||||
this.fileList.push({
|
||||
name: res.tempFiles[0].name,
|
||||
fileId: item.data.name,
|
||||
url: item.data.url,
|
||||
fileExtension: item.data.fileExtension,
|
||||
fileSize: item.data.fileSize
|
||||
})
|
||||
this.$emit('update:modelValue', this.fileList)
|
||||
this.$emit('change', this.fileList)
|
||||
this.$forceUpdate();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
onCountOver() {
|
||||
uni.showToast({
|
||||
title: `最多可以上传${this.limit}个文件`,
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
},
|
||||
// 某文件上传结束回调(成功失败都回调)
|
||||
onuploadEnd(item) {
|
||||
if (this.currentCount >= this.limit) {
|
||||
// this.disabled = true;
|
||||
return this.$u.toast('最多可以上传' + this.limit + '个文件')
|
||||
}
|
||||
if (item['responseText']) {
|
||||
let response = JSON.parse(item.responseText)
|
||||
let count = this.fileList.length
|
||||
if (count >= this.limit) {
|
||||
// this.disabled = true;
|
||||
return this.$u.toast('最多可以上传' + this.limit + '个文件')
|
||||
}
|
||||
if (response.code != 200) return this.$u.toast(response.msg)
|
||||
this.fileList.push({
|
||||
name: item.name,
|
||||
fileId: response.data.name,
|
||||
url: response.data.url,
|
||||
fileExtension: response.data.fileExtension,
|
||||
fileSize: response.data.fileSize
|
||||
})
|
||||
this.$emit('update:modelValue', this.fileList)
|
||||
this.$emit('change', this.fileList)
|
||||
}
|
||||
this.$forceUpdate();
|
||||
},
|
||||
downLoad(item) {
|
||||
if (item.fileExtension && imgTypeList.includes(item.fileExtension)) return this.previewImage(item)
|
||||
// #ifdef MP
|
||||
this.previewFile(item)
|
||||
// #endif
|
||||
// #ifndef MP
|
||||
getDownloadUrl('annex', item.fileId).then(res => {
|
||||
const fileUrl = this.baseURL + res.data.url + '&name=' + item.name;
|
||||
// #ifdef H5
|
||||
window.location.href = fileUrl;
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
this.downloadFile(res.data.url);
|
||||
// #endif
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
// 移除某个文件
|
||||
delFile(files) {
|
||||
this.fileList = files
|
||||
// if(this.fileList.length >= this.limit) {
|
||||
// this.disabled = true
|
||||
// }else{
|
||||
// this.disabled = false
|
||||
// }
|
||||
},
|
||||
previewFile(item) {
|
||||
let fileTypes = ['doc', 'xls', 'ppt', 'pdf', 'docx', 'xlsx', 'pptx']
|
||||
let url = item.url
|
||||
let fileType = url.split('.')[1]
|
||||
if (fileTypes.includes(fileType)) {
|
||||
uni.downloadFile({
|
||||
url: this.baseURL + url,
|
||||
success: (res) => {
|
||||
var filePath = res.tempFilePath;
|
||||
uni.openDocument({
|
||||
filePath: encodeURI(filePath),
|
||||
showMenu: true,
|
||||
fileType: fileType,
|
||||
success: (res) => {
|
||||
console.log('打开文档成功');
|
||||
},
|
||||
fail(err) {
|
||||
console.log('小程序', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.$u.toast(
|
||||
'该文件类型无法打开'
|
||||
)
|
||||
}
|
||||
},
|
||||
previewImage(item) {
|
||||
if (!item.url) return
|
||||
const url = jnpf.getAuthImgUrl(item.url)
|
||||
uni.previewImage({
|
||||
urls: [url],
|
||||
current: url,
|
||||
success: () => {},
|
||||
fail: () => {
|
||||
uni.showToast({
|
||||
title: '预览图片失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
downloadFile(url) {
|
||||
uni.downloadFile({
|
||||
url: this.baseURL + url,
|
||||
success: res => {
|
||||
if (res.statusCode === 200) {
|
||||
uni.saveFile({
|
||||
tempFilePath: res.tempFilePath,
|
||||
success: red => {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
mask: true,
|
||||
title: '文件已保存:' + red.savedFilePath, //保存路径
|
||||
duration: 3000,
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.openDocument({
|
||||
filePath: red.savedFilePath,
|
||||
success: ress => {},
|
||||
fail(err) {}
|
||||
});
|
||||
}, 500)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.icon-ym {
|
||||
font-size: 48rpx;
|
||||
}
|
||||
|
||||
.jnpf-file {
|
||||
width: 100%;
|
||||
|
||||
.jnpf-file-box {
|
||||
|
||||
.jnpf-file-box-line {
|
||||
height: 70rpx;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tipText {
|
||||
color: #606266;
|
||||
word-break: break-all;
|
||||
line-height: 48rpx;
|
||||
}
|
||||
|
||||
.jnpf-file-item {
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
|
||||
.jnpf-file-item-txt {
|
||||
width: 230rpx;
|
||||
flex: auto;
|
||||
}
|
||||
|
||||
.showLeft {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.closeBox {
|
||||
height: 60rpx;
|
||||
align-items: flex-end;
|
||||
justify-content: space-evenly;
|
||||
flex: 0.2;
|
||||
|
||||
.closeTxt {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #fa3534;
|
||||
color: #FFFFFF;
|
||||
font-size: 20rpx;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
432
pages/workFlow/comment/comment-file/lsj-upload/LsjFile.js
Normal file
@@ -0,0 +1,432 @@
|
||||
export class LsjFile {
|
||||
constructor(data) {
|
||||
this.dom = null;
|
||||
// files.type = waiting(等待上传)|| loading(上传中)|| success(成功) || fail(失败)
|
||||
this.files = new Map();
|
||||
this.debug = data.debug || false;
|
||||
this.id = data.id;
|
||||
this.width = data.width;
|
||||
this.height = data.height;
|
||||
this.option = data.option;
|
||||
this.instantly = data.instantly;
|
||||
this.prohibited = data.prohibited;
|
||||
this.onchange = data.onchange;
|
||||
this.onprogress = data.onprogress;
|
||||
this.uploadHandle = this._uploadHandle;
|
||||
// #ifdef MP-WEIXIN
|
||||
this.uploadHandle = this._uploadHandleWX;
|
||||
// #endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建File节点
|
||||
* @param {string}path webview地址
|
||||
*/
|
||||
create(path) {
|
||||
if (!this.dom) {
|
||||
// #ifdef H5
|
||||
let dom = document.createElement('input');
|
||||
dom.type = 'file'
|
||||
dom.value = ''
|
||||
dom.style.height = this.height
|
||||
dom.style.width = this.width
|
||||
dom.style.position = 'absolute'
|
||||
dom.style.top = 0
|
||||
dom.style.left = 0
|
||||
dom.style.right = 0
|
||||
dom.style.bottom = 0
|
||||
dom.style.opacity = 0
|
||||
dom.style.zIndex = 900
|
||||
dom.accept = this.prohibited.accept;
|
||||
if (this.prohibited.multiple) {
|
||||
dom.multiple = 'multiple';
|
||||
}
|
||||
dom.onchange = event => {
|
||||
for (let file of event.target.files) {
|
||||
if (this.files.size >= this.prohibited.count) {
|
||||
this.toast(`最多可以上传${this.prohibited.count}个文件`);
|
||||
this.dom.value = '';
|
||||
break;
|
||||
}
|
||||
this.addFile(file);
|
||||
}
|
||||
|
||||
this._uploadAfter();
|
||||
|
||||
this.dom.value = '';
|
||||
};
|
||||
this.dom = dom;
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
let styles = {
|
||||
top: '-200px',
|
||||
left: 0,
|
||||
width: '1px',
|
||||
height: '200px',
|
||||
background: 'transparent'
|
||||
};
|
||||
let extras = {
|
||||
debug: this.debug,
|
||||
instantly: this.instantly,
|
||||
prohibited: this.prohibited,
|
||||
}
|
||||
this.dom = plus.webview.create(path, this.id, styles, extras);
|
||||
this.setData(this.option);
|
||||
this._overrideUrlLoading();
|
||||
// #endif
|
||||
return this.dom;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置上传参数
|
||||
* @param {object|string}name 上传参数,支持a.b 和 a[b]
|
||||
*/
|
||||
setData() {
|
||||
let [name, value = ''] = arguments;
|
||||
if (typeof name === 'object') {
|
||||
Object.assign(this.option, name);
|
||||
} else {
|
||||
this._setValue(this.option, name, value);
|
||||
}
|
||||
|
||||
this.debug && console.log(JSON.stringify(this.option));
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
this.dom.evalJS(`vm.setData('${JSON.stringify(this.option)}')`);
|
||||
// #endif
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传
|
||||
* @param {string}name 文件名称
|
||||
*/
|
||||
async upload(name = '') {
|
||||
if (!this.option.url) {
|
||||
throw Error('未设置上传地址');
|
||||
}
|
||||
|
||||
// #ifndef APP-PLUS
|
||||
if (name && this.files.has(name)) {
|
||||
await this.uploadHandle(this.files.get(name));
|
||||
} else {
|
||||
for (let item of this.files.values()) {
|
||||
if (item.type === 'waiting' || item.type === 'fail') {
|
||||
await this.uploadHandle(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
this.dom && this.dom.evalJS(`vm.upload('${name}')`);
|
||||
// #endif
|
||||
}
|
||||
|
||||
// 选择文件change
|
||||
addFile(file, isCallChange) {
|
||||
|
||||
let name = file.name;
|
||||
this.debug && console.log('文件名称', name, '大小', file.size);
|
||||
|
||||
if (file) {
|
||||
// 限制文件格式
|
||||
let path = '';
|
||||
let suffix = name.substring(name.lastIndexOf(".") + 1).toLowerCase();
|
||||
let formats = this.prohibited.formats.toLowerCase();
|
||||
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
path = URL.createObjectURL(file);
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
path = file.path;
|
||||
// #endif
|
||||
if (formats && !formats.includes(suffix)) {
|
||||
this.toast(`不支持上传${suffix.toUpperCase()}格式文件`);
|
||||
return false;
|
||||
}
|
||||
// 限制文件大小
|
||||
if (file.size > 1024 * 1024 * Math.abs(this.prohibited.size)) {
|
||||
this.toast(`文件大小超过${this.prohibited.size}MB`)
|
||||
return false;
|
||||
}
|
||||
this.files.set(file.name, {
|
||||
file,
|
||||
path,
|
||||
name: file.name,
|
||||
size: file.size,
|
||||
progress: 0,
|
||||
type: 'waiting'
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除文件
|
||||
* @param {string}name 不传name默认移除所有文件,传入name移除指定name的文件
|
||||
*/
|
||||
clear(name = '') {
|
||||
// #ifdef APP-PLUS
|
||||
this.dom && this.dom.evalJS(`vm.clear('${name}')`);
|
||||
// #endif
|
||||
|
||||
if (!name) {
|
||||
this.files.clear();
|
||||
} else {
|
||||
this.files.delete(name);
|
||||
}
|
||||
return this.onchange(this.files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提示框
|
||||
* @param {string}msg 轻提示内容
|
||||
*/
|
||||
toast(msg) {
|
||||
uni.showToast({
|
||||
title: msg,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信小程序选择文件
|
||||
* @param {number}count 可选择文件数量
|
||||
*/
|
||||
chooseMessageFile(type, count) {
|
||||
wx.chooseMessageFile({
|
||||
count: count,
|
||||
type: type,
|
||||
success: ({
|
||||
tempFiles
|
||||
}) => {
|
||||
for (let file of tempFiles) {
|
||||
this.addFile(file);
|
||||
}
|
||||
this._uploadAfter();
|
||||
},
|
||||
fail: () => {
|
||||
this.toast(`打开失败`);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
_copyObject(obj) {
|
||||
if (typeof obj !== "undefined") {
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
} else {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动根据字符串路径设置对象中的值 支持.和[]
|
||||
* @param {Object} dataObj 数据源
|
||||
* @param {String} name 支持a.b 和 a[b]
|
||||
* @param {String} value 值
|
||||
* setValue(dataObj, name, value);
|
||||
*/
|
||||
_setValue(dataObj, name, value) {
|
||||
// 通过正则表达式 查找路径数据
|
||||
let dataValue;
|
||||
if (typeof value === "object") {
|
||||
dataValue = this._copyObject(value);
|
||||
} else {
|
||||
dataValue = value;
|
||||
}
|
||||
let regExp = new RegExp("([\\w$]+)|\\[(:\\d)\\]", "g");
|
||||
const patten = name.match(regExp);
|
||||
// 遍历路径 逐级查找 最后一级用于直接赋值
|
||||
for (let i = 0; i < patten.length - 1; i++) {
|
||||
let keyName = patten[i];
|
||||
if (typeof dataObj[keyName] !== "object") dataObj[keyName] = {};
|
||||
dataObj = dataObj[keyName];
|
||||
}
|
||||
// 最后一级
|
||||
dataObj[patten[patten.length - 1]] = dataValue;
|
||||
this.debug && console.log('参数更新后', JSON.stringify(this.option));
|
||||
}
|
||||
|
||||
_uploadAfter() {
|
||||
this.onchange(this.files);
|
||||
setTimeout(() => {
|
||||
this.instantly && this.upload();
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
_overrideUrlLoading() {
|
||||
this.dom.overrideUrlLoading({
|
||||
mode: 'reject'
|
||||
}, e => {
|
||||
let {
|
||||
retype,
|
||||
item,
|
||||
files,
|
||||
end
|
||||
} = this._getRequest(
|
||||
e.url
|
||||
);
|
||||
let _this = this;
|
||||
switch (retype) {
|
||||
case 'updateOption':
|
||||
this.dom.evalJS(`vm.setData('${JSON.stringify(_this.option)}')`);
|
||||
break
|
||||
case 'change':
|
||||
try {
|
||||
_this.files = new Map([..._this.files, ...JSON.parse(unescape(files))]);
|
||||
} catch (e) {
|
||||
return console.error('出错了,请检查代码')
|
||||
}
|
||||
_this.onchange(_this.files);
|
||||
break
|
||||
case 'progress':
|
||||
try {
|
||||
item = JSON.parse(unescape(item));
|
||||
} catch (e) {
|
||||
return console.error('出错了,请检查代码')
|
||||
}
|
||||
_this._changeFilesItem(item, end);
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
_getRequest(url) {
|
||||
let theRequest = new Object()
|
||||
let index = url.indexOf('?')
|
||||
if (index != -1) {
|
||||
let str = url.substring(index + 1)
|
||||
let strs = str.split('&')
|
||||
for (let i = 0; i < strs.length; i++) {
|
||||
theRequest[strs[i].split('=')[0]] = unescape(strs[i].split('=')[1])
|
||||
}
|
||||
}
|
||||
return theRequest
|
||||
}
|
||||
|
||||
_changeFilesItem(item, end = false) {
|
||||
this.debug && console.log('onprogress', JSON.stringify(item));
|
||||
this.onprogress(item, end);
|
||||
this.files.set(item.name, item);
|
||||
}
|
||||
|
||||
_uploadHandle(item) {
|
||||
item.type = 'loading';
|
||||
delete item.responseText;
|
||||
return new Promise((resolve, reject) => {
|
||||
this.debug && console.log('option', JSON.stringify(this.option));
|
||||
let {
|
||||
url,
|
||||
name,
|
||||
method = 'POST',
|
||||
header,
|
||||
formData,
|
||||
data
|
||||
} = this.option;
|
||||
let form = new FormData();
|
||||
for (let keys in formData) {
|
||||
form.append(keys, formData[keys])
|
||||
}
|
||||
for (let keys in data) {
|
||||
form.append(keys, data[keys])
|
||||
}
|
||||
form.append(name, item.file);
|
||||
let xmlRequest = new XMLHttpRequest();
|
||||
xmlRequest.open(method, url, true);
|
||||
for (let keys in header) {
|
||||
xmlRequest.setRequestHeader(keys, header[keys])
|
||||
}
|
||||
|
||||
xmlRequest.upload.addEventListener(
|
||||
'progress',
|
||||
event => {
|
||||
if (event.lengthComputable) {
|
||||
let progress = Math.ceil((event.loaded * 100) / event.total)
|
||||
if (progress <= 100) {
|
||||
item.progress = progress;
|
||||
this._changeFilesItem(item);
|
||||
}
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
xmlRequest.ontimeout = () => {
|
||||
console.error('请求超时')
|
||||
item.type = 'fail';
|
||||
this._changeFilesItem(item, true);
|
||||
return resolve(false);
|
||||
}
|
||||
|
||||
xmlRequest.onreadystatechange = ev => {
|
||||
if (xmlRequest.readyState == 4) {
|
||||
if (xmlRequest.status == 200) {
|
||||
this.debug && console.log('上传完成:' + xmlRequest.responseText)
|
||||
item['responseText'] = xmlRequest.responseText;
|
||||
item.type = 'success';
|
||||
this._changeFilesItem(item, true);
|
||||
return resolve(true);
|
||||
} else if (xmlRequest.status == 0) {
|
||||
console.error(
|
||||
'status = 0 :请检查请求头Content-Type与服务端是否匹配,服务端已正确开启跨域,并且nginx未拦截阻止请求')
|
||||
}
|
||||
console.error('--ERROR--:status = ' + xmlRequest.status)
|
||||
item.type = 'fail';
|
||||
this._changeFilesItem(item, true);
|
||||
return resolve(false);
|
||||
}
|
||||
}
|
||||
xmlRequest.send(form)
|
||||
});
|
||||
}
|
||||
|
||||
_uploadHandleWX(item) {
|
||||
item.type = 'loading';
|
||||
delete item.responseText;
|
||||
return new Promise((resolve, reject) => {
|
||||
this.debug && console.log('option', JSON.stringify(this.option));
|
||||
let form = {
|
||||
filePath: item.file.path,
|
||||
...this.option,
|
||||
formData: this.option.data || {},
|
||||
};
|
||||
form['fail'] = ({
|
||||
errMsg = ''
|
||||
}) => {
|
||||
console.error('--ERROR--:' + errMsg)
|
||||
item.type = 'fail';
|
||||
this._changeFilesItem(item, true);
|
||||
return resolve(false);
|
||||
}
|
||||
form['success'] = res => {
|
||||
if (res.statusCode == 200) {
|
||||
this.debug && console.log('上传完成,微信端返回不一定是字符串,根据接口返回格式判断是否需要JSON.parse:' + res.data)
|
||||
item['responseText'] = res.data;
|
||||
item.type = 'success';
|
||||
this._changeFilesItem(item, true);
|
||||
return resolve(true);
|
||||
}
|
||||
item.type = 'fail';
|
||||
this._changeFilesItem(item, true);
|
||||
return resolve(false);
|
||||
}
|
||||
|
||||
let xmlRequest = uni.uploadFile(form);
|
||||
xmlRequest.onProgressUpdate(({
|
||||
progress = 0
|
||||
}) => {
|
||||
if (progress <= 100) {
|
||||
item.progress = progress;
|
||||
this._changeFilesItem(item);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
399
pages/workFlow/comment/comment-file/lsj-upload/lsj-upload.vue
Normal file
@@ -0,0 +1,399 @@
|
||||
<template>
|
||||
<view class="lsj-file" :style="[getStyles]">
|
||||
<view ref="lsj" class="hFile" :style="[getStyles]" @click="onClick">
|
||||
<slot>
|
||||
<view class="defview" :style="[getStyles]">附件上传</view>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 查看文档:https://ext.dcloud.net.cn/plugin?id=5459
|
||||
import {
|
||||
LsjFile
|
||||
} from './LsjFile.js'
|
||||
export default {
|
||||
name: 'comment-Lsj-upload',
|
||||
props: {
|
||||
currentCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
// 打印日志
|
||||
debug: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 自动上传
|
||||
instantly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 上传接口参数设置
|
||||
option: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
// 文件大小上限
|
||||
size: {
|
||||
type: Number,
|
||||
default: 10
|
||||
},
|
||||
// 文件选择个数上限,超出后不触发点击
|
||||
count: {
|
||||
type: Number,
|
||||
default: 2000
|
||||
},
|
||||
// 是否允许多选文件
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 允许上传的文件格式(多个以逗号隔开)
|
||||
formats: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// input file选择限制
|
||||
accept: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 微信选择文件类型
|
||||
//all=从所有文件选择,
|
||||
//video=只能选择视频文件,
|
||||
//image=只能选择图片文件,
|
||||
//file=可以选择除了图片和视频之外的其它的文件
|
||||
wxFileType: {
|
||||
type: String,
|
||||
default: 'all'
|
||||
},
|
||||
// webviewID需唯一,不同窗口也不要同Id
|
||||
childId: {
|
||||
type: String,
|
||||
default: 'lsjUpload'
|
||||
},
|
||||
// 文件选择触发面宽度
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%'
|
||||
},
|
||||
// 文件选择触发面高度
|
||||
height: {
|
||||
type: String,
|
||||
default: '80rpx'
|
||||
},
|
||||
|
||||
// top,left,bottom,right仅position=absolute时才需要传入
|
||||
top: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
left: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
bottom: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
right: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// nvue不支持跟随窗口滚动
|
||||
position: {
|
||||
type: String,
|
||||
// #ifdef APP-NVUE
|
||||
default: 'absolute',
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
default: 'static',
|
||||
// #endif
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
option(v) {
|
||||
// #ifdef APP-PLUS
|
||||
this.lsjFile && this.show();
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
updated() {
|
||||
// #ifdef APP-PLUS
|
||||
if (this.isShow) {
|
||||
this.lsjFile && this.show();
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
computed: {
|
||||
getStyles() {
|
||||
let styles = {
|
||||
width: this.width,
|
||||
height: this.height
|
||||
}
|
||||
if (this.position == 'absolute') {
|
||||
styles['top'] = this.top
|
||||
styles['bottom'] = this.bottom
|
||||
styles['left'] = this.left
|
||||
styles['right'] = this.right
|
||||
styles['position'] = 'fixed'
|
||||
}
|
||||
|
||||
return styles
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this._size = 0;
|
||||
let WEBID = this.childId + new Date().getTime();
|
||||
this.lsjFile = new LsjFile({
|
||||
id: WEBID,
|
||||
debug: this.debug,
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
option: this.option,
|
||||
instantly: this.instantly,
|
||||
// 限制条件
|
||||
prohibited: {
|
||||
// 大小
|
||||
size: this.size,
|
||||
// 允许上传的格式
|
||||
formats: this.formats,
|
||||
// 限制选择的格式
|
||||
accept: this.accept,
|
||||
count: this.count,
|
||||
// 是否多选
|
||||
multiple: this.multiple,
|
||||
},
|
||||
onchange: this.onchange,
|
||||
onprogress: this.onprogress,
|
||||
});
|
||||
this.create();
|
||||
// 需判断是否当前页显示
|
||||
uni.$on('lsjShow', this.show);
|
||||
},
|
||||
beforeDestroy() {
|
||||
uni.$off('lsjShow', this.show);
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
this.lsjFile.dom.close();
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
setFiles(array) {
|
||||
if (array instanceof Map) {
|
||||
for (let [key, item] of array) {
|
||||
item['progress'] = 100;
|
||||
item['type'] = 'success';
|
||||
this.lsjFile.files.set(key, item);
|
||||
}
|
||||
} else if (Array.isArray(array)) {
|
||||
array.forEach(item => {
|
||||
if (item.name) {
|
||||
item['progress'] = 100;
|
||||
item['type'] = 'success';
|
||||
this.lsjFile.files.set(item.name, item);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.onchange(this.lsjFile.files);
|
||||
},
|
||||
setData() {
|
||||
this.lsjFile && this.lsjFile.setData(...arguments);
|
||||
},
|
||||
getDomStyles(callback) {
|
||||
// #ifndef APP-NVUE
|
||||
let view = uni
|
||||
.createSelectorQuery()
|
||||
.in(this)
|
||||
.select('.lsj-file')
|
||||
view.fields({
|
||||
size: true,
|
||||
rect: true
|
||||
},
|
||||
({
|
||||
height,
|
||||
width,
|
||||
top,
|
||||
left,
|
||||
right,
|
||||
bottom
|
||||
}) => {
|
||||
uni.createSelectorQuery()
|
||||
.selectViewport()
|
||||
.scrollOffset(({
|
||||
scrollTop
|
||||
}) => {
|
||||
return callback({
|
||||
top: parseInt(top) + parseInt(scrollTop) + 'px',
|
||||
left: parseInt(left) + 'px',
|
||||
width: parseInt(width) + 'px',
|
||||
height: parseInt(height) + 'px'
|
||||
})
|
||||
})
|
||||
.exec()
|
||||
}
|
||||
).exec()
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
const dom = weex.requireModule('dom')
|
||||
dom.getComponentRect(this.$refs.lsj, ({
|
||||
size: {
|
||||
height,
|
||||
width,
|
||||
top,
|
||||
left,
|
||||
right,
|
||||
bottom
|
||||
}
|
||||
}) => {
|
||||
return callback({
|
||||
top: parseInt(top) + 'px',
|
||||
left: parseInt(left) + 'px',
|
||||
width: parseInt(width) + 'px',
|
||||
height: parseInt(height) + 'px',
|
||||
right: parseInt(right) + 'px',
|
||||
bottom: parseInt(bottom) + 'px'
|
||||
})
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
show() {
|
||||
if (this._size && (this._size >= this.count)) {
|
||||
return;
|
||||
}
|
||||
this.isShow = true;
|
||||
// #ifdef APP-PLUS
|
||||
this.lsjFile && this.getDomStyles(styles => {
|
||||
this.lsjFile.dom.setStyle(styles)
|
||||
});
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
this.lsjFile.dom.style.display = 'inline'
|
||||
// #endif
|
||||
},
|
||||
hide() {
|
||||
this.isShow = false;
|
||||
// #ifdef APP-PLUS
|
||||
this.lsjFile && this.lsjFile.dom.setStyle({
|
||||
top: '-100px',
|
||||
left: '0px',
|
||||
width: '1px',
|
||||
height: '100px',
|
||||
});
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
this.lsjFile.dom.style.display = 'none'
|
||||
// #endif
|
||||
},
|
||||
/**
|
||||
* 手动提交上传
|
||||
* @param {string}name 文件名称,不传则上传所有type等于waiting和fail的文件
|
||||
*/
|
||||
upload(name) {
|
||||
this.lsjFile && this.lsjFile.upload(name);
|
||||
},
|
||||
/**
|
||||
* @returns {Map} 已选择的文件Map集
|
||||
*/
|
||||
onchange(files) {
|
||||
// this.$emit('change',files);
|
||||
this._size = files.size;
|
||||
return files.size >= this.count ? this.hide() : this.show();
|
||||
},
|
||||
/**
|
||||
* @returns {object} 当前上传中的对象
|
||||
*/
|
||||
onprogress(item, end = false) {
|
||||
this.$emit('progress', item);
|
||||
if (end) {
|
||||
setTimeout(() => {
|
||||
this.$emit('uploadEnd', item);
|
||||
}, 0);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 移除组件内缓存的某条数据
|
||||
* @param {string}name 文件名称,不指定默认清除所有文件
|
||||
*/
|
||||
clear(name) {
|
||||
this.lsjFile.clear(name);
|
||||
},
|
||||
// 创建选择器
|
||||
create() {
|
||||
// 若iOS端服务端处理不了跨域就将hybrid目录内的html放到服务端去,并将此处path改成服务器上的地址
|
||||
let path = '/uni_modules/lsj-upload/hybrid/html/uploadFile.html?sourceflag=comment';
|
||||
let dom = this.lsjFile.create(path);
|
||||
// #ifdef H5
|
||||
this.$refs.lsj.$el.appendChild(dom);
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
this.show();
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
dom.setStyle({
|
||||
position: this.position
|
||||
});
|
||||
dom.loadURL(path);
|
||||
setTimeout(() => {
|
||||
// #ifdef APP-NVUE
|
||||
plus.webview.currentWebview().append(dom);
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
this.$root.$scope.$getAppWebview().append(dom);
|
||||
// #endif
|
||||
this.show();
|
||||
}, 300)
|
||||
// #endif
|
||||
},
|
||||
// 点击选择附件
|
||||
onClick() {
|
||||
/*if (this.currentCount >= 9) {
|
||||
this.toast(`最多可以上传9个文件`);
|
||||
return;
|
||||
}*/
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
if (!this.isShow) {
|
||||
return;
|
||||
}
|
||||
let count = this.count - this._size;
|
||||
this.lsjFile.chooseMessageFile(this.wxFileType, count);
|
||||
// #endif
|
||||
},
|
||||
toast(msg) {
|
||||
uni.showToast({
|
||||
title: msg,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.lsj-file {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.defview {
|
||||
background-color: #007aff;
|
||||
color: #fff;
|
||||
border-radius: 10rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.hFile {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
340
pages/workFlow/comment/comment-user-select/index.vue
Normal file
@@ -0,0 +1,340 @@
|
||||
<template>
|
||||
<u-popup class="jnpf-tree-select-popup" :maskCloseAble="maskCloseAble" mode="right" v-model="showPopup"
|
||||
:safeAreaInsetBottom="safeAreaInsetBottom" @close="close" :z-index="uZIndex" width="100%">
|
||||
<view class="jnpf-tree-select-body">
|
||||
<view class="jnpf-tree-select-title">
|
||||
<text class="icon-ym icon-ym-report-icon-preview-pagePre u-font-40 backIcon" @tap="close"></text>
|
||||
<view class="title">选择用户</view>
|
||||
</view>
|
||||
<view class="jnpf-tree-select-search">
|
||||
<u-search :placeholder="$t('app.apply.pleaseKeyword')" v-model="keyword" height="72"
|
||||
:show-action="false" @change="search()" bg-color="#f0f2f6" shape="square">
|
||||
</u-search>
|
||||
</view>
|
||||
<view class="jnpf-tree-selected">
|
||||
<view class="jnpf-tree-selected-head">
|
||||
<view>{{$t('component.jnpf.common.selected')}}</view>
|
||||
<view v-if="multiple" class="clear-btn" @click="cleanAll">
|
||||
{{$t('component.jnpf.common.clearAll')}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="jnpf-tree-selected-box">
|
||||
<scroll-view scroll-y="true" style="max-height: 240rpx;">
|
||||
<view class="jnpf-tree-selected-list">
|
||||
<view class="u-selectTag" v-for="(list,index) in selectList" :key="index">
|
||||
<u-avatar class="avatar" :src="baseURL+list.headIcon" mode="circle"
|
||||
size="mini"></u-avatar>
|
||||
<view class="jnpf-tree-selected-content">
|
||||
<view class="name-box">
|
||||
<view class="name">{{list.fullName}}</view>
|
||||
<u-icon name="close" class="close" @click='delSelect(index)'></u-icon>
|
||||
</view>
|
||||
<view class="organize">{{list.organize}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="listTitle" v-if="selectType !== 'all'">全部数据</view>
|
||||
<view class="jnpf-tree-select-tree">
|
||||
<scroll-view class="scroll-view" :refresher-enabled="false" :refresher-threshold="100"
|
||||
:scroll-with-animation='true' :refresher-triggered="triggered" @scrolltolower="handleScrollToLower"
|
||||
:scroll-y="true">
|
||||
<view class="lists_box">
|
||||
<view class="list-cell-txt u-border-bottom" v-for="(list,index) in list" :key="index"
|
||||
@click="onSelect(list)">
|
||||
<u-avatar class="avatar" :src="baseURL+list.headIcon" mode="circle"
|
||||
size="default"></u-avatar>
|
||||
<view class="u-font-30 content">
|
||||
<view>{{list.fullName}}</view>
|
||||
<view class="organize">{{list.organize}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<JnpfEmpty v-if="list.length<1"></JnpfEmpty>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- 底部按钮 -->
|
||||
<view class="jnpf-tree-select-actions">
|
||||
<u-button class="buttom-btn" @click="close()">{{$t('common.cancelText')}}</u-button>
|
||||
<u-button class="buttom-btn" type="primary"
|
||||
@click.stop="handleConfirm">{{$t('common.okText')}}</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
<script>
|
||||
/**
|
||||
* tree-select 树形选择器
|
||||
* @property {Boolean} v-model 布尔值变量,用于控制选择器的弹出与收起
|
||||
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配(默认false)
|
||||
* @property {String} cancel-color 取消按钮的颜色(默认#606266)
|
||||
* @property {String} confirm-color 确认按钮的颜色(默认#2979ff)
|
||||
* @property {String} confirm-text 确认按钮的文字
|
||||
* @property {String} cancel-text 取消按钮的文字
|
||||
* @property {Boolean} mask-close-able 是否允许通过点击遮罩关闭Picker(默认true)
|
||||
* @property {String Number} z-index 弹出时的z-index值(默认10075)
|
||||
* @event {Function} confirm 点击确定按钮,返回当前选择的值
|
||||
*/
|
||||
const defaultProps = {
|
||||
label: 'fullName',
|
||||
value: 'id',
|
||||
icon: 'icon',
|
||||
children: 'children'
|
||||
}
|
||||
import {
|
||||
getTaskUserList
|
||||
} from '@/api/workFlow/flowBefore'
|
||||
export default {
|
||||
name: "comment-tree-select",
|
||||
props: {
|
||||
taskId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
selectType: {
|
||||
type: String,
|
||||
default: 'all'
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
query: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
selectedData: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
// 是否显示边框
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 通过双向绑定控制组件的弹出与收起
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// "取消"按钮的颜色
|
||||
cancelColor: {
|
||||
type: String,
|
||||
default: '#606266'
|
||||
},
|
||||
// "确定"按钮的颜色
|
||||
confirmColor: {
|
||||
type: String,
|
||||
default: '#2979ff'
|
||||
},
|
||||
// 弹出的z-index值
|
||||
zIndex: {
|
||||
type: [String, Number],
|
||||
default: 999
|
||||
},
|
||||
safeAreaInsetBottom: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否允许通过点击遮罩关闭Picker
|
||||
maskCloseAble: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
props: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
label: 'fullName',
|
||||
value: 'id',
|
||||
icon: 'icon',
|
||||
children: 'children',
|
||||
isLeaf: 'isLeaf'
|
||||
})
|
||||
},
|
||||
//多选
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 顶部标题
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 取消按钮的文字
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: '取消'
|
||||
},
|
||||
// 确认按钮的文字
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: '确认'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
triggered: false,
|
||||
selectList: [],
|
||||
keyword: '',
|
||||
current: 0,
|
||||
list: [],
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
pageSize: 20
|
||||
},
|
||||
total: 0,
|
||||
height: 0,
|
||||
showPopup: false
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
// 在select弹起的时候,重新初始化所有数据
|
||||
modelValue: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
this.showPopup = val
|
||||
if (val) setTimeout(() => this.getInfoList(), 10);
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
},
|
||||
uZIndex() {
|
||||
// 如果用户有传递z-index值,优先使用
|
||||
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
|
||||
},
|
||||
realProps() {
|
||||
return {
|
||||
...defaultProps,
|
||||
...this.props
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
setTimeout(() => {
|
||||
this.triggered = true;
|
||||
}, 1000)
|
||||
},
|
||||
methods: {
|
||||
handleScrollToLower() {
|
||||
this.getInfoList()
|
||||
},
|
||||
getInfoList() {
|
||||
this.pagination.keyword = this.keyword
|
||||
getTaskUserList(this.taskId, this.pagination).then(res => {
|
||||
const list = res.data.list;
|
||||
if (!list.length && this.pagination.currentPage != 1) return uni.showToast({
|
||||
title: '没有更多信息啦!',
|
||||
icon: 'none'
|
||||
});
|
||||
this.list = this.list.concat(list);
|
||||
this.pagination.currentPage++
|
||||
})
|
||||
},
|
||||
onSelect(list) {
|
||||
if (!this.multiple) this.selectList = []
|
||||
let flag = false;
|
||||
for (let i = 0; i < this.selectList.length; i++) {
|
||||
if (this.selectList[i].id === list.id) {
|
||||
flag = true;
|
||||
return
|
||||
}
|
||||
};
|
||||
!flag && this.selectList.push(list)
|
||||
},
|
||||
search() {
|
||||
this.searchTimer && clearTimeout(this.searchTimer)
|
||||
this.searchTimer = setTimeout(() => {
|
||||
this.pagination = {
|
||||
currentPage: 1,
|
||||
pageSize: 20
|
||||
}
|
||||
this.pagination.keyword = this.keyword
|
||||
getTaskUserList(this.taskId, this.pagination).then(res => {
|
||||
const list = res.data.list;
|
||||
this.list = list
|
||||
this.pagination = res.data.pagination
|
||||
this.total = this.pagination.total
|
||||
})
|
||||
}, 300)
|
||||
},
|
||||
delSelect(index) {
|
||||
this.selectList.splice(index, 1);
|
||||
},
|
||||
cleanAll() {
|
||||
this.selectList = [];
|
||||
},
|
||||
handleConfirm() {
|
||||
this.keyword = '';
|
||||
this.$emit('confirm', this.selectList);
|
||||
this.close();
|
||||
},
|
||||
close() {
|
||||
this.$emit('close');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.jnpf-user-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.swiper-box {
|
||||
flex: 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.listTitle {
|
||||
padding: 10rpx 30rpx;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.scroll-view {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.lists_box {
|
||||
height: 100%;
|
||||
|
||||
.nodata {
|
||||
height: 100%;
|
||||
margin: auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.list-cell-txt {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
padding: 20rpx 32rpx;
|
||||
overflow: hidden;
|
||||
color: $u-content-color;
|
||||
font-size: 28rpx;
|
||||
line-height: 24px;
|
||||
background-color: #fff;
|
||||
|
||||
.content {
|
||||
width: 85%;
|
||||
margin-left: 15rpx;
|
||||
|
||||
.organize {
|
||||
white-space: nowrap;
|
||||
overflow: hidden; //超出的文本隐藏
|
||||
text-overflow: ellipsis
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
680
pages/workFlow/comment/index.vue
Normal file
@@ -0,0 +1,680 @@
|
||||
<template>
|
||||
<view class="comment-v">
|
||||
<view class="comment_inner">
|
||||
<view class="text_box">
|
||||
<div class="u-input-wrapper">
|
||||
<u-input :type="textarea.type" v-model="dataForm.text" placeholder="请输入" :height='textarea.height'
|
||||
ref="textRef" :focus="textFocus" :border='textarea.border' :maxlength="textarea.maxlength"
|
||||
:auto-height="textarea.autoHeight" class="text_input" @input="handleContentChange" />
|
||||
<div class="remainingCharacters">{{ dataForm.text.length }}/{{textarea.maxlength}}</div>
|
||||
</div>
|
||||
</view>
|
||||
<view class="box" :style="{ bottom: popupOpenBottom + 'rpx'}">
|
||||
<scroll-view :scroll-y="true" style="height: 550rpx;" class="scroll_view" @click="hideDrawer">
|
||||
<view class="comment-area">
|
||||
<view class="img_box">
|
||||
<view class="u-preview-wrap" v-for="(item, index) in dataForm.imgList" :key="index">
|
||||
<view class="u-delete-icon" @tap.stop="deleteItem(index)">
|
||||
<u-icon class="u-icon" name="close" size="20" color="#ffffff"></u-icon>
|
||||
</view>
|
||||
<image class="u-preview-image" :src="jnpf.getAuthImgUrl(item.thumbUrl||item.url)"
|
||||
mode="aspectFill" @tap.stop="doPreviewImage(index)"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view v-for='(item,index) in dataForm.file' :key="index"
|
||||
class="jnpf-file-item u-type-primary u-flex u-line-1" @tap='downLoad(item)'>
|
||||
<view class="jnpf-file-item-txt u-line-1">{{item.name}}</view>
|
||||
<view class="closeBox u-flex-col" @click.stop="delFile(index)">
|
||||
<text class="icon-ym icon-ym-nav-close closeTxt u-flex"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="btn_box">
|
||||
<view class="u-flex">
|
||||
<view class="btn_item">
|
||||
<view class="icon-ym icon-ym-roll-call" size="mini" @click="openSelectUser()">
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn_item">
|
||||
<view class="icon-ym icon-ym-comment-img"
|
||||
v-if="dataForm.imgList && dataForm.imgList.length >= 9"
|
||||
@click="clickImgUploadOverCount">
|
||||
</view>
|
||||
<u-upload :custom-btn="true" :action="comUploadUrl+type" :header="uploadHeaders"
|
||||
ref="uUpload" :max-size="10*1024*1024" :max-count="9" :show-upload-list="false"
|
||||
:show-progress="false" @on-success="onImgSuccess" @on-change="onImgChange"
|
||||
:show-tips="false" @on-oversize="onImgOversize">
|
||||
<template #addBtn>
|
||||
<view class="slot-btn" hover-class="slot-btn__hover" hover-stay-time="150">
|
||||
<view class="icon-ym icon-ym-comment-img"></view>
|
||||
</view>
|
||||
</template>
|
||||
</u-upload>
|
||||
</view>
|
||||
<view class="btn_item">
|
||||
<CommentFile v-model="dataForm.file" :limit="9" :fileSize="10"
|
||||
:currentCount="dataForm.file?dataForm.file.length:0" ref="commentFile" />
|
||||
</view>
|
||||
<view class="btn_item">
|
||||
<view class="icon-ym icon-ym-emoji" size="mini" @click="chooseEmoji"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="btn_item">
|
||||
<u-button type="primary" @click="handleClick" :disabled="submitDisabled"
|
||||
size="medium">发送</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="popup-layer u-border-top" :class="popupLayerClass" @touchmove.stop.prevent="discard">
|
||||
<swiper class="emoji-swiper" indicator-dots="true" duration="150" v-show="showEmoji">
|
||||
<swiper-item v-for="(page,pid) in emojiTree" :key="pid">
|
||||
<view v-for="(em,eid) in page" :key="eid" @click="addEmoji(em)" class="emoji-item">
|
||||
<image mode="widthFix" :src="getEmojiUrl(em.url)" class="emoji-item-img"></image>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
<FlowUserModal v-model="flowUserModalShow" :taskId="taskId" :selectType="'custom'" :multiple="true"
|
||||
ref="flowUserModal" @confirm="handleSelectUser" @close="closeFlowUserModal" />
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
getDownloadUrl
|
||||
} from '@/api/common'
|
||||
import CommentFile from './comment-file/index.vue'
|
||||
import FlowUserModal from './comment-user-select/index.vue'
|
||||
import {
|
||||
emojiList,
|
||||
emojiTree,
|
||||
imagesMap
|
||||
} from '../flowBefore/emoji'
|
||||
import jnpf from '@/utils/jnpf'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CommentFile,
|
||||
FlowUserModal
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dataForm: {
|
||||
text: '',
|
||||
file: [],
|
||||
imgList: [],
|
||||
},
|
||||
type: 'annexpic',
|
||||
uploadHeaders: {
|
||||
Authorization: this.token
|
||||
},
|
||||
token: '',
|
||||
list: [],
|
||||
textarea: {
|
||||
type: 'textarea',
|
||||
border: true,
|
||||
height: 440,
|
||||
autoHeight: false,
|
||||
maxlength: 500
|
||||
},
|
||||
taskId: null,
|
||||
replyId: null,
|
||||
submitDisabled: true,
|
||||
selectUserType: '',
|
||||
selectionStart: 0,
|
||||
flowUserModalShow: false,
|
||||
textFocus: true,
|
||||
popupLayerClass: '',
|
||||
popupOpenBottom: 20,
|
||||
showEmoji: false,
|
||||
emojiList,
|
||||
emojiTree,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
},
|
||||
comUploadUrl() {
|
||||
return this.define.comUploadUrl
|
||||
},
|
||||
},
|
||||
onReady() {
|
||||
|
||||
},
|
||||
onLoad(e) {
|
||||
this.uploadHeaders.Authorization = uni.getStorageSync('token')
|
||||
let data = JSON.parse(decodeURIComponent(e.data))
|
||||
this.taskId = data.taskId
|
||||
if (data.replyId) {
|
||||
this.replyId = data.replyId
|
||||
uni.setNavigationBarTitle({
|
||||
title: '回复评论'
|
||||
});
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
dataForm: {
|
||||
handler: function(val) {
|
||||
this.setSubmitDisabled()
|
||||
},
|
||||
deep: true,
|
||||
immediate: true
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
clickImgUploadOverCount() {
|
||||
uni.showToast({
|
||||
title: '最多可以上传9张图片',
|
||||
icon: 'none'
|
||||
});
|
||||
return false;
|
||||
},
|
||||
discard() {
|
||||
return;
|
||||
},
|
||||
chooseEmoji() {
|
||||
if (this.showEmoji) return this.hideDrawer()
|
||||
this.showEmoji = true;
|
||||
this.openDrawer();
|
||||
},
|
||||
|
||||
addEmoji(em) {
|
||||
this.dataForm.text += em.alt;
|
||||
},
|
||||
getEmojiUrl(url) {
|
||||
return imagesMap[url.replace('.', '')]
|
||||
},
|
||||
openDrawer() {
|
||||
this.popupLayerClass = 'showLayer';
|
||||
setTimeout(() => {
|
||||
this.popupOpenBottom = 315;
|
||||
}, 150);
|
||||
},
|
||||
hideDrawer() {
|
||||
this.popupLayerClass = '';
|
||||
setTimeout(() => {
|
||||
this.showEmoji = false;
|
||||
this.popupOpenBottom = 20;
|
||||
}, 50);
|
||||
},
|
||||
getFocus() {
|
||||
this.textFocus = false
|
||||
setTimeout(() => {
|
||||
this.textFocus = true
|
||||
}, 50);
|
||||
},
|
||||
setSubmitDisabled() {
|
||||
this.submitDisabled = !this.dataForm.text
|
||||
},
|
||||
openSelectUser() {
|
||||
this.selectUserType = 'btn';
|
||||
this.selectionStart = -1;
|
||||
this.flowUserModalShow = true
|
||||
},
|
||||
closeFlowUserModal() {
|
||||
this.flowUserModalShow = false
|
||||
},
|
||||
handleContentChange(value) {
|
||||
if (!value || !value.endsWith("@")) {
|
||||
return;
|
||||
}
|
||||
this.selectUserType = 'input';
|
||||
this.selectionStart = value.length;
|
||||
this.flowUserModalShow = true
|
||||
},
|
||||
handleSelectUser(data) {
|
||||
if (!data.length || !data.length) return;
|
||||
let addContent = this.selectUserType === 'btn' ? '@' : '';
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
let str = (i > 0 ? '@' : '') + `{${data[i].fullName}}`;
|
||||
addContent += str;
|
||||
}
|
||||
if (this.selectionStart === -1) {
|
||||
this.dataForm.text += addContent;
|
||||
this.textFocus = false
|
||||
this.getFocus();
|
||||
} else {
|
||||
let oldValue = this.dataForm.text;
|
||||
let rangeIndex = this.selectionStart + addContent.length;
|
||||
this.dataForm.text = oldValue.slice(0, this.selectionStart) + addContent + oldValue.slice(this
|
||||
.selectionStart);
|
||||
this.textFocus = false
|
||||
this.getFocus();
|
||||
}
|
||||
},
|
||||
handleClick() {
|
||||
const query = {
|
||||
text: this.dataForm.text,
|
||||
file: JSON.stringify(this.dataForm.file),
|
||||
image: JSON.stringify(this.dataForm.imgList),
|
||||
replyId: this.replyId
|
||||
}
|
||||
uni.$emit('comment', query);
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
||||
//文件下载
|
||||
downLoad(item) {
|
||||
// #ifdef MP
|
||||
this.previewFile(item)
|
||||
// #endif
|
||||
// #ifndef MP
|
||||
getDownloadUrl('annex', item.fileId).then(res => {
|
||||
const fileUrl = this.baseURL + res.data.url + '&name=' + item.name;
|
||||
// #ifdef H5
|
||||
window.location.href = fileUrl;
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
this.downloadFile(res.data.url);
|
||||
// #endif
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
previewFile(item) {
|
||||
let fileTypes = ['doc', 'xls', 'ppt', 'pdf', 'docx', 'xlsx', 'pptx']
|
||||
let url = item.url
|
||||
let fileType = url.split('.')[1]
|
||||
if (fileTypes.includes(fileType)) {
|
||||
uni.downloadFile({
|
||||
url: this.baseURL + url,
|
||||
success: (res) => {
|
||||
var filePath = res.tempFilePath;
|
||||
uni.openDocument({
|
||||
filePath: encodeURI(filePath),
|
||||
showMenu: true,
|
||||
fileType: fileType,
|
||||
success: (res) => {},
|
||||
fail(err) {}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.$u.toast(
|
||||
'该文件类型无法打开'
|
||||
)
|
||||
}
|
||||
},
|
||||
//文件删除
|
||||
delFile(index) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '是否删除该文件?',
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
this.dataForm.file.splice(index, 1)
|
||||
this.$refs.commentFile.delFile(this.dataForm.file);
|
||||
} else if (res.cancel) {}
|
||||
}
|
||||
});
|
||||
},
|
||||
downloadFile(url) {
|
||||
uni.downloadFile({
|
||||
url: this.baseURL + url,
|
||||
success: res => {
|
||||
if (res.statusCode === 200) {
|
||||
const filePath = res.tempFilePath;
|
||||
uni.openDocument({
|
||||
filePath: escape(filePath),
|
||||
success: ress => {},
|
||||
fail(err) {}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
onImgSuccess(data, index, lists, name) {
|
||||
if (data.code == 200) {
|
||||
this.dataForm.imgList.push({
|
||||
name: lists[index].file.name,
|
||||
fileId: data.data.name,
|
||||
url: data.data.url,
|
||||
thumbUrl: data.data.thumbUrl,
|
||||
})
|
||||
// this.$emit('input', this.fileList)
|
||||
} else {
|
||||
lists.splice(index, 1)
|
||||
this.$u.toast(data.msg)
|
||||
}
|
||||
},
|
||||
onImgChange(res, index, lists, name) {
|
||||
const isTopLimit = lists.length > 9;
|
||||
if (isTopLimit) {
|
||||
uni.showToast({
|
||||
title: '最多可以上传9张图片',
|
||||
icon: 'none'
|
||||
});
|
||||
return false
|
||||
}
|
||||
const isRightSize = lists[index].file.size < 10 * 1024 * 1024;
|
||||
if (!isRightSize) {
|
||||
uni.showToast({
|
||||
title: '图片大小超过10MB',
|
||||
icon: 'none'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
let isAccept = new RegExp('image/!*').test(file.type);
|
||||
if (!isAccept) {
|
||||
this.$message({ message: '请上传图片', type: 'error', duration: 1000 })
|
||||
return
|
||||
}
|
||||
return isRightSize && isAccept;*/
|
||||
},
|
||||
onImgOversize(res, index, lists, name) {
|
||||
uni.showToast({
|
||||
title: '图片大小超过10MB',
|
||||
icon: 'none'
|
||||
});
|
||||
return false;
|
||||
},
|
||||
doPreviewImage(index = 0) {
|
||||
const images = this.dataForm.imgList.map(item => jnpf.getAuthImgUrl(item.url,false));
|
||||
uni.previewImage({
|
||||
urls: images,
|
||||
current: images[index],
|
||||
success: () => {},
|
||||
fail: () => {
|
||||
uni.showToast({
|
||||
title: '预览图片失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
deleteItem(index) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '是否删除该图片?',
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
this.$refs.uUpload.remove(index);
|
||||
this.dataForm.imgList.splice(index, 1)
|
||||
// this.$emit('input', this.fileList)
|
||||
uni.showToast({
|
||||
title: '移除成功',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.comment-v {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0 auto;
|
||||
// .flowBefore-actions{
|
||||
// width: 90%;
|
||||
// left: 50%;
|
||||
// transform: translateX(-50%);
|
||||
// bottom: 20rpx;
|
||||
// .buttom-btn{
|
||||
// border-radius: 10rpx;
|
||||
// }
|
||||
// }
|
||||
|
||||
.uni-textarea-compute {
|
||||
height: 470rpx !important;
|
||||
}
|
||||
|
||||
.comment_inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #FFFFFF;
|
||||
height: 100%;
|
||||
padding: 0 30rpx;
|
||||
|
||||
.text_box {
|
||||
flex: 0.35;
|
||||
|
||||
.u-input-wrapper {
|
||||
border: 1px solid #E7E7E7;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.remainingCharacters {
|
||||
width: 99%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.text_input {
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
// .input_textarea{
|
||||
// height: 470rpx !important;
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
|
||||
.scroll_view {
|
||||
.comment-area {
|
||||
height: 550rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 28rpx;
|
||||
|
||||
.img_box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.u-preview-wrap {
|
||||
width: 110rpx;
|
||||
height: 110rpx;
|
||||
overflow: hidden;
|
||||
margin: 10rpx;
|
||||
background: rgb(244, 245, 246);
|
||||
position: relative;
|
||||
border-radius: 10rpx;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.u-preview-image {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.u-delete-icon {
|
||||
position: absolute;
|
||||
top: 10rpx;
|
||||
right: 10rpx;
|
||||
z-index: 10;
|
||||
background-color: $u-type-error;
|
||||
border-radius: 100rpx;
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.u-icon {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.jnpf-file-item {
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
flex-direction: row;
|
||||
|
||||
.jnpf-file-item-txt {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.closeBox {
|
||||
height: 60rpx;
|
||||
justify-content: space-evenly;
|
||||
flex: 0.2;
|
||||
|
||||
.closeTxt {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #909194;
|
||||
color: #FFFFFF;
|
||||
font-size: 22rpx;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.btn_box {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
// justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
.btn_item {
|
||||
margin-right: 30rpx;
|
||||
margin-left: 10rpx;
|
||||
|
||||
.icon-ym {
|
||||
font-size: 48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.btn_item:last-child {
|
||||
margin-left: auto;
|
||||
margin-right: 50rpx;
|
||||
}
|
||||
|
||||
.submit_item {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.slot-btn {
|
||||
.img_icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
text-align: center;
|
||||
line-height: 80rpx;
|
||||
|
||||
&:before {
|
||||
content: "\e987";
|
||||
font-size: 60rpx;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.file_icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
text-align: center;
|
||||
line-height: 80rpx;
|
||||
|
||||
&:before {
|
||||
font-size: 60rpx;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popup-layer {
|
||||
&.showLayer {
|
||||
transform: translate3d(0, -42vw, 0);
|
||||
}
|
||||
|
||||
transition: all .15s linear;
|
||||
width: 100%;
|
||||
height: 42vw;
|
||||
padding: 20rpx 2%;
|
||||
background-color: #f2f2f2;
|
||||
position: fixed;
|
||||
z-index: 20;
|
||||
top: 100%;
|
||||
|
||||
.emoji-swiper {
|
||||
height: 40vw;
|
||||
|
||||
swiper-item {
|
||||
display: flex;
|
||||
align-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.emoji-item {
|
||||
width: 12vw;
|
||||
height: 12vw;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.emoji-item-img {
|
||||
width: 8.4vw;
|
||||
height: 8.4vw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.more-layer {
|
||||
width: 100%;
|
||||
height: 42vw;
|
||||
|
||||
.list {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.box {
|
||||
width: 18vw;
|
||||
height: 18vw;
|
||||
border-radius: 20rpx;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 0 3vw 2vw 3vw;
|
||||
|
||||
.icon {
|
||||
font-size: 70rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
196
pages/workFlow/components/CandidateForm.vue
Normal file
@@ -0,0 +1,196 @@
|
||||
<template>
|
||||
<view class="candidateForm-v">
|
||||
<u-popup mode="left" :popup="false" v-model="showPopup" length="auto" @close="close" width="100%">
|
||||
<view class="jnpf-wrap jnpf-wrap-form">
|
||||
<u-form :model="candidateForm" ref="candidateForm" :errorType="['toast']" label-position="left"
|
||||
label-width="150" label-align="left">
|
||||
<u-form-item label="分支选择" prop="branch" v-if="candidateType == 1" required>
|
||||
<JnpfSelect v-model="candidateForm.branchList" @change="branchChange" placeholder="请选择审批分支"
|
||||
:options="branchList" :multiple="true" :props='props' />
|
||||
</u-form-item>
|
||||
<u-form-item label-width="250" v-for="(item,index) in candidateForm.list" :key="index"
|
||||
:label="item.label">
|
||||
<u-input type="select" :select-open="item.selectShow" v-model="item.value"
|
||||
@click="openSelect(item)" placeholder="请选择审批候选人">
|
||||
</u-input>
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
<view class="buttom-actions">
|
||||
<u-button class="buttom-btn" @click="cancel">取消</u-button>
|
||||
<u-button class="buttom-btn" type="primary" @click="submit">确定</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
formData: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
taskId: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showPopup: false,
|
||||
candidateForm: {
|
||||
list: [],
|
||||
branchList: []
|
||||
},
|
||||
nodeId: '',
|
||||
selectId: {},
|
||||
rules: {},
|
||||
selectList: [],
|
||||
selectVal: {},
|
||||
isCandidate: false,
|
||||
props: {
|
||||
label: 'nodeName',
|
||||
value: 'nodeId'
|
||||
},
|
||||
candidateType: 1,
|
||||
branchList: [],
|
||||
candidateList: []
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
modelValue: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
this.showPopup = val
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
uni.$on('confirm', (data, id) => {
|
||||
this.selectConfirm(data, id)
|
||||
})
|
||||
},
|
||||
onUnload() {
|
||||
uni.$off('confirm')
|
||||
},
|
||||
methods: {
|
||||
branchChange(e) {
|
||||
this.candidateForm.branchList = e;
|
||||
this.init()
|
||||
},
|
||||
init(candidateType, branchList, candidateList) {
|
||||
this.candidateType = candidateType;
|
||||
this.branchList = branchList;
|
||||
this.candidateList = candidateList
|
||||
if (this.candidateType == 1) {
|
||||
let list = [];
|
||||
for (let i = 0; i < this.candidateForm.branchList.length; i++) {
|
||||
inner: for (let j = 0; j < this.branchList.length; j++) {
|
||||
let o = this.branchList[j]
|
||||
if (o.isCandidates) this.isCandidate = o.isCandidates
|
||||
if (this.candidateForm.branchList[i] === o.nodeId && o.isCandidates) {
|
||||
list.push({
|
||||
...o,
|
||||
label: o.nodeName + '审批人',
|
||||
value: '',
|
||||
selectShow: false
|
||||
})
|
||||
break inner
|
||||
}
|
||||
}
|
||||
this.candidateForm.list = list
|
||||
}
|
||||
} else {
|
||||
if (Array.isArray(this.candidateList) && this.candidateList.length) {
|
||||
this.isCandidate = true
|
||||
this.candidateForm.list = this.candidateList.map(o => ({
|
||||
...o,
|
||||
label: o.nodeName + '审批人',
|
||||
value: '',
|
||||
selectShow: false
|
||||
}))
|
||||
}
|
||||
}
|
||||
},
|
||||
openSelect(item) {
|
||||
this.selectList = []
|
||||
for (let o in this.selectVal) {
|
||||
if (o === item.nodeId) this.selectList = this.selectVal[o]
|
||||
}
|
||||
item.formData = this.formData
|
||||
item.taskId = this.taskId
|
||||
item.selectList = !item.value ? [] : this.selectList
|
||||
uni.navigateTo({
|
||||
url: '/pages/workFlow/candiDateUserSelect/index?data=' + encodeURIComponent(JSON.stringify(
|
||||
item))
|
||||
})
|
||||
},
|
||||
|
||||
selectConfirm(e, id) {
|
||||
let selectData = e;
|
||||
let selectVal = [];
|
||||
let val = [];
|
||||
let selectId = [];
|
||||
let nodeId = '';
|
||||
if (!selectData.length) {
|
||||
delete this.selectVal[id]
|
||||
delete this.selectId[id]
|
||||
for (let i = 0; i < this.candidateForm.list.length; i++) {
|
||||
if (id === this.candidateForm.list[i].nodeId) {
|
||||
this.candidateForm.list[i].value = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < this.candidateForm.list.length; i++) {
|
||||
for (let o = 0; o < selectData.length; o++) {
|
||||
if (selectData[o].nodeId === this.candidateForm.list[i].nodeId) {
|
||||
nodeId = selectData[o].nodeId
|
||||
val.push(selectData[o].userName)
|
||||
selectVal.push(selectData[o])
|
||||
this.candidateForm.list[i].value = val.join(',')
|
||||
selectId.push(selectData[o].userId)
|
||||
this.$set(this.selectId, selectData[o].nodeId, selectId)
|
||||
}
|
||||
}
|
||||
}
|
||||
this.$set(this.selectVal, nodeId, selectVal)
|
||||
},
|
||||
submit() {
|
||||
const query = {
|
||||
candidateType: this.candidateType,
|
||||
branchList: this.candidateForm.branchList
|
||||
}
|
||||
if (this.isCandidate) {
|
||||
query.candidateList = this.selectId
|
||||
for (let rules of this.candidateForm.list) {
|
||||
if (!rules.value) return this.$u.toast(
|
||||
`${rules.nodeName}不能为空`
|
||||
)
|
||||
}
|
||||
}
|
||||
this.$emit('submitCandidate', query);
|
||||
},
|
||||
cancel() {
|
||||
this.close()
|
||||
},
|
||||
close() {
|
||||
this.$emit('input', false);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.candidateForm-v {
|
||||
|
||||
.jnpf-wrap,
|
||||
.jnpf-wrap-form {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
92
pages/workFlow/components/ErrorForm.vue
Normal file
@@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<view class="dataForm-v">
|
||||
<u-popup mode="left" :popup="false" v-model="show" length="auto" @close="close" width="100%">
|
||||
<view class="diyTitle u-flex">
|
||||
<uni-icons type="back" size="27" class="uni-btn-icon" @click="black"></uni-icons>
|
||||
<view class="txt">异常处理</view>
|
||||
</view>
|
||||
<view class="jnpf-wrap-form u-p-l-20 u-p-r-20">
|
||||
<u-form :model="errorDataForm" ref="errorDataForm" :errorType="['toast']" label-position="left"
|
||||
:label-width="250" label-align="left">
|
||||
<u-form-item prop="errorDataForm" v-for="(item,index) in list" :key="index" :label="item.nodeName"
|
||||
required>
|
||||
<JnpfUserSelect v-model="errorDataForm.errorRuleUserList[item.nodeCode]" :multiple="true"
|
||||
placeholder="请选择异常处理人" />
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
<view class="buttom-actions">
|
||||
<u-button class="buttom-btn" @click="cancel">取消</u-button>
|
||||
<u-button class="buttom-btn" type="primary" @click="submit">确定</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
// 通过双向绑定控制组件的弹出与收起
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
errorDataForm: {
|
||||
errorRuleUserList: {},
|
||||
},
|
||||
list: [],
|
||||
show: false,
|
||||
query: {}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init(list, query) {
|
||||
this.show = true
|
||||
this.list = list
|
||||
this.list.map(o => {
|
||||
this.$set(this.errorDataForm.errorRuleUserList, o.nodeCode, [])
|
||||
})
|
||||
this.query = {
|
||||
...query
|
||||
}
|
||||
},
|
||||
submit() {
|
||||
const hasEmptyUserList = Object.keys(this.errorDataForm.errorRuleUserList).some(rules => {
|
||||
return !this.errorDataForm.errorRuleUserList[rules].length;
|
||||
});
|
||||
if (hasEmptyUserList) return this.$u.toast('异常处理人员不能为空');
|
||||
const query = {
|
||||
errorRuleUserList: this.errorDataForm.errorRuleUserList,
|
||||
...this.query
|
||||
}
|
||||
this.$emit('submitErrorForm', query);
|
||||
},
|
||||
cancel() {
|
||||
this.close()
|
||||
},
|
||||
black() {
|
||||
this.close()
|
||||
},
|
||||
close() {
|
||||
this.show = false
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.dataForm-v {
|
||||
.diyTitle {
|
||||
height: 80rpx;
|
||||
padding: 14rpx 6rpx;
|
||||
text-align: center;
|
||||
justify-content: flex-start;
|
||||
|
||||
.uniui-back {
|
||||
font-size: 27px;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
.txt {
|
||||
flex: 0.95;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
280
pages/workFlow/components/RecordTimeList/ProcessComments.vue
Normal file
@@ -0,0 +1,280 @@
|
||||
<template>
|
||||
<view class="record-v">
|
||||
<view class="discuss_box" v-if="commentList.length">
|
||||
<view class="u-flex-col discuss_list" v-for="(item,index) in commentList" :key="index">
|
||||
<view class="u-flex discuss_txt">
|
||||
<view class="discuss_txt_left u-flex">
|
||||
<u-avatar :src="baseURL+item.creatorUserHeadIcon"></u-avatar>
|
||||
<span class="uName">
|
||||
<span class="comment-header-color">{{item.creatorUser}}</span>
|
||||
<span v-if="item.replyUser">
|
||||
<span class="replyText comment-content-color">回复</span>
|
||||
<span class="replyText comment-header-color">{{ item.replyUser }}</span>
|
||||
<span class="replyText"> <span class="icon-ym icon-ym-chat"
|
||||
@click="openReplyText(item.replyText)"></span></span>
|
||||
</span>
|
||||
</span>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-flex-col discuss_content">
|
||||
<view class="msg-text">
|
||||
<view v-for="(item2,j) in item.text" :key="j">
|
||||
<text class="txt comment-content-color" v-if="item2.type=='text'">{{item2.content}}</text>
|
||||
<image class="msg-text-emoji" :src="item2.content" v-if="item2.type=='emjio'" />
|
||||
</view>
|
||||
</view>
|
||||
<JnpfUploadImg v-model="item.image" disabled detailed align='left' v-if="item.isDel != 2" />
|
||||
<view v-for='(file,f) in item.file' :key="f" class="jnpf-file-item u-type-primary u-flex u-line-1"
|
||||
@click="openFile(file)">
|
||||
<view class="u-line-1" style="margin-bottom: 10rpx;">
|
||||
{{file.name}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-flex discuss_txt time_button">
|
||||
<text
|
||||
class="discuss_txt_left u-flex comment-creator-time">{{$u.timeFormat(item.creatorTime,'yyyy-mm-dd hh:MM:ss')}}</text>
|
||||
<view>
|
||||
<text v-if="item.isDel == 1" class="del" @click.stop="delComment(item.id, index)">删除</text>
|
||||
<text v-if="item.isDel != 2" class="reply" @click.stop="handleReply(item.id)">回复</text>
|
||||
</view>
|
||||
</view>
|
||||
<u-divider half-width="100%" :margin-top="32" :margin-bottom="32" :use-slot="false"
|
||||
v-if="index != commentList.length-1" />
|
||||
</view>
|
||||
</view>
|
||||
<JnpfEmpty v-else />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getCommentList,
|
||||
delComment
|
||||
} from '@/api/workFlow/flowEngine'
|
||||
import {
|
||||
getDownloadUrl
|
||||
} from '@/api/common'
|
||||
import {
|
||||
emojiList,
|
||||
imagesMap
|
||||
} from '../../flowBefore/emoji'
|
||||
export default {
|
||||
props: {
|
||||
taskId: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
emojiList: emojiList,
|
||||
commentList: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCommentList() {
|
||||
let query = {
|
||||
currentPage: 1,
|
||||
pageSize: 100000,
|
||||
sort: 'desc',
|
||||
sidx: '',
|
||||
taskId: this.taskId
|
||||
}
|
||||
getCommentList(query).then(res => {
|
||||
this.commentList = [];
|
||||
const list = res.data.list.map((o) => {
|
||||
o.image = JSON.parse(o.image)
|
||||
o.file = JSON.parse(o.file)
|
||||
o.text = this.replaceEmoji(o.text)
|
||||
return o
|
||||
})
|
||||
this.commentList = this.commentList.concat(list);
|
||||
}).catch((err) => {})
|
||||
},
|
||||
openReplyText(replyText) {
|
||||
uni.showModal({
|
||||
content: replyText,
|
||||
showCancel: false,
|
||||
success: res => {}
|
||||
})
|
||||
},
|
||||
replaceEmoji(str) { //替换表情符号为图片
|
||||
if (!str) return ''
|
||||
let replacedStr = str.replace(/\[([^(\]|\[)]*)\]/g, item => 'jnpfjnpf' + item + 'jnpfjnpf');
|
||||
let strArr = replacedStr.split(/jnpfjnpfjnpfjnpf|jnpfjnpf/g)
|
||||
strArr = strArr.filter(o => o)
|
||||
let contentList = []
|
||||
for (let i = 0; i < strArr.length; i++) {
|
||||
let item = {
|
||||
content: strArr[i],
|
||||
type: 'emjio'
|
||||
}
|
||||
if (/\[([^(\]|\[)]*)\]/.test(strArr[i])) {
|
||||
let content = ''
|
||||
for (let j = 0; j < this.emojiList.length; j++) {
|
||||
let row = this.emojiList[j];
|
||||
if (row.alt == strArr[i]) {
|
||||
content = this.getEmojiUrl(row.url)
|
||||
break
|
||||
}
|
||||
}
|
||||
item = {
|
||||
content: content,
|
||||
type: 'emjio'
|
||||
}
|
||||
} else {
|
||||
item = {
|
||||
content: strArr[i],
|
||||
type: 'text'
|
||||
}
|
||||
}
|
||||
contentList.push(item)
|
||||
}
|
||||
return contentList
|
||||
},
|
||||
getEmojiUrl(url) {
|
||||
return imagesMap[url.replace('.', '')]
|
||||
},
|
||||
delComment(id, i) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定删除?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
delComment(id).then(res => {
|
||||
this.getCommentList()
|
||||
this.commentList.splice(i, 1)
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
handleReply(id) {
|
||||
this.$emit('handleReply', id)
|
||||
},
|
||||
openFile(item) {
|
||||
// #ifdef MP
|
||||
this.previewFile(item)
|
||||
// #endif
|
||||
// #ifdef H5 || APP
|
||||
getDownloadUrl('annex', item.fileId).then(res => {
|
||||
// #ifdef H5
|
||||
window.location.href = this.baseURL + res.data.url + '&name=' + item.name;
|
||||
// #endif
|
||||
// #ifdef APP
|
||||
uni.downloadFile({
|
||||
url: this.baseURL + res.data.url + '&name=' + item.name,
|
||||
success: function(res) {
|
||||
var filePath = res.tempFilePath;
|
||||
uni.openDocument({
|
||||
filePath: filePath,
|
||||
showMenu: true,
|
||||
success: function(res) {}
|
||||
});
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
previewFile(item) {
|
||||
let url = item.url
|
||||
uni.downloadFile({
|
||||
url: this.baseURL + url,
|
||||
success: (res) => {
|
||||
var filePath = res.tempFilePath;
|
||||
uni.openDocument({
|
||||
filePath: encodeURI(filePath),
|
||||
success: (res) => {}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
// 流程评论end
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.record-v {
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
|
||||
|
||||
.msg-text {
|
||||
border-radius: 4rpx 30rpx 30rpx 30rpx;
|
||||
padding: 16rpx 32rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
line-height: 17px;
|
||||
font-family: PingFang SC;
|
||||
word-break: break-word;
|
||||
flex-wrap: wrap;
|
||||
background-color: #fff;
|
||||
|
||||
.msg-text-emoji {
|
||||
vertical-align: top;
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.discuss_box {
|
||||
padding: 20rpx;
|
||||
|
||||
.discuss_list {
|
||||
|
||||
.time_button {
|
||||
padding-left: 110rpx;
|
||||
margin-top: 20rpx;
|
||||
padding-right: 10rpx;
|
||||
}
|
||||
|
||||
.discuss_txt {
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
|
||||
.discuss_txt_left {
|
||||
.uName {
|
||||
margin-left: 8px;
|
||||
font-size: 14px;
|
||||
font-family: PingFang SC;
|
||||
line-height: 17rpx;
|
||||
|
||||
.replyText {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.del {
|
||||
color: red;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.reply {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.discuss_content {
|
||||
font-size: 12px;
|
||||
padding-left: 70rpx;
|
||||
|
||||
.img_box {
|
||||
margin: 40rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
125
pages/workFlow/components/RecordTimeList/TaskLogModal.vue
Normal file
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<uni-popup ref="taskLogPoup" background-color="#fff" border-radius="8rpx 8rpx 0 0" :is-mask-click="false">
|
||||
<view class="timeLine-popup-content u-flex-col">
|
||||
<view class="u-flex head-title">
|
||||
<text class="text">任务流程</text>
|
||||
<text class="text icon-ym icon-ym-fail" @click="popupClose"></text>
|
||||
</view>
|
||||
<view class="content" v-for="item,index in taskLogList" :key="index" v-if="taskLogList.length">
|
||||
<view class="u-flex-col content-info-process">
|
||||
<view class="info-process-item">
|
||||
<view class="u-flex u-m-t-20 u-m-b-20 process-item-head">
|
||||
<view class="left">
|
||||
<text>触发时间:</text>
|
||||
<text>{{item.startTime?$u.timeFormat(item.startTime, 'yyyy-mm-dd hh:MM:ss'):''}}</text>
|
||||
</view>
|
||||
<u-tag :text="item.isAsync == 1 ? '异步' : '同步'" size="mini"
|
||||
:type="item.isAsync == 1 ? 'error' : 'primary'" />
|
||||
</view>
|
||||
<view class="process-list u-m-t-14">
|
||||
<view class="u-flex list u-p-l-12 u-p-r-12" v-for="(child,c) in item.recordList" :key="c">
|
||||
<view class="list-left">
|
||||
<u-icon :name="child.status === 0 ? 'checkmark-circle-fill' : 'close-circle-fill'"
|
||||
:color="child.status === 0 ? '#52c41a' : '#f4420a' "></u-icon>
|
||||
<text class="u-m-l-8">{{child.nodeName}}</text>
|
||||
</view>
|
||||
<text class="u-m-l-8 r-txt" v-if="child.status !== 0"
|
||||
@click="jumpErrorPage(child)">查看异常</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<JnpfEmpty v-else />
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
taskLogList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
jumpErrorPage(e) {
|
||||
let data = {
|
||||
errorData: e.errorData,
|
||||
errorTip: e.errorTip
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: '/pages/workFlow/flowBefore/logError?data=' + this.jnpf.base64.encode(JSON.stringify(
|
||||
data),
|
||||
"UTF-8"),
|
||||
})
|
||||
},
|
||||
open() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.taskLogPoup.open('bottom')
|
||||
})
|
||||
},
|
||||
popupClose() {
|
||||
this.$refs.taskLogPoup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.timeLine-popup-content {
|
||||
padding: 20rpx;
|
||||
height: 1200rpx;
|
||||
overflow-y: scroll;
|
||||
|
||||
.head-title {
|
||||
justify-content: space-between;
|
||||
color: #333333;
|
||||
/* #ifdef APP-PLUS */
|
||||
padding: 20rpx 0;
|
||||
/* #endif */
|
||||
height: 80rpx;
|
||||
}
|
||||
|
||||
.content {
|
||||
.content-info-process {
|
||||
.info-process-item {
|
||||
border-bottom: 1rpx solid #d7d7d7;
|
||||
padding-bottom: 26rpx;
|
||||
|
||||
.process-item-head {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.process-list {
|
||||
background-color: #f1f4f8;
|
||||
border-radius: 8rpx;
|
||||
|
||||
.list {
|
||||
height: 68rpx;
|
||||
align-items: center;
|
||||
border-bottom: 1rpx solid #e7e9ec;
|
||||
justify-content: space-between;
|
||||
|
||||
.r-txt {
|
||||
color: #0000ff;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
300
pages/workFlow/components/RecordTimeList/TimeLine.vue
Normal file
@@ -0,0 +1,300 @@
|
||||
<template>
|
||||
<view class="u-p-l-20 u-p-r-20 u-p-t-20">
|
||||
<u-time-line>
|
||||
<u-time-line-item nodeTop="2" class="u-p-b-20" v-for="item,index in progressList" :key="index">
|
||||
<template v-slot:node>
|
||||
<view class="u-node" :style="{ background: getTimeLineTagColor(item.nodeStatus) }"></view>
|
||||
</template>
|
||||
<template v-slot:content>
|
||||
<view class="u-font-24 content">
|
||||
<view class="u-order-title u-flex u-m-b-8">
|
||||
<view class="u-line-1 name" v-if="['start', 'end', 'outside'].includes(item.nodeType)">
|
||||
{{item.nodeName}}
|
||||
</view>
|
||||
<view class="u-line-1 name" v-else>
|
||||
{{item.nodeName + getCounterSignContent(item.counterSign, item.assigneeType)}}
|
||||
</view>
|
||||
<view class="u-m-l-10">
|
||||
<!-- 流程状态 -->
|
||||
<u-tag :text="getNodeStatusContent(item.nodeStatus)" mode="light" size="mini"
|
||||
shape="circle" :type="getNodeStatusColor(item.nodeStatus)"
|
||||
v-if="item.nodeType !=='end' && getNodeStatusContent(item.nodeStatus)" />
|
||||
<text
|
||||
class="u-m-l-10">{{item.startTime ? $u.timeFormat(item.startTime, 'mm-dd hh:MM'):''}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-flex avatar-box" v-if="item.nodeStatus == 1">
|
||||
<u-avatar :src="baseURL + taskInfo.headIcon" size="mini" mode="circle"
|
||||
class="avatar"></u-avatar>
|
||||
<text class="u-m-l-8">发起人:{{taskInfo.creatorUser}}</text>
|
||||
</view>
|
||||
<view class="u-flex-col approver-list" v-if="item.nodeStatus != 1 && item.approver?.length">
|
||||
<view class="u-flex approver-item" @click="openApprover(item)">
|
||||
<view class="u-flex approver-list-l">
|
||||
<view class="u-flex-col approver-list-l-box" v-for="child,i in item.approver"
|
||||
:key="i">
|
||||
<u-avatar :src="baseURL + child.headIcon" size="mini" mode="circle"
|
||||
class="avatar"></u-avatar>
|
||||
<u-tag :text="useDefine.getFlowStateContent(child.handleType)" mode="light"
|
||||
v-if="useDefine.getFlowStateContent(child.handleType)" class="tag"
|
||||
size="mini"
|
||||
:border-color="useDefine.getHexColor(useDefine.getFlowStateColor(child.handleType))"
|
||||
:bg-color="useDefine.getHexColor(useDefine.getFlowStateColor(child.handleType))"
|
||||
color="#fff" />
|
||||
<text class="u-m-t-20 u-line-1 approver-user-name">
|
||||
{{child.userName}}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-m-l-20 approver-list-r u-flex">
|
||||
<view class="approver-list-r-box">{{item.approverCount}}</view>
|
||||
<text class="icon-ym icon-ym-right u-m-r-12"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bottom-block" @click="openTaskLogModal(item)" v-if="item.showTaskFlow">
|
||||
<u-tag text="任务流程" type="info" mode="dark" class="u-m-l-10" />
|
||||
<text class="icon-ym icon-ym-right u-m-r-12"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-flex outside-sign" v-if="item.nodeType == 'outside'">
|
||||
<view>数据传递{{ getOutsideState(item.outSideStatus)}}</view>
|
||||
<view v-if="!item.outSideStatus">
|
||||
<text class="u-m-l-8 r-txt btn-link" @click="handleShowErrorModal(item)">查看异常</text >
|
||||
<text class="u-m-l-8 r-txt btn-link danger" @click="handleRetry(item)" v-if="item.isRetry">重试</text >
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</u-time-line-item>
|
||||
</u-time-line>
|
||||
</view>
|
||||
<TimeLinePopup :popupTitle="popupTitle" :recordList="recordList" ref="TimeLinePopup">
|
||||
</TimeLinePopup>
|
||||
<TaskLogModal ref="TaskLogModal" :taskLogList="taskLogList" />
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
recordList,
|
||||
taskList,
|
||||
retryOutside
|
||||
} from '@/api/workFlow/flowBefore'
|
||||
import fileList from './fileList.vue'
|
||||
import TimeLinePopup from './TimeLinePopup.vue'
|
||||
import TaskLogModal from './TaskLogModal.vue'
|
||||
import {
|
||||
useDefineSetting
|
||||
} from '@/utils/useDefineSetting';
|
||||
export default {
|
||||
components: {
|
||||
fileList,
|
||||
TimeLinePopup,
|
||||
TaskLogModal
|
||||
},
|
||||
props: {
|
||||
progressList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
taskInfo: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
useDefine: useDefineSetting(),
|
||||
recordList: [],
|
||||
popupTitle: '',
|
||||
taskLogList: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCounterSignContent(counterSign, assigneeType) {
|
||||
if (assigneeType == 10) return '(逐级审批)';
|
||||
return counterSign == 0 ? '(或签)' : counterSign == 1 ? '(会签)' : '(依次审批)';
|
||||
},
|
||||
getNodeStatusColor(status) {
|
||||
return status == 1 || status == 2 ? 'success' : status == 3 ? 'error' : 'primary';
|
||||
},
|
||||
getNodeStatusContent(status) {
|
||||
const list = ['', '已提交', '已通过', '已拒绝', '审批中', '已退回', '已撤回', '等待中', '办理中'];
|
||||
return list[status] || '';
|
||||
},
|
||||
/* 任务流程 */
|
||||
openTaskLogModal(item) {
|
||||
let data = {
|
||||
taskId: this.taskInfo.id,
|
||||
nodeCode: item.nodeId
|
||||
}
|
||||
taskList(data).then(res => {
|
||||
this.taskLogList = res.data || []
|
||||
this.$nextTick(() => {
|
||||
this.$refs.TaskLogModal.open()
|
||||
})
|
||||
})
|
||||
},
|
||||
openApprover(item) {
|
||||
if (item.nodeType === "start" || item.nodeType === "end") return
|
||||
this.popupTitle = item.nodeName + this.getCounterSignContent(item.counterSign, item.assigneeType)
|
||||
this.nodeId = item.nodeId
|
||||
this.getRecordList()
|
||||
},
|
||||
getTimeLineTagColor(status) {
|
||||
return status == 1 || status == 2 ? '#08AF28' : status != 3 ? '#0177FF' : '#ed6f6f';
|
||||
},
|
||||
getRecordList() {
|
||||
let data = {
|
||||
taskId: this.taskInfo.id,
|
||||
nodeId: this.nodeId
|
||||
}
|
||||
recordList(data).then(res => {
|
||||
let list = res.data || []
|
||||
list.map(o => {
|
||||
o.fileList = JSON.parse(o.fileList)
|
||||
})
|
||||
this.recordList = list
|
||||
this.$nextTick(() => {
|
||||
this.$refs.TimeLinePopup.open()
|
||||
})
|
||||
})
|
||||
},
|
||||
getOutsideState(state) {
|
||||
return state ? '成功' : '失败';
|
||||
},
|
||||
handleShowErrorModal(e) {
|
||||
let data = {
|
||||
errorData: e.errorData,
|
||||
errorTip: e.errorTip
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: '/pages/workFlow/flowBefore/logError?data=' + this.jnpf.base64.encode(JSON.stringify(
|
||||
data),
|
||||
"UTF-8"),
|
||||
})
|
||||
},
|
||||
handleRetry(e) {
|
||||
retryOutside(e.nodeId).then((res) => {
|
||||
uni.showToast({
|
||||
title: res.msg,
|
||||
complete: () => {
|
||||
uni.$emit('refresh')
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.u-node {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.active {
|
||||
background: #02a7f0;
|
||||
}
|
||||
|
||||
.content {
|
||||
.u-order-title {
|
||||
.name {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-box {
|
||||
::v-deep .u-avatar {
|
||||
// width: 2rem !important;
|
||||
// height: 2rem !important;
|
||||
}
|
||||
}
|
||||
.outside-sign {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 40px;
|
||||
padding: 0 16px;
|
||||
cursor: pointer;
|
||||
background-color: #F5F5F5;
|
||||
|
||||
.btn-link {
|
||||
background: none;
|
||||
border: none;
|
||||
color: #007AFF;
|
||||
padding: 0;
|
||||
font-size: 28rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.danger {
|
||||
color: #ff0000;
|
||||
padding-left: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.approver-list {
|
||||
border-radius: 8rpx;
|
||||
min-height: 140rpx;
|
||||
background-color: #F5F5F5;
|
||||
|
||||
.approver-item {
|
||||
.approver-list-l {
|
||||
flex: 1;
|
||||
|
||||
.approver-list-l-box {
|
||||
width: 120rpx;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
.tag {
|
||||
position: absolute;
|
||||
top: 50rpx;
|
||||
}
|
||||
|
||||
.approver-user-name {
|
||||
color: #303133;
|
||||
width: 120rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.approver-list-r {
|
||||
height: 4.375rem;
|
||||
|
||||
.approver-list-r-box {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-block {
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-top: 1rpx solid #e5e5e5;
|
||||
|
||||
:deep(.u-tag) {
|
||||
padding: 8rpx;
|
||||
background-color: rgb(165, 168, 172);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
173
pages/workFlow/components/RecordTimeList/TimeLinePopup.vue
Normal file
@@ -0,0 +1,173 @@
|
||||
<template>
|
||||
<uni-popup ref="flowStepPopup" background-color="#fff" border-radius="8rpx 8rpx 0 0" :is-mask-click="false">
|
||||
<view class="timeLine-popup-content u-flex-col">
|
||||
<view class="u-flex head-title">
|
||||
<text class="text">{{popupTitle}}</text>
|
||||
<text class="text icon-ym icon-ym-fail" @click="popupClose"></text>
|
||||
</view>
|
||||
<view class="content" v-for="item,index in recordList" :key="index" v-if="recordList.length">
|
||||
<!--头部 -->
|
||||
<view class="u-flex u-m-t-20 content-info">
|
||||
<view class="u-flex content-info-left">
|
||||
<u-avatar :src="baseURL + item.headIcon" size="mini" mode="circle" class="avatar"></u-avatar>
|
||||
<view class="u-m-l-10 name-box">
|
||||
<p>{{item.userName}}</p>
|
||||
<p class="name">
|
||||
{{item.handleTime?$u.timeFormat(item.handleTime, 'yyyy-mm-dd hh:MM:ss'):''}}
|
||||
</p>
|
||||
</view>
|
||||
</view>
|
||||
<u-tag :text="useDefine.getFlowStateContent(item.handleType)"
|
||||
:border-color="useDefine.getHexColor(useDefine.getFlowStateColor(item.handleType))"
|
||||
:bg-color="useDefine.getHexColor(useDefine.getFlowStateColor(item.handleType))" color="#fff"
|
||||
size="mini" shape="circle" />
|
||||
<view class="content-info-right u-line-1" v-if="item.handleUserName">
|
||||
<u-icon name="arrow-rightward" color="#1890ff" class="u-m-l-10 u-m-r-10"></u-icon>
|
||||
<text class="u-font-24 txt u-line-1">{{item.handleUserName}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="content-info-bottom" v-if="item.signImg || item.fileList?.length || item.handleOpinion">
|
||||
<text class="u-line-2" v-if="item.handleOpinion">{{item.handleOpinion}}</text>
|
||||
<fileList :fileList="item.fileList" v-if="item?.fileList?.length"></fileList>
|
||||
<view class="u-flex sign-box" v-if="item.signImg">
|
||||
<view class="sign-title">签名:</view>
|
||||
<JnpfSign v-model="item.signImg" align="left" detailed />
|
||||
</view>
|
||||
<view class="approvalField" v-for="(field,index) in item.approvalField" :key="index">
|
||||
<text>{{field.fieldName+':'}}</text>
|
||||
<text>{{field.value}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<JnpfEmpty v-else />
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import fileList from './fileList.vue'
|
||||
import {
|
||||
useDefineSetting
|
||||
} from '@/utils/useDefineSetting';
|
||||
export default {
|
||||
components: {
|
||||
fileList
|
||||
},
|
||||
props: {
|
||||
recordList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
popupTitle: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
useDefine: useDefineSetting(),
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.flowStepPopup.open('bottom')
|
||||
})
|
||||
},
|
||||
popupClose() {
|
||||
this.$refs.flowStepPopup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.timeLine-popup-content {
|
||||
padding: 20rpx;
|
||||
height: 1200rpx;
|
||||
overflow-y: scroll;
|
||||
|
||||
.head-title {
|
||||
justify-content: space-between;
|
||||
color: #333333;
|
||||
/* #ifdef APP-PLUS */
|
||||
padding: 20rpx 0;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.content {
|
||||
.content-info {
|
||||
height: 100rpx;
|
||||
|
||||
.content-info-left {
|
||||
flex: 1;
|
||||
|
||||
.name-box {
|
||||
.name {
|
||||
color: #606266;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-info-right {
|
||||
max-width: 228rpx;
|
||||
|
||||
.txt {
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-info-bottom {
|
||||
background-color: #F5F5F5;
|
||||
padding: 20rpx;
|
||||
border-radius: 8rpx;
|
||||
color: #303133;
|
||||
|
||||
.approvalField {
|
||||
padding: 10rpx 0;
|
||||
}
|
||||
|
||||
.sign-box {
|
||||
height: 88rpx;
|
||||
|
||||
.sign-title {
|
||||
width: 120rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-info-process {
|
||||
.info-process-item {
|
||||
border-bottom: 1rpx solid #d7d7d7;
|
||||
padding-bottom: 26rpx;
|
||||
|
||||
.process-item-head {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.process-list {
|
||||
background-color: #f1f4f8;
|
||||
border-radius: 8rpx;
|
||||
|
||||
.list {
|
||||
height: 68rpx;
|
||||
align-items: center;
|
||||
border-bottom: 1rpx solid #e7e9ec;
|
||||
justify-content: space-between;
|
||||
|
||||
.r-txt {
|
||||
color: #0000ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
125
pages/workFlow/components/RecordTimeList/fileList.vue
Normal file
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<view class="" style="padding: 20rpx 0;">
|
||||
<view v-for='(item,index) in fileList' :key="index"
|
||||
class="jnpf-file-item u-type-primary u-flex u-line-1 u-m-t-10" @tap='downLoad(item)'>
|
||||
<view class="jnpf-file-item-txt u-line-1">{{item.name}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
const imgTypeList = ['png', 'jpg', 'jpeg', 'bmp', 'gif']
|
||||
import {
|
||||
getDownloadUrl
|
||||
} from '@/api/common'
|
||||
import jnpf from '@/utils/jnpf'
|
||||
export default {
|
||||
props: {
|
||||
fileList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
downLoad(item) {
|
||||
if (item.fileExtension && imgTypeList.includes(item.fileExtension)) return this.previewImage(item)
|
||||
// #ifdef MP
|
||||
this.previewFile(item)
|
||||
// #endif
|
||||
// #ifndef MP
|
||||
getDownloadUrl('annex', item.fileId).then(res => {
|
||||
const fileUrl = this.baseURL + res.data.url + '&name=' + item.name;
|
||||
// #ifdef H5
|
||||
window.location.href = fileUrl;
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
this.downloadFile(res.data.url);
|
||||
// #endif
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
previewFile(item) {
|
||||
let fileTypes = ['doc', 'xls', 'ppt', 'pdf', 'docx', 'xlsx', 'pptx']
|
||||
let url = item.url
|
||||
let fileType = url.split('.')[1]
|
||||
if (fileTypes.includes(fileType)) {
|
||||
uni.downloadFile({
|
||||
url: this.baseURL + url,
|
||||
success: (res) => {
|
||||
var filePath = res.tempFilePath;
|
||||
uni.openDocument({
|
||||
filePath: encodeURI(filePath),
|
||||
showMenu: true,
|
||||
fileType: fileType,
|
||||
success: (res) => {
|
||||
console.log('打开文档成功');
|
||||
},
|
||||
fail(err) {
|
||||
console.log('小程序', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.$u.toast(
|
||||
'该文件类型无法打开'
|
||||
)
|
||||
}
|
||||
},
|
||||
previewImage(item) {
|
||||
if (!item.url) return
|
||||
const url = jnpf.getAuthImgUrl(item.url)
|
||||
uni.previewImage({
|
||||
urls: [url],
|
||||
current: url,
|
||||
success: () => {},
|
||||
fail: () => {
|
||||
uni.showToast({
|
||||
title: '预览图片失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
downloadFile(url) {
|
||||
uni.downloadFile({
|
||||
url: this.baseURL + url,
|
||||
success: res => {
|
||||
if (res.statusCode === 200) {
|
||||
uni.saveFile({
|
||||
tempFilePath: res.tempFilePath,
|
||||
success: red => {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
mask: true,
|
||||
title: '文件已保存:' + red.savedFilePath, //保存路径
|
||||
duration: 3000,
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.openDocument({
|
||||
filePath: red.savedFilePath,
|
||||
success: ress => {},
|
||||
fail(err) {}
|
||||
});
|
||||
}, 500)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
228
pages/workFlow/components/RecordTimeList/index.vue
Normal file
@@ -0,0 +1,228 @@
|
||||
<template>
|
||||
<view class="flowStep u-m-t-20">
|
||||
<view class="tabsContent">
|
||||
<u-tabs :list="getList" :current="current" @change="change"></u-tabs>
|
||||
<view class="time-line-box" v-if="opType != '-1'">
|
||||
<TimeLine :progressList="progressList" :taskInfo="taskInfo" v-if="tabId == 0"></TimeLine>
|
||||
<ProcessComments ref="ProcessComments" v-if="tabId == 1" :taskId="taskId" @handleReply="handleReply">
|
||||
</ProcessComments>
|
||||
<view class="u-p-l-20 u-p-r-20" v-if="tabId == 2">
|
||||
<dataLog :dataLogList="dataLogList"></dataLog>
|
||||
</view>
|
||||
<assistantMsg v-if="tabId == 3" :auxiliaryInfo="auxiliaryInfo" :formData="formData"></assistantMsg>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import TimeLine from './TimeLine.vue'
|
||||
import dataLog from '@/components/dataLog'
|
||||
import ProcessComments from './ProcessComments.vue'
|
||||
import assistantMsg from '@/components/assistantMsg'
|
||||
export default {
|
||||
components: {
|
||||
ProcessComments,
|
||||
TimeLine,
|
||||
dataLog,
|
||||
assistantMsg
|
||||
},
|
||||
props: {
|
||||
dataLogList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
progressList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
commentList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
taskInfo: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
formData: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
auxiliaryInfo: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
taskId: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
hasComment: {
|
||||
default: false
|
||||
},
|
||||
dataLog: {
|
||||
default: false
|
||||
},
|
||||
formID: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
opType: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
current: 0,
|
||||
value: '',
|
||||
popupTitle: '',
|
||||
nodeId: '',
|
||||
tabId: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
},
|
||||
getList() {
|
||||
const list = [];
|
||||
const OP_TYPE_INVALID = '-1';
|
||||
if (this.opType !== OP_TYPE_INVALID) {
|
||||
list.push({
|
||||
name: '流转',
|
||||
id: 0
|
||||
});
|
||||
if (this.hasComment) {
|
||||
list.push({
|
||||
name: '评论',
|
||||
id: 1
|
||||
});
|
||||
};
|
||||
if (this.dataLog) {
|
||||
list.push({
|
||||
name: '修改记录',
|
||||
id: 2
|
||||
})
|
||||
}
|
||||
}
|
||||
if (this.auxiliaryInfo.length) {
|
||||
list.push({
|
||||
name: '辅助信息',
|
||||
id: 3
|
||||
});
|
||||
}
|
||||
return list
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleReply(id) {
|
||||
this.$emit('handleReply', id)
|
||||
},
|
||||
popupClose() {
|
||||
this.$refs.flowStepPopup.close()
|
||||
},
|
||||
change(e) {
|
||||
this.current = e
|
||||
this.tabId = this.getList[e].id
|
||||
if (this.current === 1) {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.ProcessComments.getCommentList()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.flowStep {
|
||||
width: 100%;
|
||||
|
||||
.tabsContent {
|
||||
.time-line-box {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.bottom-btn {
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
padding: 0 20rpx;
|
||||
color: #7f7f7f;
|
||||
|
||||
.btn {
|
||||
background-color: #f2f2f2;
|
||||
border-radius: 8rpx;
|
||||
height: 60rpx;
|
||||
padding-left: 10rpx;
|
||||
width: 100%;
|
||||
line-height: 60rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.timeLine {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 20rpx;
|
||||
|
||||
.u-time-axis-item {
|
||||
.u-time-axis-node {
|
||||
top: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.timeLine-right {
|
||||
padding-left: 0;
|
||||
padding-right: 40rpx !important;
|
||||
|
||||
&::before {
|
||||
left: 670rpx !important;
|
||||
}
|
||||
|
||||
.u-time-axis-item {
|
||||
.u-time-axis-node {
|
||||
left: 670rpx !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.timeLine-dot {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
border: 4rpx solid #FFFFFF;
|
||||
box-shadow: 0 6rpx 12rpx rgba(2, 7, 28, 0.16);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.timeLine-content {
|
||||
padding: 0 10rpx;
|
||||
|
||||
.timeLine-title {
|
||||
font-size: 30rpx;
|
||||
line-height: 36rpx;
|
||||
|
||||
.name {
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.timeLine-title2 {
|
||||
margin-top: 6rpx;
|
||||
background: rgba(255, 255, 255, 0.39);
|
||||
box-shadow: 0px 3px 10px rgba(0, 0, 0, 0.1);
|
||||
padding: 10rpx 20rpx;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.timeLine-desc {
|
||||
margin-top: 10rpx;
|
||||
font-size: 26rpx;
|
||||
line-height: 36rpx;
|
||||
color: #909399;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
126
pages/workFlow/components/fileList.vue
Normal file
@@ -0,0 +1,126 @@
|
||||
<template>
|
||||
<view class="" style="padding: 20rpx 0;">
|
||||
<view v-for='(item,index) in fileList' :key="index"
|
||||
class="jnpf-file-item u-type-primary u-flex u-line-1 u-m-t-10" @tap='downLoad(item)'>
|
||||
<view class="jnpf-file-item-txt u-line-1">{{item.name}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const imgTypeList = ['png', 'jpg', 'jpeg', 'bmp', 'gif']
|
||||
import {
|
||||
getDownloadUrl
|
||||
} from '@/api/common'
|
||||
import jnpf from '@/utils/jnpf'
|
||||
export default {
|
||||
props: {
|
||||
fileList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
downLoad(item) {
|
||||
if (item.fileExtension && imgTypeList.includes(item.fileExtension)) return this.previewImage(item)
|
||||
// #ifdef MP
|
||||
this.previewFile(item)
|
||||
// #endif
|
||||
// #ifndef MP
|
||||
getDownloadUrl('annex', item.fileId).then(res => {
|
||||
const fileUrl = this.baseURL + res.data.url + '&name=' + item.name;
|
||||
// #ifdef H5
|
||||
window.location.href = fileUrl;
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
this.downloadFile(res.data.url);
|
||||
// #endif
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
previewFile(item) {
|
||||
let fileTypes = ['doc', 'xls', 'ppt', 'pdf', 'docx', 'xlsx', 'pptx']
|
||||
let url = item.url
|
||||
let fileType = url.split('.')[1]
|
||||
if (fileTypes.includes(fileType)) {
|
||||
uni.downloadFile({
|
||||
url: this.baseURL + url,
|
||||
success: (res) => {
|
||||
var filePath = res.tempFilePath;
|
||||
uni.openDocument({
|
||||
filePath: encodeURI(filePath),
|
||||
showMenu: true,
|
||||
fileType: fileType,
|
||||
success: (res) => {
|
||||
console.log('打开文档成功');
|
||||
},
|
||||
fail(err) {
|
||||
console.log('小程序', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.$u.toast(
|
||||
'该文件类型无法打开'
|
||||
)
|
||||
}
|
||||
},
|
||||
previewImage(item) {
|
||||
if (!item.url) return
|
||||
const url = jnpf.getAuthImgUrl(item.url)
|
||||
uni.previewImage({
|
||||
urls: [url],
|
||||
current: url,
|
||||
success: () => {},
|
||||
fail: () => {
|
||||
uni.showToast({
|
||||
title: '预览图片失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
downloadFile(url) {
|
||||
uni.downloadFile({
|
||||
url: this.baseURL + url,
|
||||
success: res => {
|
||||
if (res.statusCode === 200) {
|
||||
uni.saveFile({
|
||||
tempFilePath: res.tempFilePath,
|
||||
success: red => {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
mask: true,
|
||||
title: '文件已保存:' + red.savedFilePath, //保存路径
|
||||
duration: 3000,
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.openDocument({
|
||||
filePath: red.savedFilePath,
|
||||
success: ress => {},
|
||||
fail(err) {}
|
||||
});
|
||||
}, 500)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
150
pages/workFlow/components/flowBtn.vue
Normal file
@@ -0,0 +1,150 @@
|
||||
<template>
|
||||
<view class="flowBefore-actions" :style="{'height': '88rpx'}"
|
||||
v-if="hasComment || (actionList.length || rightBtnList.length) ">
|
||||
<CustomButton v-if="showMoreBtn" btnText="更多" btnType="more" iconName="more-dot-fill" size="28"
|
||||
@handleBtn="showAction = $event" :btnLoading="loading" class="u-flex-col buttom-btn-left-inner" />
|
||||
<template v-if="opType != 2">
|
||||
<CustomButton v-if="showSaveBtn" :btnText="saveBtnText || '暂存'" customIcon
|
||||
class="u-flex-col buttom-btn-left-inner" btnIcon="icon-ym icon-ym-extend-save" size="28"
|
||||
@handleBtn="handleBtn('save')" btnType="save" :btnLoading="loading" />
|
||||
<CustomButton v-if="showRejectBtn" btnText="拒绝" iconName="minus-circle" size="28"
|
||||
@handleBtn="handleBtn('reject')" btnType="reject" :btnLoading="loading"
|
||||
class="u-flex-col buttom-btn-left-inner" />
|
||||
</template>
|
||||
<view class="rightBtn u-flex">
|
||||
<u-button class="buttom-btn" @click.stop="handleBtn('comment')" v-if="!rightBtnList.length"
|
||||
:loading="loading">
|
||||
评论
|
||||
</u-button>
|
||||
<template v-if="opType != 2">
|
||||
<u-button v-for="btn,index in rightBtnList" :key="index" class="buttom-btn"
|
||||
@click.stop="handleBtn(btn.id)" :style="{'width':btn.width}"
|
||||
:class="{'delegate-submit-btn':btn.id === 'delegateSubmit'}" :loading="loading" :type="btn?.type">
|
||||
{{ btn.fullName}}
|
||||
</u-button>
|
||||
</template>
|
||||
<template class="" v-else>
|
||||
<u-button v-for="btn,index in todoBtnList" :key="index" class="buttom-btn"
|
||||
@click.stop="handleBtn(btn.id)" :style="{'width':btn.width}" :loading="loading" :type="btn?.type">
|
||||
{{ btn.fullName}}
|
||||
</u-button>
|
||||
</template>
|
||||
</view>
|
||||
<u-action-sheet v-model="showAction" :list="actionList" @click="handleAction" />
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import CustomButton from '@/components/CustomButton'
|
||||
export default {
|
||||
components: {
|
||||
CustomButton
|
||||
},
|
||||
props: {
|
||||
actionList: {
|
||||
type: Array,
|
||||
default: () => ([])
|
||||
},
|
||||
rightBtnList: {
|
||||
type: Array,
|
||||
default: () => ([])
|
||||
},
|
||||
todoBtnList: {
|
||||
type: Array,
|
||||
default: () => ([])
|
||||
},
|
||||
btnInfo: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
opType: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
saveBtnText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
btnLoading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hideSaveBtn: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hasSignFor: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hasComment: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isProcessing: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
loading() {
|
||||
return this.btnLoading
|
||||
},
|
||||
showMoreBtn() {
|
||||
if (this.actionList.length) return true
|
||||
return false
|
||||
},
|
||||
showRejectBtn() {
|
||||
if (this.btnInfo?.hasRejectBtn && !this.isProcessing && this.opType != 2) return true
|
||||
return false
|
||||
},
|
||||
showSaveBtn() {
|
||||
if (this.btnInfo?.hasSaveBtn && !this.hideSaveBtn) return true
|
||||
return false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showAction: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleBtn(type, item) {
|
||||
if (!this.loading) this.$emit('handleBtn', type, item)
|
||||
},
|
||||
//更多按钮
|
||||
handleAction(index) {
|
||||
this.handleBtn(this.actionList[index].id, this.actionList[index])
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.flowBefore-actions {
|
||||
.poup-btn {
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
padding: 0 20rpx;
|
||||
color: #7f7f7f;
|
||||
border-bottom: 1rpx solid #d7d7d7;
|
||||
|
||||
.btn {
|
||||
background-color: #f2f2f2;
|
||||
border-radius: 8rpx;
|
||||
height: 60rpx;
|
||||
padding-left: 10rpx;
|
||||
width: 100%;
|
||||
line-height: 60rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.delegate-submit-btn {
|
||||
background-color: #50abf6;
|
||||
|
||||
button {
|
||||
background-color: #50abf6 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
372
pages/workFlow/components/flowStep.vue
Normal file
@@ -0,0 +1,372 @@
|
||||
<template>
|
||||
<view class="flowStep u-m-t-20">
|
||||
<view class="tabsContent">
|
||||
<u-tabs :list="list" :current="current" @change="change"></u-tabs>
|
||||
<view class="u-p-l-20 u-p-r-20 time-line-box">
|
||||
<view class="u-p-l-20 u-p-r-20 u-p-t-20" v-if="current == 0">
|
||||
<TimeLine :progressList="progressList" :taskInfo="taskInfo"></TimeLine>
|
||||
<!-- <u-time-line>
|
||||
<u-time-line-item nodeTop="2" class="u-p-b-20" v-for="item,index in progressList" :key="index">
|
||||
<template v-slot:node>
|
||||
<view class="u-node"></view>
|
||||
</template>
|
||||
<template v-slot:content>
|
||||
<view class="u-font-24 content">
|
||||
<view class="u-order-title u-flex u-m-b-8">
|
||||
<view class="u-line-1 name">
|
||||
{{item.nodeName + getCounterSignContent(item.counterSign)}}
|
||||
</view>
|
||||
<view class="u-m-l-10">
|
||||
<u-tag :text="getNodeStatusContent(item.nodeStatus)" mode="light"
|
||||
size="mini" shape="circle"
|
||||
:type="getNodeStatusColor(item.nodeStatus)" />
|
||||
<text
|
||||
class="u-m-l-10">{{item.startTime?$u.timeFormat(item.startTime, 'mm-dd hh:MM'):''}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-flex avatar-box" v-if="item.nodeStatus == 1">
|
||||
<u-avatar :src="baseURL + taskInfo.headIcon" size="mini" mode="circle"
|
||||
class="avatar"></u-avatar>
|
||||
<text class="u-m-l-8">发起人:{{taskInfo.creatorUser}}</text>
|
||||
</view>
|
||||
<view class="u-flex approver-list" v-else>
|
||||
<view class="u-flex approver-list-l">
|
||||
<view class="u-flex-col approver-list-l-box"
|
||||
v-for="child,i in item.approver" :key="i">
|
||||
<u-avatar :src="baseURL + taskInfo.headIcon" size="mini" mode="circle"
|
||||
class="avatar"></u-avatar>
|
||||
<u-tag :text="useDefine.getFlowStateContent(child.handleType)"
|
||||
mode="light" v-if="useDefine.getFlowStateContent(child.handleType)"
|
||||
class="tag" size="mini"
|
||||
:border-color="useDefine.getHexColor(useDefine.getFlowStateColor(child.handleType))"
|
||||
:bg-color="useDefine.getHexColor(useDefine.getFlowStateColor(child.handleType))"
|
||||
color="#fff" />
|
||||
<text class="u-m-t-20 u-line-1 approver-user-name">
|
||||
{{child.userName}}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-m-l-20 approver-list-r u-flex" @click="openApprover(item)">
|
||||
<view class="approver-list-r-box">{{item.approverCount}}</view>
|
||||
<text class="icon-ym icon-ym-right u-m-r-12"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</u-time-line-item>
|
||||
</u-time-line> -->
|
||||
</view>
|
||||
<view class="u-p-l-20 u-p-r-20" v-if="current == 1">
|
||||
2
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<uni-popup ref="flowStepPopup" background-color="#fff" border-radius="8rpx 8rpx 0 0" :is-mask-click="false">
|
||||
<view class="flow-popup-content" style="height: 1200rpx;">
|
||||
<view class="u-flex head-title">
|
||||
<text class="text">{{popupTitle}}</text>
|
||||
<text class="text icon-ym icon-ym-fail" @click="popupClose"></text>
|
||||
</view>
|
||||
<view class="" v-for="item,index in recordList" :key="index" v-if="recordList.length">
|
||||
<view class="u-flex u-m-t-20" style="height: 100rpx;">
|
||||
<view class="u-flex" style="flex: 1;">
|
||||
<u-avatar :src="baseURL + taskInfo.headIcon" size="mini" mode="circle"
|
||||
class="avatar"></u-avatar>
|
||||
<view class="u-m-l-10">
|
||||
<p>{{item.userName}}</p>
|
||||
<p style="color: #606266;">
|
||||
{{item.handleTime?$u.timeFormat(item.handleTime, 'yyyy-mm-dd hh:MM:ss'):''}}
|
||||
</p>
|
||||
</view>
|
||||
</view>
|
||||
<u-tag :text="useDefine.getFlowStateContent(item.handleType)"
|
||||
:border-color="useDefine.getHexColor(useDefine.getFlowStateColor(item.handleType))"
|
||||
:bg-color="useDefine.getHexColor(useDefine.getFlowStateColor(item.handleType))" color="#fff"
|
||||
size="mini" shape="circle" />
|
||||
<view class="" v-if="item.handleUserName">
|
||||
<u-icon name="arrow-rightward" color="#1890ff" class="u-m-l-10 u-m-r-10"></u-icon>
|
||||
<text class="u-font-24" style="color: #303133;">{{item.handleUserName}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" style="background-color: #F5F5F5;padding: 20rpx;border-radius: 8rpx;color: #303133;"
|
||||
v-if="item.signImg || item.fileList.length || item.handleOpinion">
|
||||
<text class="u-line-2" v-if="item.handleOpinion">{{item.handleOpinion}}</text>
|
||||
<fileList :fileList="item.fileList" v-if="item.fileList.length"></fileList>
|
||||
<view class="u-flex" style="height: 88rpx;" v-if="item.signImg">
|
||||
<view style="width: 60px;">签名:</view>
|
||||
<JnpfSign v-model="item.signImg" align="left" detailed />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<JnpfEmpty v-else />
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import fileList from './fileList.vue'
|
||||
import TimeLine from './TimeLine.vue'
|
||||
import {
|
||||
useDefineSetting
|
||||
} from '@/utils/useDefineSetting';
|
||||
import {
|
||||
recordList
|
||||
} from '@/api/workFlow/flowBefore'
|
||||
const imgTypeList = ['png', 'jpg', 'jpeg', 'bmp', 'gif']
|
||||
export default {
|
||||
components: {
|
||||
fileList,
|
||||
TimeLine
|
||||
},
|
||||
props: {
|
||||
progressList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
taskInfo: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: [{
|
||||
name: '流转'
|
||||
}, {
|
||||
name: '评论'
|
||||
}],
|
||||
current: 0,
|
||||
value: '',
|
||||
popupTitle: '',
|
||||
recordList: [],
|
||||
nodeId: '',
|
||||
useDefine: useDefineSetting()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openApprover(item) {
|
||||
this.popupTitle = item.nodeName + this.getCounterSignContent(item.counterSign, item.assigneeType)
|
||||
this.nodeId = item.nodeId
|
||||
this.$nextTick(() => {
|
||||
this.$refs.flowStepPopup.open('bottom')
|
||||
this.getRecordList()
|
||||
})
|
||||
},
|
||||
getRecordList() {
|
||||
let data = {
|
||||
taskId: this.taskInfo.id,
|
||||
nodeId: this.nodeId
|
||||
}
|
||||
recordList(data).then(res => {
|
||||
let list = res.data || []
|
||||
list.map(o => {
|
||||
o.fileList = JSON.parse(o.fileList)
|
||||
})
|
||||
this.recordList = list
|
||||
})
|
||||
},
|
||||
getCounterSignContent(counterSign, assigneeType) {
|
||||
if (assigneeType == 10) return '(逐级审批)';
|
||||
return counterSign == 0 ? '(或签)' : counterSign == 1 ? '(会签)' : '(依次审批)';
|
||||
},
|
||||
popupClose() {
|
||||
this.$refs.flowStepPopup.close()
|
||||
},
|
||||
getNodeStatusContent(status) {
|
||||
const list = ['', '已提交', '已通过', '已拒绝', '审批中'];
|
||||
return list[status] || '';
|
||||
},
|
||||
|
||||
getNodeStatusColor(status) {
|
||||
return status == 1 || status == 2 ? 'success' : status == 3 ? 'error' : 'primary';
|
||||
},
|
||||
change(e) {
|
||||
this.current = e
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.flow-popup-content {
|
||||
padding: 20rpx;
|
||||
|
||||
.head-title {
|
||||
|
||||
justify-content: space-between;
|
||||
color: #333333;
|
||||
// border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.flowStep {
|
||||
width: 100%;
|
||||
|
||||
.tabsContent {
|
||||
.time-line-box {
|
||||
background-color: #fff;
|
||||
|
||||
.u-node {
|
||||
background: #19be6b;
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.active {
|
||||
background: #02a7f0;
|
||||
}
|
||||
|
||||
.content {
|
||||
.u-order-title {
|
||||
.name {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-box {
|
||||
::v-deep .u-avatar {
|
||||
width: 2rem !important;
|
||||
height: 2rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
.approver-list {
|
||||
border-radius: 8rpx;
|
||||
height: 140rpx;
|
||||
background-color: #F5F5F5;
|
||||
|
||||
.approver-list-l {
|
||||
flex: 1;
|
||||
|
||||
.approver-list-l-box {
|
||||
width: 120rpx;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
.tag {
|
||||
position: absolute;
|
||||
top: 50rpx;
|
||||
}
|
||||
|
||||
.approver-user-name {
|
||||
color: #303133;
|
||||
width: 120rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.approver-list-r {
|
||||
height: 4.375rem;
|
||||
|
||||
.approver-list-r-box {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-btn {
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
padding: 0 20rpx;
|
||||
color: #7f7f7f;
|
||||
|
||||
.btn {
|
||||
background-color: #f2f2f2;
|
||||
border-radius: 8rpx;
|
||||
height: 60rpx;
|
||||
padding-left: 10rpx;
|
||||
width: 100%;
|
||||
line-height: 60rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .u-time-axis-item {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.timeLine {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 20rpx;
|
||||
|
||||
.u-time-axis-item {
|
||||
.u-time-axis-node {
|
||||
top: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.timeLine-right {
|
||||
padding-left: 0;
|
||||
padding-right: 40rpx !important;
|
||||
|
||||
&::before {
|
||||
left: 670rpx !important;
|
||||
}
|
||||
|
||||
.u-time-axis-item {
|
||||
.u-time-axis-node {
|
||||
left: 670rpx !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.timeLine-dot {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
border: 4rpx solid #FFFFFF;
|
||||
box-shadow: 0 6rpx 12rpx rgba(2, 7, 28, 0.16);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.timeLine-content {
|
||||
padding: 0 10rpx;
|
||||
|
||||
.timeLine-title {
|
||||
font-size: 30rpx;
|
||||
line-height: 36rpx;
|
||||
|
||||
.name {
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.timeLine-title2 {
|
||||
margin-top: 6rpx;
|
||||
background: rgba(255, 255, 255, 0.39);
|
||||
box-shadow: 0px 3px 10px rgba(0, 0, 0, 0.1);
|
||||
padding: 10rpx 20rpx;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.timeLine-desc {
|
||||
margin-top: 10rpx;
|
||||
font-size: 26rpx;
|
||||
line-height: 36rpx;
|
||||
color: #909399;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
203
pages/workFlow/document/components/AddFilePopup.vue
Normal file
@@ -0,0 +1,203 @@
|
||||
<template>
|
||||
<u-popup class="jnpf-select" :maskCloseAble="maskCloseAble" mode="bottom" v-model="showPopup"
|
||||
:safeAreaInsetBottom="safeAreaInsetBottom" @close="close">
|
||||
<view class="u-select">
|
||||
<view class="u-select__header" @touchmove.stop.prevent="">
|
||||
<view class="u-select__header__cancel u-select__header__btn" :style="{ color: cancelColor }"
|
||||
hover-class="u-hover-class" :hover-stay-time="150" @tap="close()"
|
||||
style="width: 60rpx;text-align: center;">
|
||||
<text v-if="cancelBtn">{{cancelText}}</text>
|
||||
</view>
|
||||
<view class="u-select__header__title" style="flex: 1;text-align: center;">
|
||||
{{title}}
|
||||
</view>
|
||||
<view class="u-select__header__confirm u-select__header__btn" :style="{ color: confirmColor }"
|
||||
style="width: 60rpx;text-align: center;" hover-class="u-hover-class" :hover-stay-time="150"
|
||||
@touchmove.stop="" @tap.stop="handleConfirm()">
|
||||
<text v-if="confirmBtn">{{confirmText}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="u-select__body u-select__body__multiple">
|
||||
<scroll-view :scroll-y="true" style="height: 100%">
|
||||
<view class="u-flex u-p-l-20 u-p-r-20" style="height: 100rpx;border-bottom: 1rpx solid #f0f2f6;"
|
||||
@click="radioGroupChange('add')">
|
||||
<text class="u-m-r-20 u-font-28 icon-ym icon-ym-add-folder"></text>
|
||||
<text>新建文件夹</text>
|
||||
</view>
|
||||
<view class="u-flex u-p-l-20 u-p-r-20 uploadFileBtn" @click="radioGroupChange('up')">
|
||||
<JnpfUploadFileComment ref="lsjUpload" height="100rpx" childId="upload" :size="10"
|
||||
:parentId="parentId" @callback="onCallback">
|
||||
</JnpfUploadFileComment>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
height: {
|
||||
type: [Number, String],
|
||||
default: ''
|
||||
},
|
||||
cancelBtn: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
confirmBtn: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
cancelColor: {
|
||||
type: String,
|
||||
default: '#606266'
|
||||
},
|
||||
confirmColor: {
|
||||
type: String,
|
||||
default: '#2979ff'
|
||||
},
|
||||
safeAreaInsetBottom: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
maskCloseAble: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
parentId: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: '取消'
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: '确认'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showPopup: false,
|
||||
option: {},
|
||||
id: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
show: {
|
||||
handler(val) {
|
||||
this.showPopup = val
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
},
|
||||
token() {
|
||||
return uni.getStorageSync('token')
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
//文件上传
|
||||
onCallback(e) {
|
||||
this.$emit('onCallback', e)
|
||||
},
|
||||
// 获取默认选中的值
|
||||
radioGroupChange(e) {
|
||||
this.$emit('confirm', e)
|
||||
},
|
||||
close() {
|
||||
this.$emit('close');
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.notData-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: -50px;
|
||||
|
||||
.notData-inner {
|
||||
width: 286rpx;
|
||||
height: 222rpx;
|
||||
align-items: center;
|
||||
|
||||
.iconImg {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.notData-inner-text {
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
|
||||
.uploadFileBtn {
|
||||
height: 3.125rem;
|
||||
}
|
||||
|
||||
.jnpf-select {
|
||||
width: 100%;
|
||||
|
||||
.u-select {
|
||||
&__header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 40px;
|
||||
padding: 0 20px;
|
||||
position: relative;
|
||||
|
||||
::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
border-bottom: 0.5px solid #eaeef1;
|
||||
transform: scaleY(0.5);
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__body {
|
||||
width: 100%;
|
||||
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
|
||||
&__picker-view {
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
&__item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32rpx;
|
||||
padding: 0 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
91
pages/workFlow/document/components/DocHead.vue
Normal file
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<view class="notice-warp" :style="{height:noticeWarpH + 'px'}">
|
||||
<view class="search-box" style="background-color: #fff;">
|
||||
<u-search :placeholder="$t('app.apply.pleaseKeyword')" v-model="keyword" height="72" :show-action="false"
|
||||
@change="search" bg-color="#f0f2f6" shape="square" />
|
||||
</view>
|
||||
<CommonTabs class="commonTabs" :list="categoryList" @change="change" :current="current" ref="CommonTabs"
|
||||
:icon="icon" type="doc" @iconClick="iconClick">
|
||||
</CommonTabs>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mixin from "../mixin.js"
|
||||
import CommonTabs from '@/components/CommonTabs'
|
||||
export default {
|
||||
mixins: [mixin],
|
||||
components: {
|
||||
CommonTabs
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
icon: 'icon-ym icon-ym-thumb-mode',
|
||||
keyword: '',
|
||||
current: 0,
|
||||
categoryList: [{
|
||||
fullName: '我的文档',
|
||||
|
||||
}, {
|
||||
fullName: '我的共享'
|
||||
}, {
|
||||
fullName: '共享给我'
|
||||
}, {
|
||||
fullName: '回收站'
|
||||
}],
|
||||
commonTabs: 0,
|
||||
noticeWarpH: 0
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getContentHeight()
|
||||
},
|
||||
methods: {
|
||||
async getContentHeight() {
|
||||
const windowHeight = this.$u.sys().windowHeight;
|
||||
const [commonTabs, searchBox] = await Promise.all([
|
||||
this.$uGetRect('.search-box'),
|
||||
this.$uGetRect('.commonTabs')
|
||||
]);
|
||||
this.commonTabs = commonTabs.height
|
||||
this.searchBox = searchBox.height
|
||||
this.noticeWarpH = this.commonTabs + this.searchBox
|
||||
// #ifdef MP
|
||||
this.$emit('mescrollTop', this.commonTabs + 10)
|
||||
// #endif
|
||||
// #ifndef MP
|
||||
this.$emit('mescrollTop', this.noticeWarpH)
|
||||
// #endif
|
||||
},
|
||||
search() {
|
||||
this.searchTimer && clearTimeout(this.searchTimer);
|
||||
this.searchTimer = setTimeout(() => {
|
||||
this.$emit('search', this.keyword)
|
||||
}, 300);
|
||||
},
|
||||
change(e) {
|
||||
this.current = e;
|
||||
this.keyword = ''
|
||||
this.$emit('change', this.current)
|
||||
},
|
||||
iconClick(e) {
|
||||
this.$emit('iconClick')
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.notice-warp {
|
||||
z-index: 9;
|
||||
position: fixed;
|
||||
top: var(--window-top);
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
/*对应mescroll-body的top值*/
|
||||
font-size: 26rpx;
|
||||
text-align: center;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
183
pages/workFlow/document/components/DocList.vue
Normal file
@@ -0,0 +1,183 @@
|
||||
<template>
|
||||
<view class="" v-if="list.length">
|
||||
<view class="doc-list" v-if="modelValue">
|
||||
<checkbox-group @change="checkboxChange" @click.stop>
|
||||
<label class="item-label" v-for="(item,index) in list" :key="index">
|
||||
<view class="u-flex item-label-left u-line-1" @click.stop="goDetail(item)">
|
||||
<view class="doc-icon">
|
||||
<u-image :src="getRecordImg(item.fileExtension)" width="74" height="74" />
|
||||
</view>
|
||||
<view class="text">
|
||||
<p class="u-m-l-10 u-m-b-8 u-font-28 name u-line-1">{{item.fullName}}</p>
|
||||
<p class="u-m-l-10 u-m-t-8 u-font-24 time">
|
||||
{{item.time ? jnpf.toDate(item.time, 'yyyy-MM-dd HH:mm:ss') :''}}
|
||||
</p>
|
||||
</view>
|
||||
</view>
|
||||
<checkbox :value="item.id" :checked="item.checked" activeBackgroundColor="#0177FF" iconColor="#fff"
|
||||
style="transform:scale(0.7)" />
|
||||
</label>
|
||||
</checkbox-group>
|
||||
</view>
|
||||
<view class="u-flex u-p-l-20 u-p-r-20 doc-list2 u-p-t-20" v-else>
|
||||
<checkbox-group @change="checkboxChange" @click.stop class="checkbox-group">
|
||||
<label class="group-label" v-for="(item,index) in list" :key="index">
|
||||
<view class="u-flex-col doc-list-inner" @click.stop="goDetail(item)">
|
||||
<view class="doc-icon u-flex">
|
||||
<u-image :src="getRecordImg(item.fileExtension)" width="84" height="84" />
|
||||
</view>
|
||||
<view class="u-flex doc-name" @click.stop>
|
||||
<view class="u-line-1 name">{{item.fullName}}</view>
|
||||
<checkbox :value="item.id" :checked="item.checked" activeBackgroundColor="#0177FF"
|
||||
iconColor="#fff" style="transform:scale(0.7)" />
|
||||
</view>
|
||||
</view>
|
||||
</label>
|
||||
</checkbox-group>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import mixin from "../mixin.js"
|
||||
export default {
|
||||
name: 'DocList',
|
||||
mixins: [mixin],
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
documentList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
documentList: {
|
||||
handler(val) {
|
||||
this.list = val
|
||||
},
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goDetail(item) {
|
||||
this.$emit('goDetail', item)
|
||||
},
|
||||
checkboxChange(e) {
|
||||
this.$emit('checkboxChange', e.detail.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.doc-list {
|
||||
background-color: #FFFFFF;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.item-label {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
border-bottom: 1rpx solid #f0f2f6;
|
||||
height: 126rpx;
|
||||
|
||||
.item-label-left {
|
||||
flex: 1;
|
||||
|
||||
.doc-icon {
|
||||
width: 74rpx;
|
||||
height: 74rpx;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
width: 80%;
|
||||
|
||||
.name {
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.time {
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.uni-checkbox-wrapper {
|
||||
.uni-checkbox-input {
|
||||
margin: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.doc-list2 {
|
||||
background-color: #fff;
|
||||
|
||||
.doc-list-inner {
|
||||
width: 100%;
|
||||
background-color: #f2f3f7;
|
||||
padding: 12rpx 12rpx 0 12rpx;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 8rpx;
|
||||
|
||||
.doc-icon {
|
||||
width: 100%;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 8rpx;
|
||||
height: 160rpx;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.doc-name {
|
||||
width: 100%;
|
||||
height: 73rpx;
|
||||
|
||||
.name {
|
||||
text-align: left;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
::v-deep .uni-checkbox-wrapper {
|
||||
.uni-checkbox-input {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
|
||||
.group-label {
|
||||
width: 48%;
|
||||
}
|
||||
|
||||
::v-deep .uni-label-pointer {
|
||||
width: 48%;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,28 @@
|
||||
// 导航栏标题
|
||||
.title {
|
||||
height: 90rpx;
|
||||
padding: 0 32rpx;
|
||||
line-height: 90rpx;
|
||||
font-size: 30rpx;
|
||||
background-color: #f5f5f5;
|
||||
color: #606064;
|
||||
// 导航栏图标样式
|
||||
.iconclass {
|
||||
display: inline-block;
|
||||
margin: 0 12rpx;
|
||||
color: #D0D4DB;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
// 导航栏项样式
|
||||
.inline-item {
|
||||
display: inline-block
|
||||
}
|
||||
// 导航栏项-启用状态
|
||||
.active {
|
||||
color: #4297ED !important;
|
||||
}
|
||||
// 导航栏项-无状态
|
||||
.none {
|
||||
color: #666666;
|
||||
}
|
||||
168
pages/workFlow/document/components/navigation/NaviGation.vue
Normal file
@@ -0,0 +1,168 @@
|
||||
<template>
|
||||
<view class="title" style="background-color: #fff;margin-top: 20rpx;">
|
||||
<scroll-view ref="sea" scroll-x style="width: 100%;white-space: nowrap;">
|
||||
<!-- 全部 -->
|
||||
<view class="inline-item" @click="clickItem(null,-1)">
|
||||
<text v-if="!isre && treeStack.length == 0" class="none">全部</text>
|
||||
<text v-else class="active">全部</text>
|
||||
</view>
|
||||
<!-- 全部 -->
|
||||
<!-- 搜索结果 -->
|
||||
<view v-if="isre" @click="clickItem(null,-2)"
|
||||
:class="activeSearch?'active inline-item':' none inline-item'">
|
||||
<i class="iconfont icon-z043 iconclass" />
|
||||
搜索结果
|
||||
</view>
|
||||
<!-- 搜索结果 -->
|
||||
<!-- 当前树的层级值 -->
|
||||
<view v-for="(item,index) in treeStack" class="inline-item" :key="index">
|
||||
<view class="inline-item" @click="clickItem(item,index)">
|
||||
<i class="iconfont icon-z043 iconclass" />
|
||||
<text v-if="index== treeStack.length-1" class="none inline-item">
|
||||
{{item[slabel]}}
|
||||
</text>
|
||||
<text v-else class="active">
|
||||
{{item[slabel]}}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 当前树的层级值 -->
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 无限级树-面包屑导航
|
||||
* @description 无限级树的面包屑导航
|
||||
* @property {String} slabel 显示的label值
|
||||
* @return {Function} clickItem(item , index) 点击导航栏的索引
|
||||
* @item 表示导航项对应的值
|
||||
* @index 表示导航项的层级别索引
|
||||
* @value -1 全部
|
||||
* @value -2 表示层级
|
||||
* @value 其他 (从最外层开始,依次0,1,2,3……)
|
||||
* @return {Object} outF 导航条内部的方法
|
||||
* @param {Function} isIre 设置是否搜索状态
|
||||
* @param {Function} setTreeStack 设置导航树的值
|
||||
* @param {Function} pushTreeStack 为导航树添加项
|
||||
* @param {Function} clearTreeStack 清空导航树
|
||||
*/
|
||||
// scrollLeft : 暂时
|
||||
export default {
|
||||
name: "luyj-tree-navigation",
|
||||
props: {
|
||||
// 显示的label值
|
||||
slabel: {
|
||||
type: String,
|
||||
default: 'label'
|
||||
},
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isre: false, // 是否进行了搜索(返回是否进行了搜索)
|
||||
treeStack: [], // 当前搜索值
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 是否可点击搜索结果
|
||||
activeSearch() {
|
||||
return this.treeStack.length > 0;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 浅拷贝导航列表的每一个对象(为了不改变item值,也不复制过多的数据)
|
||||
this.treeStack.forEach(item => {
|
||||
let tempItem = Object.assign(item);
|
||||
this.treeStack.push(tempItem);
|
||||
});
|
||||
let obj = {
|
||||
setIsre: this.setIsre,
|
||||
getIsre: this.getIsre,
|
||||
setTreeStack: this.setTreeStack,
|
||||
concatTreeStack: this.concatTreeStack,
|
||||
pushTreeStack: this.pushTreeStack,
|
||||
clearTreeStack: this.clearTreeStack,
|
||||
getTreeStack: this.getTreeStack
|
||||
};
|
||||
this.$emit("inF", obj); // 导出的导航栏调用方法
|
||||
},
|
||||
methods: {
|
||||
// ================================== 初始化时导出方法(用于外部调用内部结果) =========================================================
|
||||
/** 设置isre值(是否搜索)
|
||||
* @param {Boolean} isre 设置是否搜索
|
||||
*/
|
||||
setIsre(isre) {
|
||||
this.isre = isre;
|
||||
},
|
||||
/**
|
||||
* 获取isr值(获取是否搜索中)
|
||||
*/
|
||||
getIsre() {
|
||||
return this.isre;
|
||||
},
|
||||
/** 设置导航树
|
||||
* @param {Array} treeStack 导航树
|
||||
*/
|
||||
setTreeStack(treeStack) {
|
||||
this.treeStack = treeStack;
|
||||
},
|
||||
/** 拼接导航树
|
||||
* @param {Object} treeStack 导航树
|
||||
*/
|
||||
concatTreeStack(treeStack) {
|
||||
this.treeStack = this.treeStack.concat(treeStack);
|
||||
},
|
||||
/** 为导航树添加项
|
||||
* @param {Object} item 待添加的对象
|
||||
*/
|
||||
pushTreeStack(item) {
|
||||
this.treeStack.push(item);
|
||||
},
|
||||
/**
|
||||
* 获取当前导航条
|
||||
*/
|
||||
getTreeStack() {
|
||||
return this.treeStack;
|
||||
},
|
||||
/**
|
||||
* 清空导航树
|
||||
*/
|
||||
clearTreeStack() {
|
||||
this.treeStack.splice(0);
|
||||
},
|
||||
// ================================== 监听事件 ===========================================================
|
||||
/** 点击导航栏索引
|
||||
* @param {Object} item 当前层的值
|
||||
* @param {Number} index 索引值
|
||||
*/
|
||||
clickItem(item, index) {
|
||||
if (index == -1) {
|
||||
// 点击全部
|
||||
this.isre = false;
|
||||
this.treeStack.splice(0);
|
||||
} else if (index == -2) {
|
||||
// 搜索结果
|
||||
if (this.activeSearch) {
|
||||
this.isre = true;
|
||||
this.treeStack.splice(0);
|
||||
}
|
||||
} else {
|
||||
// 点击某一层级树
|
||||
this.isre = false;
|
||||
if (this.treeStack.length - 1 > index) {
|
||||
this.treeStack.splice(index + 1);
|
||||
}
|
||||
}
|
||||
this.$emit("clickItem", item, index);
|
||||
},
|
||||
},
|
||||
// ============================================================================================================
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "navigation.scss";
|
||||
@import "icon.css";
|
||||
</style>
|
||||
342
pages/workFlow/document/components/navigation/icon.css
Normal file
@@ -0,0 +1,342 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 2009600 */
|
||||
src: url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff2?t=1620633089023') format('woff2'),
|
||||
url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff?t=1620633089023') format('woff'),
|
||||
url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.ttf?t=1620633089023') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-banxuanzhongshousuo1-shi:before {
|
||||
content: "\e682";
|
||||
}
|
||||
|
||||
.icon-xuanzhong3:before {
|
||||
content: "\e6bb";
|
||||
}
|
||||
|
||||
.icon-weixuanzhong2:before {
|
||||
content: "\e62e";
|
||||
}
|
||||
|
||||
.icon-danxuanxuanzhong:before {
|
||||
content: "\e631";
|
||||
}
|
||||
|
||||
.icon-xuanzhong4:before {
|
||||
content: "\e63e";
|
||||
}
|
||||
|
||||
.icon-xuanzhong1:before {
|
||||
content: "\e62d";
|
||||
}
|
||||
|
||||
.icon-xuanzhong2:before {
|
||||
content: "\e656";
|
||||
}
|
||||
|
||||
.icon-selected:before {
|
||||
content: "\e615";
|
||||
}
|
||||
|
||||
.icon-weixuanzhong1:before {
|
||||
content: "\e614";
|
||||
}
|
||||
|
||||
.icon-xingzhuang6kaobei3-copy-copy:before {
|
||||
content: "\e613";
|
||||
}
|
||||
|
||||
.icon-radio-checked:before {
|
||||
content: "\e63f";
|
||||
}
|
||||
|
||||
.icon-huifu:before {
|
||||
content: "\e619";
|
||||
}
|
||||
|
||||
.icon-dizhi:before {
|
||||
content: "\e64a";
|
||||
}
|
||||
|
||||
.icon-kuaijiecaidan:before {
|
||||
content: "\e60a";
|
||||
}
|
||||
|
||||
.icon-z043:before {
|
||||
content: "\e62f";
|
||||
}
|
||||
|
||||
.icon-guanbi:before {
|
||||
content: "\e607";
|
||||
}
|
||||
|
||||
.icon-xuanze:before {
|
||||
content: "\e623";
|
||||
}
|
||||
|
||||
.icon-caidanzhaolinggan:before {
|
||||
content: "\e616";
|
||||
}
|
||||
|
||||
.icon-xitongshezhi:before {
|
||||
content: "\e60c";
|
||||
}
|
||||
|
||||
.icon-xitongshezhi1:before {
|
||||
content: "\e633";
|
||||
}
|
||||
|
||||
.icon-lunbo:before {
|
||||
content: "\e692";
|
||||
}
|
||||
|
||||
.icon-shuping:before {
|
||||
content: "\e659";
|
||||
}
|
||||
|
||||
.icon-tongzhi:before {
|
||||
content: "\e641";
|
||||
}
|
||||
|
||||
.icon-pinglunguanlishezhi:before {
|
||||
content: "\e6ac";
|
||||
}
|
||||
|
||||
.icon-icon:before {
|
||||
content: "\e600";
|
||||
}
|
||||
|
||||
.icon-liuyanguanli:before {
|
||||
content: "\e61d";
|
||||
}
|
||||
|
||||
.icon-xuanzhong:before {
|
||||
content: "\e669";
|
||||
}
|
||||
|
||||
.icon--:before {
|
||||
content: "\e622";
|
||||
}
|
||||
|
||||
.icon-tushu:before {
|
||||
content: "\e604";
|
||||
}
|
||||
|
||||
.icon-huishouzhan:before {
|
||||
content: "\e61c";
|
||||
}
|
||||
|
||||
.icon-yonghutouxiang:before {
|
||||
content: "\e617";
|
||||
}
|
||||
|
||||
.icon-liebiao:before {
|
||||
content: "\e630";
|
||||
}
|
||||
|
||||
.icon-fenlei:before {
|
||||
content: "\e621";
|
||||
}
|
||||
|
||||
.icon-tushu1:before {
|
||||
content: "\e605";
|
||||
}
|
||||
|
||||
.icon-tubiao-:before {
|
||||
content: "\e620";
|
||||
}
|
||||
|
||||
.icon-weixuanze:before {
|
||||
content: "\e624";
|
||||
}
|
||||
|
||||
.icon-tushujieyue:before {
|
||||
content: "\e690";
|
||||
}
|
||||
|
||||
.icon-lunbo1:before {
|
||||
content: "\e6c5";
|
||||
}
|
||||
|
||||
.icon-shanchu:before {
|
||||
content: "\e67b";
|
||||
}
|
||||
|
||||
.icon-lunbo2:before {
|
||||
content: "\e61e";
|
||||
}
|
||||
|
||||
.icon-huaban:before {
|
||||
content: "\e663";
|
||||
}
|
||||
|
||||
.icon-kehuan:before {
|
||||
content: "\e608";
|
||||
}
|
||||
|
||||
.icon-icon02:before {
|
||||
content: "\e601";
|
||||
}
|
||||
|
||||
.icon-huishouzhan1:before {
|
||||
content: "\e612";
|
||||
}
|
||||
|
||||
.icon-huishouzhan2:before {
|
||||
content: "\e63d";
|
||||
}
|
||||
|
||||
.icon-sousuo:before {
|
||||
content: "\e62c";
|
||||
}
|
||||
|
||||
.icon-xingzhuang:before {
|
||||
content: "\e625";
|
||||
}
|
||||
|
||||
.icon-lunbobankuai:before {
|
||||
content: "\e61f";
|
||||
}
|
||||
|
||||
.icon-shangchuan:before {
|
||||
content: "\e602";
|
||||
}
|
||||
|
||||
.icon-yonghu:before {
|
||||
content: "\e761";
|
||||
}
|
||||
|
||||
.icon-tongzhi1:before {
|
||||
content: "\e603";
|
||||
}
|
||||
|
||||
.icon-jingsong:before {
|
||||
content: "\e65c";
|
||||
}
|
||||
|
||||
.icon-fenlei1:before {
|
||||
content: "\e6c6";
|
||||
}
|
||||
|
||||
.icon-xieshupingicon:before {
|
||||
content: "\e72d";
|
||||
}
|
||||
|
||||
.icon-liuyan:before {
|
||||
content: "\e626";
|
||||
}
|
||||
|
||||
.icon-weixuanzhong:before {
|
||||
content: "\e627";
|
||||
}
|
||||
|
||||
.icon-youxiang:before {
|
||||
content: "\e646";
|
||||
}
|
||||
|
||||
.icon-lunboguanggao:before {
|
||||
content: "\e6b3";
|
||||
}
|
||||
|
||||
.icon-xuanze1:before {
|
||||
content: "\e60d";
|
||||
}
|
||||
|
||||
.icon-chushaixuanxiang:before {
|
||||
content: "\e606";
|
||||
}
|
||||
|
||||
.icon-liuyanguanli1:before {
|
||||
content: "\e61a";
|
||||
}
|
||||
|
||||
.icon-shanchu1:before {
|
||||
content: "\e609";
|
||||
}
|
||||
|
||||
.icon-huishouzhan3:before {
|
||||
content: "\e642";
|
||||
}
|
||||
|
||||
.icon-shangchuan1:before {
|
||||
content: "\e823";
|
||||
}
|
||||
|
||||
.icon-huishouzhan4:before {
|
||||
content: "\e61b";
|
||||
}
|
||||
|
||||
.icon-chuangzuo:before {
|
||||
content: "\e8ad";
|
||||
}
|
||||
|
||||
.icon-dianzan:before {
|
||||
content: "\e8ae";
|
||||
}
|
||||
|
||||
.icon-paihangbang:before {
|
||||
content: "\e8b3";
|
||||
}
|
||||
|
||||
.icon-shouye:before {
|
||||
content: "\e8b9";
|
||||
}
|
||||
|
||||
.icon-shoucang:before {
|
||||
content: "\e8c6";
|
||||
}
|
||||
|
||||
.icon-addApp:before {
|
||||
content: "\e60b";
|
||||
}
|
||||
|
||||
.icon-huishouzhan5:before {
|
||||
content: "\e63a";
|
||||
}
|
||||
|
||||
.icon-add1:before {
|
||||
content: "\e60e";
|
||||
}
|
||||
|
||||
.icon-shoucang1:before {
|
||||
content: "\e60f";
|
||||
}
|
||||
|
||||
.icon-canshutongji:before {
|
||||
content: "\e618";
|
||||
}
|
||||
|
||||
.icon-rizhiguanli:before {
|
||||
content: "\e628";
|
||||
}
|
||||
|
||||
.icon-shanchu2:before {
|
||||
content: "\e629";
|
||||
}
|
||||
|
||||
.icon-xinzeng:before {
|
||||
content: "\e62a";
|
||||
}
|
||||
|
||||
.icon-zhankailiebiao:before {
|
||||
content: "\e62b";
|
||||
}
|
||||
|
||||
.icon-xiala-copy:before {
|
||||
content: "\e610";
|
||||
}
|
||||
|
||||
.icon-shangla:before {
|
||||
content: "\e64e";
|
||||
}
|
||||
|
||||
.icon-xianxingshezhi:before {
|
||||
content: "\e611";
|
||||
}
|
||||
309
pages/workFlow/document/detail.vue
Normal file
@@ -0,0 +1,309 @@
|
||||
<template>
|
||||
<view class="document-v" :style="{'padding-bottom': show ? '88rpx' : '0','overflow':showAddSelect?'hidden':''}">
|
||||
<view class="u-flex top-btn" :class="slide2" v-show="show && current !== 1">
|
||||
<view class="button-left" @click.stop="bottomfun('cancel')">
|
||||
<p class="u-m-t-10 u-font-28">取消</p>
|
||||
</view>
|
||||
<view class="button-center" @click.stop="bottomfun('select')">
|
||||
<p class="u-m-t-10 u-font-28">已选中{{this.selectFiles.length}}文件</p>
|
||||
</view>
|
||||
<view class="button-right u-m-t-12" @click.stop="bottomfun('checkAll')">
|
||||
<p class="icon-ym icon-ym-app-checkAll " :style="{'color':this.checkedAll ? '#0293fc' : '#303133'}">
|
||||
</p>
|
||||
</view>
|
||||
</view>
|
||||
<NaviGation @inF="navigationInt" @clickItem="backTree" :slabel="props.label" ref="NaviGation"></NaviGation>
|
||||
<mescroll-body ref="mescrollRef" @down="downCallback" :down="downOption" :sticky="false" @up="upCallback"
|
||||
:up="upOption" :bottombar="false" @init="mescrollInit" top="20">
|
||||
<DocList v-model="changeStyle" :documentList="documentList" @goDetail="goDetail"
|
||||
@checkboxChange="checkboxChange"></DocList>
|
||||
</mescroll-body>
|
||||
<view class="com-addBtn" @click="addFolder()" v-if="!selectFiles.length && current == 0">
|
||||
<u-icon name="plus" size="48" color="#fff" />
|
||||
</view>
|
||||
<view class="u-flex bottom-btn" :class="slide" v-show="show && current !== 1">
|
||||
<template v-if="current == 0">
|
||||
<view class="button-preIcon" @click.stop="bottomfun('down')">
|
||||
<p class="icon-ym icon-ym-app-download u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">下载</p>
|
||||
</view>
|
||||
<view class="button-preIcon" @click.stop="bottomfun('share')">
|
||||
<p class="icon-ym icon-ym-app-share u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">共享</p>
|
||||
</view>
|
||||
<view class="button-preIcon" @click.stop="bottomfun('delete')">
|
||||
<p class="icon-ym icon-ym-app-delete u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">删除</p>
|
||||
</view>
|
||||
<view class="button-preIcon" @click.stop="bottomfun('move')">
|
||||
<p class="icon-ym icon-ym-app-move u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">移动到</p>
|
||||
</view>
|
||||
<view class="button-preIcon" @click.stop="bottomfun('restName')" v-if="this.selectFiles.length === 1">
|
||||
<p class="icon-ym icon-ym-app-rename u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">重命名</p>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="current == 2">
|
||||
<view class="button-preIcon" @click.stop="bottomfun('down')">
|
||||
<p class="icon-ym icon-ym-app-download u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">下载</p>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="current == 1">
|
||||
<view class="button-preIcon" @click.stop="bottomfun('shareCancel')">
|
||||
<p class="icon-ym icon-ym-app-share u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">取消共享</p>
|
||||
</view>
|
||||
<view class="button-preIcon" @click.stop="bottomfun('share')">
|
||||
<p class="icon-ym icon-ym-app-share u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">共享</p>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="current == 3">
|
||||
<view class="button-preIcon" @click.stop="bottomfun('revert')">
|
||||
<p class="icon-ym icon-ym-recovery u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">还原</p>
|
||||
</view>
|
||||
<view class="button-preIcon" @click.stop="bottomfun('delete')">
|
||||
<p class="icon-ym icon-ym-app-delete u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">删除</p>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
<!-- 重命名弹窗 -->
|
||||
<uni-popup ref="inputDialog" type="dialog">
|
||||
<uni-popup-dialog ref="inputClose" mode="input" :title="modalTitle" v-model="modalValue" placeholder="请输入内容"
|
||||
before-close @confirm="restName" @close="closeDialog"></uni-popup-dialog>
|
||||
</uni-popup>
|
||||
<treeCollapse :show="showApply" v-if="showApply" :treeData="folderTreeList" @change="handelClick" mode="right"
|
||||
@close="close" width="100%" type="doc">
|
||||
<view class="u-flex u-p-l-32 u-p-r-32" style="justify-content: space-between;height: 88rpx;">
|
||||
<text style="color: #2979ff;" @click="close()">取消</text>
|
||||
<text>移动到</text>
|
||||
<text style="color: #2979ff;" v-if="selectFiles.length" @click="folderMove">移动到此</text>
|
||||
</view>
|
||||
</treeCollapse>
|
||||
<JnpfUsersSelect ref="JnpfUsersSelect" @change="shareSubmit" v-model="usersSelectValue" :isInput="false" />
|
||||
<AddFilePopup v-if="showAddFilePopup" :show="showAddSelect" @confirm="addSelect" @close="showAddSelect = false"
|
||||
title="新建" :confirmBtn="false" @onCallback="onCallback" :parentId="parentId"></AddFilePopup>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
getDocumentList,
|
||||
trash,
|
||||
shareFolder,
|
||||
shareTome
|
||||
} from "@/api/workFlow/document";
|
||||
import treeCollapse from '@/components/treeCollapse'
|
||||
import AddFilePopup from './components/AddFilePopup.vue'
|
||||
import NaviGation from './components/navigation/NaviGation.vue'
|
||||
import DocList from './components/DocList.vue'
|
||||
import mixin from "./mixin.js"
|
||||
export default {
|
||||
mixins: [mixin],
|
||||
components: {
|
||||
NaviGation,
|
||||
DocList,
|
||||
treeCollapse,
|
||||
AddFilePopup,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showAddFilePopup: false,
|
||||
showModal: false,
|
||||
show: false,
|
||||
detailList: [],
|
||||
keyword: '',
|
||||
documentList: [],
|
||||
changeStyle: true,
|
||||
parentId: 0,
|
||||
props: {
|
||||
id: 'id',
|
||||
label: 'fullName',
|
||||
children: 'children',
|
||||
multiple: false,
|
||||
checkStrictly: false, //不关联
|
||||
nodes: false, // nodes为false时,可以选择任意一级选项;nodes为true时只能选择叶子节点
|
||||
}
|
||||
}
|
||||
},
|
||||
onLoad(e) {
|
||||
let config = JSON.parse(e.config)
|
||||
this.config = JSON.parse(JSON.stringify(config))
|
||||
this.parentId = this.config.id
|
||||
this.$nextTick(() => {
|
||||
this.$refs.NaviGation.pushTreeStack(this.config);
|
||||
})
|
||||
this.init()
|
||||
},
|
||||
watch: {
|
||||
// 在select弹起的时候,重新初始化所有数据
|
||||
selectFiles: {
|
||||
handler(val) {
|
||||
if (!val.length) {
|
||||
setTimeout(() => {
|
||||
this.show = false
|
||||
}, 500)
|
||||
}
|
||||
if (val.length === this.documentList.length) {
|
||||
this.checkedAll = true
|
||||
} else {
|
||||
this.checkedAll = false
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.isDetail = true
|
||||
this.current = this.config.current
|
||||
this.changeStyle = this.config.changeStyle
|
||||
this.setTitle(this.config.fullName)
|
||||
this.showAddFilePopup = true
|
||||
},
|
||||
navigationInt(e) {
|
||||
this.pushTreeStack = e.pushTreeStack;
|
||||
},
|
||||
backTree(item, index) {
|
||||
if (index === -1) {
|
||||
this.isDetail = false
|
||||
uni.navigateBack()
|
||||
return
|
||||
}
|
||||
if (item.id === this.parentId) return
|
||||
this.parentId = item.id
|
||||
this.setTitle(item.fullName)
|
||||
this.resetList()
|
||||
},
|
||||
setTitle(fullName) {
|
||||
uni.setNavigationBarTitle({
|
||||
title: fullName
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f0f2f6;
|
||||
}
|
||||
|
||||
.document-v {
|
||||
padding-bottom: 88rpx;
|
||||
height: calc(100vh - 288rpx);
|
||||
|
||||
::v-deep .mescroll-empty {
|
||||
padding-top: 400rpx;
|
||||
}
|
||||
|
||||
::v-deep .u-model__title {
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
::v-deep .u-model__footer__button {
|
||||
border-right: 1rpx solid #e4e7ed;
|
||||
height: 76rpx;
|
||||
line-height: 76rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.top-btn {
|
||||
height: 80rpx;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: #fff;
|
||||
z-index: 9999;
|
||||
justify-content: space-between;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.button-left {
|
||||
color: #0293fc;
|
||||
}
|
||||
|
||||
.button-right {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.slide-down2 {
|
||||
animation: slide-down2 0.5s forwards;
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.slide-up2 {
|
||||
animation: slide-up2 0.5s forwards;
|
||||
opacity: 0;
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
.slide-down {
|
||||
animation: slide-down 0.5s forwards;
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.slide-up {
|
||||
animation: slide-up 0.5s forwards;
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.bottom-btn {
|
||||
height: 100rpx;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: #0293fc;
|
||||
z-index: 9;
|
||||
justify-content: space-around;
|
||||
|
||||
.button-preIcon {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-up {
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-down {
|
||||
to {
|
||||
transform: translateY(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-up2 {
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-down2 {
|
||||
to {
|
||||
transform: translateY(-100%);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.com-addBtn {
|
||||
bottom: 320rpx;
|
||||
right: 66rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
298
pages/workFlow/document/index.vue
Normal file
@@ -0,0 +1,298 @@
|
||||
<template>
|
||||
<view class="document-v" :style="{'padding-bottom': show ? '88rpx' : '0','overflow':showAddSelect?'hidden':''}">
|
||||
<view class="u-flex top-btn" :class="slide2" v-show="show">
|
||||
<view class="button-left" @click.stop="bottomfun('cancel')">
|
||||
<p class="u-m-t-10 u-font-28">取消</p>
|
||||
</view>
|
||||
<view class="button-center" @click.stop="bottomfun('select')">
|
||||
<p class="u-m-t-10 u-font-28">已选中{{this.selectFiles.length}}文件</p>
|
||||
</view>
|
||||
<view class="button-right u-m-t-12" @click.stop="bottomfun('checkAll')">
|
||||
<p class="icon-ym icon-ym-app-checkAll " :style="{'color':this.checkedAll ? '#0293fc' : '#303133'}">
|
||||
</p>
|
||||
</view>
|
||||
</view>
|
||||
<DocHead @search="search" @change="change" @iconClick="iconClick" @mescrollTop="mescrollTop">
|
||||
</DocHead>
|
||||
<mescroll-body ref="mescrollRef" @down="downCallback" :down="downOption" :sticky="false" @up="upCallback"
|
||||
:up="upOption" :bottombar="false" @init="mescrollInit" :top="top">
|
||||
<DocList :modelValue="changeStyle" :documentList="documentList" @goDetail="goDetail"
|
||||
@checkboxChange="checkboxChange"></DocList>
|
||||
</mescroll-body>
|
||||
<view class="com-addBtn" @click="addFolder()" v-if="!selectFiles.length && current == 0">
|
||||
<u-icon name="plus" size="48" color="#fff" />
|
||||
</view>
|
||||
<view class="u-flex bottom-btn" :class="slide" v-show="show">
|
||||
<template v-if="current == 0">
|
||||
<!-- #ifdef H5 -->
|
||||
<view class="button-preIcon" @click.stop="bottomfun('down')">
|
||||
<p class="icon-ym icon-ym-app-download u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">下载</p>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<view class="button-preIcon" @click.stop="bottomfun('share')">
|
||||
<p class="icon-ym icon-ym-app-share u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">共享</p>
|
||||
</view>
|
||||
<view class="button-preIcon" @click.stop="bottomfun('delete')">
|
||||
<p class="icon-ym icon-ym-app-delete u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">删除</p>
|
||||
</view>
|
||||
<view class="button-preIcon" @click.stop="bottomfun('move')">
|
||||
<p class="icon-ym icon-ym-app-move u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">移动到</p>
|
||||
</view>
|
||||
<view class="button-preIcon" @click.stop="bottomfun('restName')" v-if="this.selectFiles.length === 1">
|
||||
<p class="icon-ym icon-ym-app-rename u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">重命名</p>
|
||||
</view>
|
||||
</template>
|
||||
<!-- #ifdef H5 -->
|
||||
<template v-if="current == 2">
|
||||
<view class="button-preIcon" @click.stop="bottomfun('down')">
|
||||
<p class="icon-ym icon-ym-app-download u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">下载</p>
|
||||
</view>
|
||||
</template>
|
||||
<!-- #endif -->
|
||||
<template v-if="current == 1">
|
||||
<view class="button-preIcon" @click.stop="bottomfun('shareCancel')">
|
||||
<p class="icon-ym icon-ym-app-share u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">取消共享</p>
|
||||
</view>
|
||||
<view class="button-preIcon" @click.stop="bottomfun('share')" v-if="this.selectFiles.length === 1">
|
||||
<p class="icon-ym icon-ym-app-share u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">共享</p>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="current == 3">
|
||||
<view class="button-preIcon" @click.stop="bottomfun('revert')">
|
||||
<p class="icon-ym icon-ym-recovery u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">还原</p>
|
||||
</view>
|
||||
<view class="button-preIcon" @click.stop="bottomfun('delete')">
|
||||
<p class="icon-ym icon-ym-app-delete u-m-b-8"></p>
|
||||
<p class="u-m-t-10 u-font-24">删除</p>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
<!-- 重命名弹窗 -->
|
||||
<uni-popup ref="inputDialog" type="dialog" class="diyPopup">
|
||||
<uni-popup-dialog ref="inputClose" mode="input" :title="modalTitle" placeholder="请输入内容" before-close
|
||||
@confirm="restName" @close="closeDialog" class="popup-dialog">
|
||||
<u-input v-model="modalValue" placeholder="请输入" :auto-height="false" maxlength="99999" height="150"
|
||||
:clearable="true" :border="true" />
|
||||
</uni-popup-dialog>
|
||||
</uni-popup>
|
||||
<treeCollapse :show="showApply" v-if="showApply" :treeData="folderTreeList" @change="handelClick" mode="right"
|
||||
@close="close" width="100%" type="doc">
|
||||
<view class="u-flex u-p-l-32 u-p-r-32" style="justify-content: space-between;height: 88rpx;">
|
||||
<text style="color: #2979ff;" @click="close()">取消</text>
|
||||
<text>移动到</text>
|
||||
<text style="color: #2979ff;" v-if="selectFiles.length" @click="folderMove">移动到此</text>
|
||||
</view>
|
||||
</treeCollapse>
|
||||
<JnpfUsersSelect ref="JnpfUsersSelect" @change="shareSubmit" :isInput="false" v-model="usersSelectValue" />
|
||||
<AddFilePopup :show="showAddSelect" @confirm="addSelect" @close="showAddSelect = false" title="新建"
|
||||
:confirmBtn="false" @onCallback="onCallback" :parentId="parentId"></AddFilePopup>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import treeCollapse from '@/components/treeCollapse'
|
||||
import DocHead from './components/DocHead.vue'
|
||||
import DocList from './components/DocList.vue'
|
||||
import AddFilePopup from './components/AddFilePopup.vue'
|
||||
import mixin from "./mixin.js"
|
||||
export default {
|
||||
mixins: [mixin],
|
||||
components: {
|
||||
DocHead,
|
||||
DocList,
|
||||
AddFilePopup,
|
||||
treeCollapse
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
documentList: [],
|
||||
top: 0
|
||||
}
|
||||
},
|
||||
onLoad(e) {
|
||||
this.selectFiles = []
|
||||
this.parentId = e.parentId ? e.parentId : 0
|
||||
this.current = e.current ? Number(e.current) : 0
|
||||
},
|
||||
|
||||
watch: {
|
||||
// 在select弹起的时候,重新初始化所有数据
|
||||
selectFiles: {
|
||||
handler(val) {
|
||||
if (!val.length) {
|
||||
setTimeout(() => {
|
||||
this.show = false
|
||||
}, 500)
|
||||
|
||||
}
|
||||
if (val.length === this.documentList.length) {
|
||||
this.checkedAll = true
|
||||
} else {
|
||||
this.checkedAll = false
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
search(e) {
|
||||
this.keyword = e
|
||||
this.documentList = [];
|
||||
this.mescroll.resetUpScroll();
|
||||
},
|
||||
mescrollTop(e) {
|
||||
this.top = e + 10
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f0f2f6;
|
||||
}
|
||||
|
||||
.document-v {
|
||||
padding-bottom: 88rpx;
|
||||
height: calc(100vh - 288rpx);
|
||||
|
||||
::v-deep .mescroll-empty {
|
||||
padding-top: 400rpx;
|
||||
}
|
||||
|
||||
::v-deep .u-model__title {
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
::v-deep .u-model__footer__button {
|
||||
border-right: 1rpx solid #e4e7ed;
|
||||
height: 76rpx;
|
||||
line-height: 76rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.top-btn {
|
||||
height: 80rpx;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: #fff;
|
||||
/* #ifdef MP-WEIXIN */
|
||||
z-index: 99;
|
||||
/* #endif */
|
||||
/* #ifndef MP-WEIXIN */
|
||||
z-index: 999;
|
||||
/* #endif */
|
||||
justify-content: space-between;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.button-left {
|
||||
color: #0293fc;
|
||||
}
|
||||
|
||||
.button-right {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.slide-down2 {
|
||||
animation: slide-down2 0.5s forwards;
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.slide-up2 {
|
||||
animation: slide-up2 0.5s forwards;
|
||||
opacity: 0;
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
.slide-down {
|
||||
animation: slide-down 0.5s forwards;
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.slide-up {
|
||||
animation: slide-up 0.5s forwards;
|
||||
opacity: 0;
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.bottom-btn {
|
||||
height: 100rpx;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: #0293fc;
|
||||
z-index: 9;
|
||||
justify-content: space-around;
|
||||
|
||||
.button-preIcon {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
.diyPopup {
|
||||
.popup-dialog {
|
||||
.uni-dialog-title {
|
||||
justify-content: center
|
||||
}
|
||||
|
||||
.uni-dialog-content {
|
||||
height: 160rpx;
|
||||
|
||||
.u-input {
|
||||
height: 80rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-up {
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-down {
|
||||
to {
|
||||
transform: translateY(100%);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-up2 {
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide-down2 {
|
||||
to {
|
||||
transform: translateY(-100%);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.com-addBtn {
|
||||
bottom: 320rpx;
|
||||
right: 66rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
541
pages/workFlow/document/mixin.js
Normal file
@@ -0,0 +1,541 @@
|
||||
import {
|
||||
getDocumentList,
|
||||
packDownload,
|
||||
resetFileName,
|
||||
batchDelete,
|
||||
trash,
|
||||
recovery,
|
||||
trashDelete,
|
||||
folderTree,
|
||||
folderMove,
|
||||
addFolder,
|
||||
shareFolder,
|
||||
shareFolderList,
|
||||
shareTome,
|
||||
shareUser,
|
||||
shareAdjustment,
|
||||
cancelShare,
|
||||
fileDetail
|
||||
} from "@/api/workFlow/document";
|
||||
import resources from "@/libs/resources.js";
|
||||
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
|
||||
import jnpf from '@/utils/jnpf'
|
||||
const wordTypeList = ['doc', 'docx'];
|
||||
const excelTypeList = ['xls', 'xlsx'];
|
||||
const pptTypeList = ['ppt', 'pptx'];
|
||||
const pdfTypeList = ['pdf'];
|
||||
const zipTypeList = ['rar', 'zip', 'arj', 'z', '7z'];
|
||||
const txtTypeList = ['txt', 'log'];
|
||||
const codeTypeList = ['html', 'cs', 'xml'];
|
||||
const imgTypeList = ['png', 'jpg', 'jpeg', 'bmp', 'gif'];
|
||||
const videoTypeList = ['avi', 'wmv', 'mpg', 'mpeg', 'mov', 'rm', 'ram', 'swf', 'flv', 'mp4', 'mp3', 'wma', 'avi', 'rm',
|
||||
'rmvb', 'flv', 'mpg', 'mkv'
|
||||
];
|
||||
const previewTypeList = [...wordTypeList, ...excelTypeList, ...pptTypeList, ...pdfTypeList];
|
||||
export default {
|
||||
mixins: [MescrollMixin],
|
||||
data() {
|
||||
return {
|
||||
usersSelectValue: '',
|
||||
isDetail: true,
|
||||
showApply: false,
|
||||
folderTreeList: [],
|
||||
modalValue: '',
|
||||
keyword: '',
|
||||
current: 0,
|
||||
show: false,
|
||||
slide: '',
|
||||
slide2: '',
|
||||
changeStyle: true,
|
||||
checkedAll: false,
|
||||
parentId: 0,
|
||||
wordImg: resources.document.wordImg,
|
||||
excelImg: resources.document.excelImg,
|
||||
pptImg: resources.document.pptImg,
|
||||
pdfImg: resources.document.pdfImg,
|
||||
rarImg: resources.document.rarImg,
|
||||
txtImg: resources.document.txtImg,
|
||||
codeImg: resources.document.codeImg,
|
||||
imageImg: resources.document.imageImg,
|
||||
audioImg: resources.document.audioImg,
|
||||
blankImg: resources.document.blankImg,
|
||||
folderImg: resources.document.folderImg,
|
||||
downOption: {
|
||||
use: true,
|
||||
auto: true,
|
||||
},
|
||||
upOption: {
|
||||
page: {
|
||||
num: 0,
|
||||
size: 50,
|
||||
time: null,
|
||||
},
|
||||
empty: {
|
||||
use: true,
|
||||
icon: resources.message.nodata,
|
||||
tip: this.$t('common.noData'),
|
||||
fixed: false,
|
||||
top: "560rpx",
|
||||
},
|
||||
textNoMore: this.$t('app.apply.noMoreData'),
|
||||
toTop: {
|
||||
bottom: 200,
|
||||
right: 80
|
||||
}
|
||||
},
|
||||
selectFolder: {},
|
||||
moveId: '',
|
||||
selectFiles: [],
|
||||
modalType: 'restName',
|
||||
showAddSelect: false,
|
||||
selector: [{
|
||||
fullName: '新建文件夹',
|
||||
id: 1,
|
||||
icon: 'icon-ym icon-ym-add-folder'
|
||||
},
|
||||
{
|
||||
fullName: '上传文件',
|
||||
id: 2,
|
||||
icon: 'icon-ym icon-ym-generator-menu'
|
||||
}
|
||||
],
|
||||
isDetail: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
},
|
||||
modalTitle() {
|
||||
return this.modalType === 'restName' ? '重命名文件' : '新建文件夹'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onCallback(e) {
|
||||
this.$u.toast(e.msg)
|
||||
setTimeout(() => {
|
||||
this.showAddSelect = false
|
||||
this.resetList()
|
||||
}, 1000)
|
||||
},
|
||||
addSelect(item) {
|
||||
if (item == 'add') {
|
||||
this.showAddSelect = false
|
||||
this.$refs.inputDialog.open('center')
|
||||
this.modalType = 'addFolder'
|
||||
}
|
||||
},
|
||||
addFolder() {
|
||||
this.modalValue = ''
|
||||
this.showAddSelect = true
|
||||
},
|
||||
shareSubmit(e) {
|
||||
let method = this.current === 1 ? shareAdjustment : shareFolder;
|
||||
let data = {
|
||||
ids: this.selectFiles,
|
||||
userIds: e
|
||||
}
|
||||
method(data).then(res => {
|
||||
this.resetList()
|
||||
})
|
||||
},
|
||||
upCallback(page) {
|
||||
let method;
|
||||
switch (this.current) {
|
||||
case 1:
|
||||
method = shareFolderList
|
||||
break;
|
||||
case 3:
|
||||
method = trash
|
||||
break;
|
||||
case 2:
|
||||
method = shareTome
|
||||
break;
|
||||
default:
|
||||
method = getDocumentList
|
||||
break;
|
||||
}
|
||||
let query = {
|
||||
keyword: this.keyword,
|
||||
parentId: this.parentId
|
||||
};
|
||||
method(query).then(res => {
|
||||
this.documentList = [];
|
||||
this.selectFiles = []
|
||||
const timeMap = ['creatorTime', 'shareTime', 'shareTime', 'deleteTime'];
|
||||
const useTime = timeMap[this.current] ?? 'creatorTime'; // 添加默认值
|
||||
const list = res.data.list.map(o => ({
|
||||
...o,
|
||||
time: o[useTime]
|
||||
}));
|
||||
this.documentList = this.documentList.concat(list);
|
||||
this.mescroll.endSuccess(list.length);
|
||||
})
|
||||
},
|
||||
downLoad(id) {
|
||||
let data = {
|
||||
ids: id ? id : this.selectFiles
|
||||
}
|
||||
packDownload(JSON.stringify(data)).then(res => {
|
||||
// #ifdef H5
|
||||
const fileUrl = this.baseURL + res.data.url + '&name=' + encodeURI(res.data.name);
|
||||
window.location.href = fileUrl;
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
this.previewFile(res.data)
|
||||
// #endif
|
||||
|
||||
// #ifndef H5 || MP
|
||||
this.downloadFile(res.data);
|
||||
// #endif
|
||||
})
|
||||
},
|
||||
handelClick(item) {
|
||||
this.moveId = item.id == '-1' ? 0 : item.id
|
||||
},
|
||||
downloadFile(data) {
|
||||
const {
|
||||
url,
|
||||
name
|
||||
} = data;
|
||||
const fileExt = name.split('.').pop().toLowerCase();
|
||||
const handleDownload = () => {
|
||||
uni.downloadFile({
|
||||
url: `${this.baseURL}${url}&name=${name}`,
|
||||
success: (res) => {
|
||||
if (res.statusCode !== 200) return this.$u.toast('文件下载失败');
|
||||
|
||||
// #ifdef APP-HARMONY
|
||||
openDocument(res.tempFilePath)
|
||||
// #endif
|
||||
|
||||
// #ifndef APP-HARMONY
|
||||
if (plus.os.name == 'iOS') {
|
||||
openDocument(res.tempFilePath)
|
||||
return
|
||||
}
|
||||
|
||||
/* 安卓 */
|
||||
uni.saveFile({
|
||||
tempFilePath: res.tempFilePath,
|
||||
success: red => {
|
||||
uni.showToast({
|
||||
icon: 'none',
|
||||
mask: true,
|
||||
title: '文件已保存:' + red.savedFilePath, //保存路径
|
||||
duration: 3000,
|
||||
});
|
||||
},
|
||||
fail(err) {
|
||||
console.log(err, 547);
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
fail: (err) => {
|
||||
this.$u.toast('文件下载失败');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const openDocument = (filePath) => {
|
||||
uni.openDocument({
|
||||
filePath,
|
||||
showMenu: true,
|
||||
success: () => {},
|
||||
fail: (err) => {
|
||||
console.error('打开文档失败:', err);
|
||||
this.$u.toast('文件打开失败');
|
||||
}
|
||||
});
|
||||
}
|
||||
handleDownload();
|
||||
},
|
||||
previewFile(item) {
|
||||
let fileTypes = ['doc', 'xls', 'ppt', 'pdf', 'docx', 'xlsx', 'pptx', 'txt']
|
||||
let fileType = item.name.split('.')[1]
|
||||
if (fileTypes.includes(fileType)) {
|
||||
uni.downloadFile({
|
||||
url: `${this.baseURL}${ item.url}&name=${item.name}`,
|
||||
success: (res) => {
|
||||
let filePath = res.tempFilePath;
|
||||
uni.openDocument({
|
||||
filePath,
|
||||
showMenu: true,
|
||||
success: (res) => {}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.$u.toast('该文件类型无法打开')
|
||||
}
|
||||
},
|
||||
checkboxChange(e) {
|
||||
if (e.length) {
|
||||
this.slide = 'slide-up'
|
||||
this.slide2 = 'slide-up2'
|
||||
const {
|
||||
platform
|
||||
} = uni.getSystemInfoSync()
|
||||
if (platform === 'ios' && this.current == 2) return this.show = false
|
||||
this.show = true
|
||||
} else {
|
||||
this.slide = 'slide-down'
|
||||
this.slide2 = 'slide-down2'
|
||||
}
|
||||
this.selectOperation(e)
|
||||
},
|
||||
change(e) {
|
||||
this.current = e
|
||||
this.parentId = 0
|
||||
this.resetList()
|
||||
},
|
||||
bottomfun(type) {
|
||||
if (type === 'down') this.downLoad()
|
||||
if (type === 'restName') {
|
||||
fileDetail(this.selectFiles[0]).then(res => {
|
||||
this.modalValue = res?.data?.fullName || ''
|
||||
this.modalType = 'restName'
|
||||
this.$refs.inputDialog.open()
|
||||
})
|
||||
}
|
||||
if (type === 'checkAll') this.checkedAllFun()
|
||||
if (type === 'revert') this.recoveryOrDelete(type)
|
||||
if (type === 'delete') this.recoveryOrDelete(type)
|
||||
if (type === 'share') {
|
||||
if (this.current == 1) return this.shareUser()
|
||||
this.usersSelectValue = ''
|
||||
this.$nextTick(() => {
|
||||
this.$refs.JnpfUsersSelect.openSelect()
|
||||
})
|
||||
}
|
||||
if (type === 'shareCancel') return this.cancelShare()
|
||||
if (type === 'move') this.getFolderTree()
|
||||
if (type === 'cancel') {
|
||||
this.selectFiles = []
|
||||
this.selectOperation(this.selectFiles)
|
||||
}
|
||||
},
|
||||
cancelShare() {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '您确定要取消共享, 是否继续?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
cancelShare({
|
||||
ids: this.selectFiles
|
||||
}).then(res => {
|
||||
this.$u.toast(res.msg)
|
||||
this.resetList()
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
shareUser() {
|
||||
shareUser(this.selectFiles[0]).then(res => {
|
||||
let list = res.data.list || []
|
||||
const ids = list.map(item => item.shareUserId);
|
||||
this.usersSelectValue = ids
|
||||
this.$nextTick(() => {
|
||||
this.$refs.JnpfUsersSelect.openSelect()
|
||||
})
|
||||
})
|
||||
},
|
||||
folderMove() {
|
||||
let data = {
|
||||
ids: this.selectFiles,
|
||||
id: this.moveId
|
||||
}
|
||||
folderMove(data).then(res => {
|
||||
this.selectFiles = []
|
||||
this.close()
|
||||
this.resetList()
|
||||
})
|
||||
},
|
||||
iconClick() {
|
||||
if (this.documentList.length) this.changeStyle = !this.changeStyle
|
||||
},
|
||||
|
||||
close() {
|
||||
this.showApply = false
|
||||
},
|
||||
checkedAllFun() {
|
||||
this.checkedAll = !this.checkedAll
|
||||
this.selectFiles = [];
|
||||
this.documentList.forEach(o => {
|
||||
if (this.checkedAll) {
|
||||
this.$set(o, 'checked', true)
|
||||
this.selectFiles.push(o.id);
|
||||
} else {
|
||||
this.$set(o, 'checked', false)
|
||||
this.selectFiles = [];
|
||||
}
|
||||
})
|
||||
},
|
||||
goDetail(e) {
|
||||
if (e.type == 0 && this.current != 3) {
|
||||
if (!this.isDetail) {
|
||||
let item = {
|
||||
current: this.current,
|
||||
changeStyle: this.changeStyle,
|
||||
...e
|
||||
}
|
||||
this.selectFiles = []
|
||||
this.selectOperation()
|
||||
uni.navigateTo({
|
||||
url: './detail?config=' + JSON.stringify(item),
|
||||
});
|
||||
} else {
|
||||
this.parentId = e.id
|
||||
this.setTitle(e.fullName)
|
||||
this.pushTreeStack(e);
|
||||
this.resetList()
|
||||
}
|
||||
} else {
|
||||
if (imgTypeList.includes(e.fileExtension)) {
|
||||
const images = jnpf.getAuthImgUrl(e.uploaderUrl, false);
|
||||
uni.previewImage({
|
||||
urls: [images],
|
||||
success: (res) => {},
|
||||
fail: (err) => {
|
||||
uni.showToast({
|
||||
title: '预览图片失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
return
|
||||
}
|
||||
if (this.current !== 3) this.downLoad([e.id])
|
||||
}
|
||||
},
|
||||
selectOperation(value) {
|
||||
let items = this.documentList;
|
||||
this.selectFiles = value || [];
|
||||
for (let i = 0, lenI = items.length; i < lenI; ++i) {
|
||||
const item = items[i]
|
||||
if (this.selectFiles.includes(item.id)) {
|
||||
this.$set(item, 'checked', true)
|
||||
} else {
|
||||
this.$set(item, 'checked', false)
|
||||
}
|
||||
}
|
||||
},
|
||||
getRecordImg(ext) {
|
||||
if (!ext) return this.folderImg;
|
||||
if (ext) ext = ext.replace('.', '');
|
||||
if (wordTypeList.includes(ext)) return this.wordImg;
|
||||
if (excelTypeList.includes(ext)) return this.excelImg;
|
||||
if (pptTypeList.includes(ext)) return this.pptImg;
|
||||
if (pdfTypeList.includes(ext)) return this.pdfImg;
|
||||
if (zipTypeList.includes(ext)) return this.rarImg;
|
||||
if (txtTypeList.includes(ext)) return this.txtImg;
|
||||
if (codeTypeList.includes(ext)) return this.codeImg;
|
||||
if (imgTypeList.includes(ext)) return this.imageImg;
|
||||
if (videoTypeList.includes(ext)) return this.audioImg;
|
||||
return this.blankImg;
|
||||
},
|
||||
getFolderTree() {
|
||||
let data = {
|
||||
ids: this.selectFiles
|
||||
}
|
||||
folderTree(data).then(res => {
|
||||
this.showApply = true
|
||||
this.folderTreeList = JSON.parse(JSON.stringify(res.data.list)) || []
|
||||
const loop = (list, parent) => {
|
||||
list.forEach(o => {
|
||||
o.icon = 'icon-ym icon-ym-folder';
|
||||
if (o && o.children && Array.isArray(o.children)) {
|
||||
loop(o.children, o)
|
||||
}
|
||||
})
|
||||
}
|
||||
loop(this.folderTreeList)
|
||||
})
|
||||
},
|
||||
recoveryOrDelete(type) {
|
||||
let data = {
|
||||
ids: this.selectFiles
|
||||
}
|
||||
let content = '确定要还原选中的文件吗'
|
||||
let method = recovery
|
||||
if (type !== 'revert') {
|
||||
content = '删除后,放入回收站!'
|
||||
method = batchDelete
|
||||
if (type === 'delete' && this.current == 3) {
|
||||
content = '删除后数据无法恢复'
|
||||
method = trashDelete
|
||||
}
|
||||
}
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content,
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.$nextTick(() => {
|
||||
method(JSON.stringify(data)).then(res => {
|
||||
this.$u.toast(res.msg)
|
||||
setTimeout(() => {
|
||||
this.$nextTick(() => {
|
||||
this.documentList = [];
|
||||
this.selectFiles = []
|
||||
this.mescroll.resetUpScroll();
|
||||
})
|
||||
}, 1000)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/* 新建文件 */
|
||||
handleAddFolder() {
|
||||
let item = {
|
||||
id: '',
|
||||
parentId: this.parentId,
|
||||
type: 0,
|
||||
fullName: this.modalValue
|
||||
}
|
||||
addFolder(item).then(res => {
|
||||
this.modalType = 'restName'
|
||||
this.closeDialog()
|
||||
this.resetList()
|
||||
})
|
||||
},
|
||||
/* 重命名 */
|
||||
closeDialog() {
|
||||
this.$refs.inputDialog.close()
|
||||
},
|
||||
restName(e) {
|
||||
let txt = this.modalType === 'addFolder' ? '文件夹名称不能为空' : '文件名不能为空'
|
||||
if (!this.modalValue) return this.$u.toast(txt)
|
||||
if (this.modalType === 'addFolder') return this.handleAddFolder()
|
||||
if (this.modalType === 'restName') return this.handleRestName()
|
||||
},
|
||||
handleRestName() {
|
||||
let item = {}
|
||||
this.documentList.forEach(o => {
|
||||
if (o.id === this.selectFiles[0]) item = {
|
||||
id: o.id,
|
||||
parentId: this.parentId,
|
||||
type: o.type,
|
||||
fullName: this.modalValue
|
||||
}
|
||||
})
|
||||
resetFileName(item).then(res => {
|
||||
this.selectFiles = []
|
||||
this.closeDialog()
|
||||
this.resetList()
|
||||
})
|
||||
},
|
||||
resetList() {
|
||||
this.$nextTick(() => {
|
||||
this.selectFiles = []
|
||||
this.documentList = [];
|
||||
this.mescroll.resetUpScroll();
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
BIN
pages/workFlow/document/static/audio.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
pages/workFlow/document/static/blank.png
Normal file
|
After Width: | Height: | Size: 594 B |
BIN
pages/workFlow/document/static/code.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
pages/workFlow/document/static/excel.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
pages/workFlow/document/static/folder.png
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
pages/workFlow/document/static/image.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
pages/workFlow/document/static/pdf.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
pages/workFlow/document/static/ppt.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
pages/workFlow/document/static/rar.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
pages/workFlow/document/static/txt.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
pages/workFlow/document/static/word.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
292
pages/workFlow/entrustAgent/components/flowSelect/Select.vue
Normal file
@@ -0,0 +1,292 @@
|
||||
<template>
|
||||
<u-popup class="jnpf-tree-select-popup" :maskCloseAble="maskCloseAble" mode="right" :popup="false"
|
||||
v-model="showPopup" :safeAreaInsetBottom="safeAreaInsetBottom" :z-index="uZIndex" width="100%">
|
||||
<view class="jnpf-tree-select-body">
|
||||
<view class="jnpf-tree-select-title">
|
||||
<text class="icon-ym icon-ym-report-icon-preview-pagePre u-font-40 backIcon"
|
||||
@click.stop="handleConfirm"></text>
|
||||
<view class="title">{{$t('app.my.flowSelect')}}</view>
|
||||
</view>
|
||||
<view class="jnpf-tree-select-search">
|
||||
<u-search :placeholder="$t('app.apply.pleaseKeyword')" v-model="keyword" height="72"
|
||||
:show-action="false" @change="search(swiperCurrent)" bg-color="#f0f2f6" shape="square">
|
||||
</u-search>
|
||||
</view>
|
||||
<view class="jnpf-tree-selected">
|
||||
<view class="jnpf-tree-selected-head">
|
||||
<view>{{$t('component.jnpf.common.selected')}}</view>
|
||||
<view v-if="multiple" class="clear-btn" @click="cleanAll">{{$t('component.jnpf.common.clearAll')}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="jnpf-tree-selected-box">
|
||||
<scroll-view scroll-y="true" style="max-height: 180rpx;height: 180rpx;">
|
||||
<view class="jnpf-tree-selected-list">
|
||||
<view class="u-selectTag u-selectTag-flow" v-for="(list,index) in selectList" :key="index">
|
||||
<view class="jnpf-tree-selected-content">
|
||||
<view class="name-box">
|
||||
<view class="name">{{list.fullName}}</view>
|
||||
<u-icon name="close" class="close" @click='delSelect(index)'></u-icon>
|
||||
</view>
|
||||
<view class="organize">{{list.organize}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="sticky-tabs">
|
||||
<u-tabs ref="tabs" :list="tabsList" :current="tabIndex" @change="tabChange" :is-scroll="true"
|
||||
name="fullName">
|
||||
</u-tabs>
|
||||
</view>
|
||||
<view class="jnpf-tree-select-tree">
|
||||
<scroll-view :style="{height: '100%'}" :refresher-enabled="false" :refresher-threshold="100"
|
||||
:scroll-with-animation='true' :refresher-triggered="triggered" @scrolltolower="handleScrollToLower"
|
||||
:scroll-y="true">
|
||||
<view class="lists_box list_top">
|
||||
<view class="list-cell-txt" v-for="(list,index) in list" :key="index"
|
||||
@click="handleNodeClick(list)">
|
||||
<view class="u-font-30 content">
|
||||
<view class="nameSty">{{list.fullName}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<JnpfEmpty v-if="list.length<1"></JnpfEmpty>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- 底部按钮 -->
|
||||
<view class="jnpf-tree-select-actions">
|
||||
<u-button class="buttom-btn" @click.stop="handleConfirm">{{$t('common.cancelText')}}</u-button>
|
||||
<u-button class="buttom-btn" type="primary"
|
||||
@click.stop="handleConfirm">{{$t('common.okText')}}</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getSystemList
|
||||
} from '@/api/system'
|
||||
import {
|
||||
getFlowSelector
|
||||
} from '@/api/workFlow/flowEngine'
|
||||
import {
|
||||
useBaseStore
|
||||
} from '@/store/modules/base'
|
||||
|
||||
const baseStore = useBaseStore()
|
||||
export default {
|
||||
props: {
|
||||
selectType: {
|
||||
type: String,
|
||||
default: 'all'
|
||||
},
|
||||
selectedData: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
// 通过双向绑定控制组件的弹出与收起
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 弹出的z-index值
|
||||
zIndex: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
safeAreaInsetBottom: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否允许通过点击遮罩关闭Picker
|
||||
maskCloseAble: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
//多选
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 顶部标题
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isAuthority: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tabWidth: 150,
|
||||
tabIndex: 0,
|
||||
tabsList: [],
|
||||
keyword: '',
|
||||
selectList: [],
|
||||
list: [],
|
||||
// 因为内部的滑动机制限制,请将tabs组件和swiper组件的current用不同变量赋值
|
||||
current: 0, // tabs组件的current值,表示当前活动的tab选项
|
||||
swiperCurrent: 0, // swiper组件的current值,表示当前那个swiper-item是活动的
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
pageSize: 20
|
||||
},
|
||||
total: 0,
|
||||
categoryId: '',
|
||||
triggered: false,
|
||||
moving: false,
|
||||
showPopup: false,
|
||||
systemId: ''
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
// 在select弹起的时候,重新初始化所有数据
|
||||
modelValue: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
this.showPopup = val
|
||||
if (val) setTimeout(() => this.init(), 10);
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
uZIndex() {
|
||||
// 如果用户有传递z-index值,优先使用
|
||||
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
setTimeout(() => {
|
||||
this.triggered = true;
|
||||
}, 1000)
|
||||
this.getSystemList()
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.upCallback()
|
||||
this.selectList = JSON.parse(JSON.stringify(this.selectedData)) || []
|
||||
// #ifdef MP-WEIXIN
|
||||
this.$nextTick(() => {
|
||||
this.$refs.tabs.init()
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
getSystemList() {
|
||||
getSystemList().then(res => {
|
||||
this.tabsList.push({
|
||||
id: 0,
|
||||
encode: "all",
|
||||
fullName: "全部流程",
|
||||
})
|
||||
this.tabsList.push(...res.data)
|
||||
})
|
||||
},
|
||||
delSelect(index) {
|
||||
this.selectList.splice(index, 1);
|
||||
},
|
||||
cleanAll() {
|
||||
this.selectList = [];
|
||||
},
|
||||
handleNodeClick(obj) {
|
||||
if (!this.multiple) this.selectList = []
|
||||
var isExist = false;
|
||||
for (var i = 0; i < this.selectList.length; i++) {
|
||||
if (this.selectList[i].id == obj.id) {
|
||||
isExist = true;
|
||||
break;
|
||||
}
|
||||
};
|
||||
!isExist && this.selectList.push(obj);
|
||||
},
|
||||
//父组件调用
|
||||
resetData() {
|
||||
this.list = []
|
||||
this.pagination = {
|
||||
currentPage: 1,
|
||||
pageSize: 20
|
||||
}
|
||||
},
|
||||
search(index) {
|
||||
this.pagination.currentPage = 1
|
||||
this.searchTimer && clearTimeout(this.searchTimer)
|
||||
this.searchTimer = setTimeout(() => {
|
||||
this.list = [];
|
||||
this.upCallback()
|
||||
}, 300)
|
||||
},
|
||||
// 切换菜单
|
||||
tabChange(index) {
|
||||
this.tabIndex = index
|
||||
this.pagination.currentPage = 1
|
||||
this.fullName = this.tabsList[this.tabIndex].fullName
|
||||
this.categoryId = ""
|
||||
this.systemId = !this.tabsList[this.tabIndex].id ? '' : this.tabsList[this.tabIndex].id
|
||||
this.list = [];
|
||||
this.upCallback()
|
||||
},
|
||||
handleScrollToLower() {
|
||||
if (this.pagination.pageSize * this.pagination.currentPage < this.total) {
|
||||
this.pagination.currentPage = this.pagination.currentPage + 1;
|
||||
this.upCallback()
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '没有更多信息啦!',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
upCallback() {
|
||||
let query = {
|
||||
currentPage: this.pagination.currentPage,
|
||||
pageSize: this.pagination.pageSize,
|
||||
keyword: this.keyword,
|
||||
category: this.categoryId ? this.categoryId : "",
|
||||
isAuthority: this.isAuthority == 2 ? 0 : 1,
|
||||
isDelegate: 1,
|
||||
systemId: this.systemId
|
||||
}
|
||||
this.loading = false
|
||||
getFlowSelector(query).then(res => {
|
||||
const list = res.data.list || [];
|
||||
list.map((o) => {
|
||||
o.fullName = o.fullName + '/' + o.enCode
|
||||
})
|
||||
this.list = this.list.concat(list);
|
||||
this.pagination = res.data.pagination
|
||||
this.total = this.pagination.total
|
||||
})
|
||||
},
|
||||
handleConfirm() {
|
||||
// #ifdef MP-WEIXIN
|
||||
if (this.moving) return;
|
||||
// #endif
|
||||
this.keyword = '';
|
||||
this.$emit('confirm', this.selectList);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.lists_box {
|
||||
height: 100%;
|
||||
|
||||
.list-cell-txt {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
padding: 20rpx 32rpx;
|
||||
overflow: hidden;
|
||||
color: $u-content-color;
|
||||
font-size: 28rpx;
|
||||
line-height: 48rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
111
pages/workFlow/entrustAgent/components/flowSelect/index.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<view class="jnpf-tree-select">
|
||||
<u-input input-align='right' type="select" :select-open="selectShow" v-model="innerValue"
|
||||
:placeholder="placeholder" @click="openSelect"></u-input>
|
||||
<flowSelect v-model="selectShow" @confirm="selectConfirm" :multiple="multiple" :selectedData="selectedData"
|
||||
:clearable="clearable" ref="flowSelect" :isAuthority='current'>
|
||||
</flowSelect>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import flowSelect from './Select.vue';
|
||||
import {
|
||||
getFlowEngineListByIds
|
||||
} from '@/api/workFlow/flowEngine.js'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
flowSelect
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
default: ''
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择'
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
current: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectShow: false,
|
||||
innerValue: '',
|
||||
selectedData: [],
|
||||
selectedIds: [],
|
||||
delegateUser: '',
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
modelValue: {
|
||||
handler(val) {
|
||||
if (!val || !val.length) return this.innerValue = ''
|
||||
this.setDefault(val)
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setDefault(id) {
|
||||
if (!id || !id.length) return this.innerValue = ''
|
||||
getFlowEngineListByIds(id).then(res => {
|
||||
let data = res.data || []
|
||||
this.innerValue = data.map(o => o.fullName).join()
|
||||
this.selectedData = data.map(o => {
|
||||
return {
|
||||
...o,
|
||||
fullName: o.fullName + '/' + o.enCode,
|
||||
};
|
||||
});
|
||||
})
|
||||
},
|
||||
openSelect() {
|
||||
if (this.disabled) return
|
||||
this.selectShow = true
|
||||
this.$refs.flowSelect.resetData()
|
||||
this.setDefault()
|
||||
},
|
||||
selectConfirm(e) {
|
||||
this.selectShow = false
|
||||
this.selectedData = e;
|
||||
let label = ''
|
||||
let value = []
|
||||
this.defaultValue = []
|
||||
for (let i = 0; i < e.length; i++) {
|
||||
label += (i ? ',' : '') + e[i].fullName
|
||||
value.push(e[i].id)
|
||||
}
|
||||
this.defaultValue = value
|
||||
this.innerValue = label
|
||||
if (!this.multiple) {
|
||||
this.$emit('update:modelValue', value)
|
||||
this.$emit('change', value.join(), e[0])
|
||||
return
|
||||
}
|
||||
this.$emit('update:modelValue', value)
|
||||
this.$emit('change', value, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.jnpf-tree-select {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,244 @@
|
||||
<template>
|
||||
<u-popup class="jnpf-tree-select-popup" mode="right" v-model="showPopup" width="100%" @close="close">
|
||||
<view class="jnpf-tree-select-body">
|
||||
<view class="jnpf-tree-select-title">
|
||||
<text class="icon-ym icon-ym-report-icon-preview-pagePre backIcon" @tap="close()"></text>
|
||||
<view class="title">选择用户</view>
|
||||
</view>
|
||||
<view class="jnpf-tree-select-search">
|
||||
<u-search :placeholder="$t('app.apply.pleaseKeyword')" v-model="keyword" height="72"
|
||||
@clear="handleSearch" :show-action="false" @change="handleSearch" bg-color="#f0f2f6" shape="square">
|
||||
</u-search>
|
||||
</view>
|
||||
<view class="jnpf-tree-selected">
|
||||
<view class="jnpf-tree-selected-head">
|
||||
<view>{{$t('component.jnpf.common.selected')}}({{selectedList.length||0}})</view>
|
||||
<view v-if="multiple" class="clear-btn" @click="setCheckAll">
|
||||
{{$t('component.jnpf.common.clearAll')}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="jnpf-tree-selected-box">
|
||||
<scroll-view scroll-y="true" class="select-list">
|
||||
<u-tag closeable @close="delSelect(index)" v-for="(item,index) in selectedList" :key="index"
|
||||
:text="item.orgNameTree" class="u-selectTag" />
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="jnpf-tree-selected-line"></view>
|
||||
<view class="jnpf-tree-selected-tabs">
|
||||
<view class="tab-item" :class="{'tab-item-active':activeKey==='user'}">
|
||||
用户
|
||||
</view>
|
||||
</view>
|
||||
<view class="jnpf-tree-select-tree">
|
||||
<scroll-view :scroll-y="true" style="height: 100%" :refresher-enabled="false" :refresher-threshold="100"
|
||||
:scroll-with-animation='true' :refresher-triggered="triggered" @scrolltolower="handleScrollToLower">
|
||||
<view class="jnpf-selcet-list" v-if="userList.length">
|
||||
<view class="jnpf-selcet-cell" v-for="item in userList" :key="item.id"
|
||||
@click.stop="handleUserNodeClick(item)">
|
||||
<view class="jnpf-selcet-cell-action">
|
||||
<lyCheckbox :type="multiple ? 'checkbox' : 'radio'"
|
||||
:checked="selectedIds.includes(item.id)" />
|
||||
</view>
|
||||
<u-avatar class="jnpf-selcet-cell-avatar" :src="baseURL+item.headIcon" mode="circle"
|
||||
size="44" v-if="activeKey==='user'"></u-avatar>
|
||||
<view class="jnpf-selcet-cell-name">
|
||||
{{item.orgNameTree}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<JnpfEmpty class="h-full" v-else />
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- 底部按钮 -->
|
||||
<view class="jnpf-tree-select-actions">
|
||||
<u-button class="buttom-btn" @click="close()">{{$t('common.cancelText')}}</u-button>
|
||||
<u-button class="buttom-btn" type="primary"
|
||||
@click.stop="handleConfirm()">{{$t('common.okText')}}</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
getReceiveUserList
|
||||
} from '@/api/common'
|
||||
import lyCheckbox from '@/components/ly-tree/components/ly-checkbox.vue';
|
||||
import {
|
||||
useBaseStore
|
||||
} from '@/store/modules/base'
|
||||
export default {
|
||||
props: {
|
||||
selectedData: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 通过双向绑定控制组件的弹出与收起
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 弹出的z-index值
|
||||
zIndex: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
props: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
label: 'fullName',
|
||||
value: 'id',
|
||||
icon: 'icon',
|
||||
children: 'children',
|
||||
isLeaf: 'isLeaf'
|
||||
})
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
hasSys: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
type: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
components: {
|
||||
lyCheckbox
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
moving: false,
|
||||
selectedList: [],
|
||||
selectedIds: [],
|
||||
keyword: '',
|
||||
showPopup: false,
|
||||
lazyOptions: [],
|
||||
activeKey: 'user',
|
||||
hasPage: false,
|
||||
pagination: {
|
||||
hasPage: 1,
|
||||
currentPage: 1,
|
||||
pageSize: 20
|
||||
},
|
||||
triggered: false,
|
||||
finish: false,
|
||||
list: [],
|
||||
userList: [],
|
||||
scrollTop: 0,
|
||||
currStep: 0,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
// 在select弹起的时候,重新初始化所有数据
|
||||
modelValue: {
|
||||
handler(val) {
|
||||
this.showPopup = val
|
||||
this.keyword = ""
|
||||
if (val) setTimeout(() => this.init(), 10);
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
selectedList: {
|
||||
handler(val) {
|
||||
this.selectedIds = val.map((o) => o.id);
|
||||
this.$refs.tree && this.$refs.tree.setCheckedKeys(this.selectedIds)
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
},
|
||||
uZIndex() {
|
||||
// 如果用户有传递z-index值,优先使用
|
||||
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
|
||||
},
|
||||
realProps() {
|
||||
return {
|
||||
...defaultProps,
|
||||
...this.props
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.hasPage = 0
|
||||
this.currStep = 0
|
||||
this.activeKey = 'user'
|
||||
this.resetQuery()
|
||||
this.$nextTick(() => {
|
||||
this.triggered = true
|
||||
})
|
||||
this.selectedList = JSON.parse(JSON.stringify(this.selectedData))
|
||||
this.getUserList()
|
||||
},
|
||||
resetQuery() {
|
||||
this.userList = []
|
||||
this.finish = false
|
||||
this.pagination.currentPage = 1
|
||||
},
|
||||
handleScroll(e) {
|
||||
this.scrollTop = e.detail.scrollTop
|
||||
},
|
||||
goTop() {
|
||||
this.scrollTop = 0
|
||||
},
|
||||
handleScrollToLower() {
|
||||
if (this.finish || this.activeKey !== 'user') return
|
||||
this.getUserList()
|
||||
},
|
||||
getUserList() {
|
||||
let data = {
|
||||
keyword: this.keyword,
|
||||
...this.pagination,
|
||||
type: this.type
|
||||
}
|
||||
getReceiveUserList(data).then(res => {
|
||||
const list = (res.data.list || []).map((o) => ({
|
||||
...o,
|
||||
id: o.id,
|
||||
orgNameTree: o.orgNameTree || o.fullName
|
||||
}));
|
||||
if (list.length < this.pagination.pageSize) this.finish = true;
|
||||
this.userList = this.userList.concat(list);
|
||||
this.pagination.currentPage++
|
||||
})
|
||||
},
|
||||
handleUserNodeClick(data) {
|
||||
const index = this.selectedList.findIndex((o) => o.id === data.id);
|
||||
if (index !== -1) return this.selectedList.splice(index, 1);
|
||||
this.multiple ? this.selectedList.push(data) : (this.selectedList = [data]);
|
||||
},
|
||||
delSelect(index) {
|
||||
this.selectedList.splice(index, 1);
|
||||
},
|
||||
setCheckAll() {
|
||||
this.selectedIds = []
|
||||
this.selectedList = []
|
||||
},
|
||||
handleConfirm() {
|
||||
this.$emit('confirm', this.selectedList, this.selectedIds);
|
||||
this.close();
|
||||
},
|
||||
close() {
|
||||
this.$emit('close', false);
|
||||
},
|
||||
handleSearch(val) {
|
||||
this.keyword = val || ""
|
||||
this.hasPage = !!val
|
||||
this.currStep = val ? 1 : 0
|
||||
this.goTop()
|
||||
if (this.activeKey != 'user') this.activeKey = 'user'
|
||||
this.$nextTick(() => {
|
||||
this.resetQuery()
|
||||
this.$u.debounce(this.getUserList, 300)
|
||||
})
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
96
pages/workFlow/entrustAgent/components/userSelect/index.vue
Normal file
@@ -0,0 +1,96 @@
|
||||
<template>
|
||||
<view class="jnpf-users-select w-full">
|
||||
<selectBox v-model="innerValue" :placeholder="placeholder" @openSelect="openSelect" :select-open="selectShow"
|
||||
:disabled="disabled" v-if="isInput" />
|
||||
<SelectPopup v-model="selectShow" :selectedData="selectedData" :hasSys="hasSys" @close="handleClose"
|
||||
@confirm="handleConfirm" :type="type" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SelectPopup from './SelectPopup';
|
||||
import selectBox from '@/components/selectBox'
|
||||
import {
|
||||
getSelectedList
|
||||
} from '@/api/common'
|
||||
export default {
|
||||
name: 'jnpf-users-select',
|
||||
components: {
|
||||
SelectPopup,
|
||||
selectBox
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
default: ''
|
||||
},
|
||||
isInput: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择'
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
hasSys: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
type: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectShow: false,
|
||||
innerValue: '',
|
||||
selectedData: [],
|
||||
multiple: true
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
modelValue: {
|
||||
handler() {
|
||||
this.setDefault()
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setDefault() {
|
||||
if (!this.modelValue || !this.modelValue.length) return this.setNullValue();
|
||||
const ids = this.multiple ? this.modelValue : [this.modelValue];
|
||||
getSelectedList(ids).then((res) => {
|
||||
if (!this.modelValue || !this.modelValue.length) return this.setNullValue();
|
||||
const selectedData = res.data.list || []
|
||||
this.selectedData = selectedData
|
||||
this.innerValue = this.selectedData.map(o => o.orgNameTree).join();
|
||||
});
|
||||
},
|
||||
setNullValue() {
|
||||
this.innerValue = '';
|
||||
this.selectedData = [];
|
||||
},
|
||||
openSelect() {
|
||||
if (this.disabled) return
|
||||
this.selectShow = true
|
||||
},
|
||||
handleConfirm(selectedData, selectedIds) {
|
||||
if (!this.multiple) {
|
||||
this.$emit('update:modelValue', selectedIds[0])
|
||||
this.$emit('change', selectedIds[0], selectedData[0])
|
||||
} else {
|
||||
this.$emit('update:modelValue', selectedIds)
|
||||
this.$emit('change', selectedIds, selectedData)
|
||||
}
|
||||
},
|
||||
handleClose() {
|
||||
this.selectShow = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
198
pages/workFlow/entrustAgent/detail.vue
Normal file
@@ -0,0 +1,198 @@
|
||||
<template>
|
||||
<view class="jnpf-wrap personalData">
|
||||
<view class="u-p-l-20 u-p-r-20 content">
|
||||
<u-form :model="dataForm" :errorType="['toast']" label-width="180" label-align="left" ref="dataForm">
|
||||
<u-form-item :label="titleList[config?.current]" prop='toUserId' required>
|
||||
<view class="txt">
|
||||
{{dataForm.userName}}
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item v-if="config.current == 0 || config.current == 2">
|
||||
<view class="u-flex tag-box">
|
||||
<view v-for="(item,index) in infoList" :key="index" size="mini">{{item.toUserName}}<u-tag
|
||||
class="u-m-l-8" size="mini"
|
||||
:type="item.status=== 0?'info':item.status=== 1?'success':'error'"
|
||||
:text="item.status === 0 ? '待确认' : item.status === 1 ? '已接受' : '已拒绝'" /></view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item :label="config.current == 2 ? '代理流程' : '委托流程'">
|
||||
<view class="txt">{{dataForm.flowName}}</view>
|
||||
</u-form-item>
|
||||
<u-form-item label="开始时间" prop='startTime' required>
|
||||
<view class="txt">
|
||||
{{$u.timeFormat(dataForm.startTime,'yyyy-mm-dd hh:MM:ss')}}
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item label="结束时间" prop='endTime' required>
|
||||
<view class="txt">
|
||||
{{$u.timeFormat(dataForm.endTime,'yyyy-mm-dd hh:MM:ss')}}
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item label="委托说明">
|
||||
<u-input input-align='right' v-model="dataForm.description" type="textarea" placeholder="请输入"
|
||||
disabled />
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
</view>
|
||||
<view class="flowBefore-actions" v-if="config.confirmStatus != 1 && config.status != 2">
|
||||
<u-button class="buttom-btn" type="primary" @click.stop="jumpForm"
|
||||
v-if="isEdit">{{$t('common.editText')}}</u-button>
|
||||
<template v-if='isAccept'>
|
||||
<u-button class="buttom-btn" type="primary" @click.stop="getResult('accept')">接受</u-button>
|
||||
<u-button class="buttom-btn" @click="getResult('refuse')" type="error">拒绝</u-button>
|
||||
</template>
|
||||
<u-button class="buttom-btn" type="primary" @click.stop="entrustStop" v-if="isStop">终止</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
entrustStop,
|
||||
getPrincipalDetails,
|
||||
entrustHandle,
|
||||
FlowDelegateInfo
|
||||
} from '@/api/workFlow/entrust.js'
|
||||
export default {
|
||||
data() {
|
||||
const data = {
|
||||
dataForm: {
|
||||
id: '',
|
||||
userId: '',
|
||||
toUserId: [],
|
||||
flowId: [],
|
||||
description: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
flowName: '',
|
||||
toUserName: '',
|
||||
type: undefined,
|
||||
},
|
||||
config: {},
|
||||
infoList: [],
|
||||
titleList: ['受委托人', '委托人', '代理人', '被代理人'],
|
||||
}
|
||||
return data
|
||||
},
|
||||
computed: {
|
||||
isAccept() {
|
||||
if (this.config.current == 1 && this.config.confirmStatus == 2) return false
|
||||
if (this.config.current == 0 || this.config.current == 2) return false
|
||||
if (this.config.status == 0 || this.config.status == 1) return true
|
||||
return false
|
||||
},
|
||||
isStop() {
|
||||
return (this.config.current == 0 || this.config.current == 2) && this.config.status == 1
|
||||
},
|
||||
isEdit() {
|
||||
return (this.config.current == 0 || this.config.current == 2) && this.config.status == 0
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
uni.$on('refreshDetail', () => {
|
||||
this.flowDelegateInfo()
|
||||
})
|
||||
},
|
||||
onUnload() {
|
||||
uni.$emit('refresh')
|
||||
uni.$off('refreshDetail')
|
||||
},
|
||||
onLoad(e) {
|
||||
this.config = JSON.parse(decodeURIComponent(e.data));
|
||||
if (this.config) this.init()
|
||||
},
|
||||
methods: {
|
||||
flowDelegateInfo() {
|
||||
FlowDelegateInfo(this.config.id).then(res => {
|
||||
this.dataForm = res.data || {}
|
||||
this.dataForm.flowId = this.dataForm.flowId ? this.dataForm.flowId.split(",") : [];
|
||||
this.config = {
|
||||
...this.config,
|
||||
...this.dataForm
|
||||
}
|
||||
if (this.dataForm.id) {
|
||||
if (this.config.current == 0 || this.config.current == 2) this.getPrincipalDetails()
|
||||
}
|
||||
})
|
||||
},
|
||||
init() {
|
||||
this.dataForm.id = this.config.id || ''
|
||||
this.dataForm.userName = this.config.userName
|
||||
this.dataForm.flowName = this.config.flowName
|
||||
this.dataForm.description = this.config.description
|
||||
this.dataForm.startTime = this.config.startTime
|
||||
this.dataForm.endTime = this.config.endTime
|
||||
if (this.dataForm.id) {
|
||||
if (this.config.current == 1) this.dataForm = this.config || {}
|
||||
if (this.config.current == 0 || this.config.current == 2) this.getPrincipalDetails()
|
||||
}
|
||||
},
|
||||
getPrincipalDetails() {
|
||||
getPrincipalDetails(this.dataForm.id).then(res => {
|
||||
this.infoList = res.data || []
|
||||
this.dataForm.userName = this.infoList.map(o => o.toUserName).join()
|
||||
})
|
||||
},
|
||||
entrustStop() {
|
||||
let currTime = Math.round(new Date())
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '结束后,流程不再进行委托!',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
entrustStop(this.dataForm.id).then(res => {
|
||||
this.dataForm.endTime = currTime
|
||||
uni.$emit('refresh')
|
||||
uni.navigateBack()
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
getResult(entrustType) {
|
||||
let data = {
|
||||
'type': entrustType === 'accept' ? 1 : 2
|
||||
}
|
||||
entrustHandle(this.dataForm.id, data).then(res => {
|
||||
uni.$emit('refresh')
|
||||
uni.navigateBack()
|
||||
})
|
||||
},
|
||||
jumpForm() {
|
||||
let isEdit = this.infoList.some(o => o.status == 1)
|
||||
if (isEdit) return this.$u.toast("已有人接受,不可编辑");
|
||||
uni.navigateTo({
|
||||
url: `/pages/workFlow/entrustAgent/form?data=${encodeURIComponent(JSON.stringify(this.config))}`
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f0f2f6;
|
||||
}
|
||||
|
||||
.content {
|
||||
background-color: #fff;
|
||||
|
||||
:deep(.u-form-item) {
|
||||
min-height: 112rpx;
|
||||
}
|
||||
|
||||
.u-form {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tag-box {
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.txt {
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
295
pages/workFlow/entrustAgent/form.vue
Normal file
@@ -0,0 +1,295 @@
|
||||
<template>
|
||||
<view class="jnpf-wrap personalData">
|
||||
<view class="u-p-l-20 u-p-r-20 content">
|
||||
<u-form :model="dataForm" :errorType="['toast']" label-width="180" label-align="left" ref="dataForm">
|
||||
<u-form-item :label="titleList[config.current]" prop='toUserId' required>
|
||||
<JnpfUserSelect v-if="getTypeValue() === 1 " v-model="dataForm.toUserId" multiple
|
||||
:placeholder="$t('common.chooseText')" :disabled="disabled" @change="toChangeUser" />
|
||||
<userSelect v-else v-model="dataForm.toUserId" multiple :placeholder="$t('common.chooseText')"
|
||||
:disabled="disabled" @change="toChangeUser" :type="getTypeValue()" />
|
||||
</u-form-item>
|
||||
<u-form-item :label="config.current == 2 ? '代理流程' : '委托流程'">
|
||||
<FlowSelect v-model="dataForm.flowId" :placeholder="$t('app.my.allFlow')" multiple
|
||||
@change="onChange" :disabled="disabled" clearable :current="config.current" />
|
||||
</u-form-item>
|
||||
<u-form-item label="开始时间" prop='startTime' required>
|
||||
<JnpfDatePicker v-model="dataForm.startTime" :placeholder="$t('common.chooseTextPrefix')"
|
||||
:disabled="disabled" @change="change" format="yyyy-MM-dd HH:mm:ss" />
|
||||
</u-form-item>
|
||||
<u-form-item label="结束时间" prop='endTime' required>
|
||||
<JnpfDatePicker v-model="dataForm.endTime" :placeholder="$t('common.chooseTextPrefix')"
|
||||
@change="change" :disabled="disabled" format="yyyy-MM-dd HH:mm:ss" />
|
||||
</u-form-item>
|
||||
<u-form-item label="委托说明">
|
||||
<u-input input-align='right' v-model="dataForm.description" type="textarea"
|
||||
:placeholder="$t('common.inputTextPrefix')" :disabled="disabled" />
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
</view>
|
||||
<view class="flowBefore-actions">
|
||||
<u-button class="buttom-btn" type="primary" @click.stop="entrustStop"
|
||||
v-if="config.status == 1">{{$t('app.my.stop')}}</u-button>
|
||||
<template v-else>
|
||||
<u-button class="buttom-btn" @click="getResult('cancel')">{{$t('common.cancelText')}}</u-button>
|
||||
<u-button class="buttom-btn" type="primary"
|
||||
@click.stop="getResult('confirm')">{{$t('common.okText')}}</u-button>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
UpdateUser
|
||||
} from '@/api/common'
|
||||
import {
|
||||
Create,
|
||||
Update,
|
||||
FlowDelegateInfo
|
||||
} from '@/api/workFlow/entrust.js'
|
||||
import FlowSelect from './components/flowSelect/index.vue'
|
||||
import userSelect from './components/userSelect/index.vue'
|
||||
export default {
|
||||
components: {
|
||||
FlowSelect,
|
||||
userSelect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showBtn: false,
|
||||
showctionSheet: false,
|
||||
show: false,
|
||||
props: {
|
||||
label: 'fullName',
|
||||
value: 'enCode'
|
||||
},
|
||||
dataForm: {
|
||||
id: '',
|
||||
toUserId: [],
|
||||
flowId: [],
|
||||
description: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
flowName: '',
|
||||
toUserName: '',
|
||||
type: 0,
|
||||
},
|
||||
typeOptions: [{
|
||||
enCode: "0",
|
||||
fullName: '发起委托'
|
||||
}, {
|
||||
enCode: "1",
|
||||
fullName: '审批委托'
|
||||
}],
|
||||
userInfo: {},
|
||||
rules: {
|
||||
toUserId: [{
|
||||
required: true,
|
||||
message: `受委托人不能为空`,
|
||||
trigger: ['change', 'blur'],
|
||||
type: 'array'
|
||||
}],
|
||||
endTime: [{
|
||||
required: true,
|
||||
message: '结束时间不能为空',
|
||||
trigger: 'blur',
|
||||
type: 'number'
|
||||
}],
|
||||
startTime: [{
|
||||
required: true,
|
||||
message: '开始时间不能为空',
|
||||
trigger: 'blur',
|
||||
type: 'number'
|
||||
}]
|
||||
},
|
||||
disabled: false,
|
||||
config: {},
|
||||
titleList: ['受委托人', '委托人', '代理人', '被代理人'],
|
||||
type: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
}
|
||||
},
|
||||
onLoad(e) {
|
||||
this.userInfo = uni.getStorageSync('userInfo') || {}
|
||||
this.sysConfigInfo = uni.getStorageSync('sysConfigInfo') || {}
|
||||
if (e.data) this.config = JSON.parse(decodeURIComponent(e?.data));
|
||||
if (this.config) this.init()
|
||||
},
|
||||
methods: {
|
||||
getTypeValue() {
|
||||
return this.sysConfigInfo[this.type === 0 ? 'delegateScope' : 'proxyScope'];
|
||||
},
|
||||
init() {
|
||||
// 初始化配置
|
||||
this.type = this.config.type ?? 0 // 统一转为数字类型
|
||||
this.dataForm.id = this.config.id ?? ''
|
||||
|
||||
// 状态处理优化
|
||||
this.config.status ??= 0
|
||||
this.disabled = this.config.status === 1
|
||||
|
||||
// 系统配置处理(使用可选链操作符增强健壮性)
|
||||
const {
|
||||
delegateScope,
|
||||
proxyScope
|
||||
} = uni.getStorageSync('sysConfigInfo') || {}
|
||||
|
||||
// 类型映射处理(确保sysConfigInfo存在)
|
||||
if (this.sysConfigInfo) {
|
||||
const typeKey = this.type === 0 ? 'delegateScope' : 'proxyScope'
|
||||
this.type = this.sysConfigInfo[typeKey] ?? 0
|
||||
}
|
||||
|
||||
// 导航栏标题设置
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.dataForm.id ? this.$t('common.editText') : this.$t('common.addText')
|
||||
})
|
||||
|
||||
// 验证规则初始化
|
||||
const setValidationRules = () => {
|
||||
this.rules.toUserId[0].message = `${this.config.current === 2 ? '代理人' : '受委托人'}不能为空`
|
||||
if (this.config.current !== 2) {
|
||||
this.rules.type = [{
|
||||
required: true,
|
||||
message: '委托类型不能为空',
|
||||
trigger: ['change', 'blur'],
|
||||
type: 'number'
|
||||
}]
|
||||
}
|
||||
}
|
||||
this.type = this.dataForm.type
|
||||
// 表单初始化
|
||||
const initForm = async () => {
|
||||
if (this.dataForm.id) {
|
||||
try {
|
||||
const res = await FlowDelegateInfo(this.dataForm.id)
|
||||
this.dataForm = {
|
||||
...res.data,
|
||||
flowId: res.data?.flowId?.split(',') || []
|
||||
}
|
||||
this.type = this.dataForm.type
|
||||
} catch (error) {
|
||||
console.error('数据加载失败:', error)
|
||||
}
|
||||
}
|
||||
setValidationRules()
|
||||
this.$nextTick(() => {
|
||||
this.$refs.dataForm.setRules(this.rules)
|
||||
})
|
||||
}
|
||||
|
||||
// 执行初始化
|
||||
initForm()
|
||||
this.getTypeValue()
|
||||
// 统一设置数据类型
|
||||
this.dataForm.type = Number(this.type) || 0
|
||||
},
|
||||
entrustStop() {
|
||||
let currTime = Math.round(new Date())
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '结束后,流程不再进行委托!',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
entrustStop(this.dataForm.id).then(res => {
|
||||
this.dataForm.endTime = currTime
|
||||
uni.$emit('refresh')
|
||||
uni.navigateBack()
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
onChange(id, listData) {
|
||||
if (listData && listData.length) {
|
||||
let arr = []
|
||||
listData.forEach(item => {
|
||||
arr.push(item.fullName)
|
||||
})
|
||||
this.dataForm.flowName = arr.join(",")
|
||||
} else {
|
||||
this.dataForm.flowName = "全部流程"
|
||||
}
|
||||
},
|
||||
change(val, list) {
|
||||
this.$nextTick(() => {
|
||||
this.$emit('change', this.dataForm)
|
||||
})
|
||||
},
|
||||
toChangeUser(id, selectedData) {
|
||||
this.dataForm.toUserName = selectedData.map(user => user.fullName).join(',');
|
||||
return this.dataForm.toUserName
|
||||
},
|
||||
// 点击确定或者取消
|
||||
getResult(event = null) {
|
||||
// #ifdef MP-WEIXIN
|
||||
if (this.moving) return;
|
||||
// #endif
|
||||
this.keyword = '';
|
||||
if (event === 'cancel') return this.close();
|
||||
this.submit()
|
||||
},
|
||||
close() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
submit() {
|
||||
let startTime = this.dataForm.startTime;
|
||||
let endTime = this.dataForm.endTime;
|
||||
this.dataForm.type = this.config.type || 0
|
||||
this.$refs.dataForm.validate(valid => {
|
||||
if (valid) {
|
||||
if (startTime > endTime) return this.$u.toast('开始时间不能大于等于结束时间')
|
||||
const formMethod = this.dataForm.id ? Update : Create
|
||||
let params = {
|
||||
...this.dataForm
|
||||
}
|
||||
params.flowId = this.dataForm.flowId ? this.dataForm.flowId.join(",") : ""
|
||||
if (!params.flowId) params.flowName = "全部流程"
|
||||
formMethod(params).then(res => {
|
||||
uni.showToast({
|
||||
title: res.msg,
|
||||
complete: () => {
|
||||
setTimeout(() => {
|
||||
uni.$emit('refreshDetail')
|
||||
uni.navigateBack()
|
||||
}, 1500)
|
||||
}
|
||||
});
|
||||
}).catch()
|
||||
}
|
||||
});
|
||||
},
|
||||
onTypeChange() {
|
||||
this.dataForm.flowId = []
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f0f2f6;
|
||||
}
|
||||
|
||||
.content {
|
||||
background-color: #fff;
|
||||
|
||||
:deep(.u-form-item) {
|
||||
min-height: 112rpx;
|
||||
}
|
||||
|
||||
.u-form {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tag-box {
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
340
pages/workFlow/entrustAgent/index.vue
Normal file
@@ -0,0 +1,340 @@
|
||||
<template>
|
||||
<view class="flowLaunch-v">
|
||||
<view class="notice-warp">
|
||||
<view class="search-box">
|
||||
<u-search :placeholder="$t('app.apply.pleaseKeyword')" v-model="keyword" height="72"
|
||||
:show-action="false" @change="search" bg-color="#f0f2f6" shape="square" />
|
||||
</view>
|
||||
<u-tabs :list="entrustList" v-model="current" @change="change" :is-scroll='false' name="fullName">
|
||||
</u-tabs>
|
||||
</view>
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption"
|
||||
:up="upOption" :bottombar="false" top="115">
|
||||
<view class="flow-list">
|
||||
<view class="flow-list-box">
|
||||
<SwipeItem :list="list" :buttons="options" @action="handleClick" ref="swipeItem" :marginB="20">
|
||||
<template v-slot="{ item }">
|
||||
<view class="item" :id="'item'+item.index" ref="mydom" @click="goDetail(item)">
|
||||
<view class="item-left">
|
||||
<text class="title u-line-1 u-font-24 u-m-b-18">
|
||||
{{titleList[current]}}:
|
||||
<text
|
||||
class="titInner">{{current == '0' || current == '2' ? item.toUserName : item.userName }}</text>
|
||||
</text>
|
||||
<text class="title u-line-1 u-font-24 u-m-b-18">
|
||||
{{current == 2 ? '代理流程:' :'委托流程:' }}
|
||||
<text class="titInner">{{item.flowName ? item.flowName : ''}}</text>
|
||||
</text>
|
||||
<text class="time title u-font-24 u-m-b-18">
|
||||
开始时间:
|
||||
<text
|
||||
class="titInner">{{item.startTime?$u.timeFormat(item.startTime, 'yyyy-mm-dd hh:MM:ss'):''}}</text>
|
||||
</text>
|
||||
<text class="time title u-font-24 "
|
||||
:class="current == 1 || current == 3 ?'u-m-b-18': ''">
|
||||
结束时间:
|
||||
<text
|
||||
class="titInner">{{item.endTime?$u.timeFormat(item.endTime, 'yyyy-mm-dd hh:MM:ss'):''}}</text>
|
||||
</text>
|
||||
<view class="time title u-font-24" v-if="current == 1 || current == 3 ">
|
||||
确认状态:
|
||||
<u-tag
|
||||
:type="item.confirmStatus == 0 ? 'info' : item.confirmStatus == 1 ? 'success' : 'error'"
|
||||
:text="item.confirmStatus == 0 ? '待确认' : item.confirmStatus == 1 ? '已接受' : '已拒绝'"
|
||||
size="mini" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="item-right">
|
||||
<image :src="item.entrustStatus.flowStatus" mode="widthFix"
|
||||
class="item-right-img" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</SwipeItem>
|
||||
</view>
|
||||
</view>
|
||||
</mescroll-body>
|
||||
<view class="com-addBtn" v-if="current == 0 || current == 2" @click="addPage()">
|
||||
<u-icon name="plus" size="48" color="#fff" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import resources from '@/libs/resources.js'
|
||||
import {
|
||||
FlowDelegateList,
|
||||
DeleteDelagate,
|
||||
getDelegateUser
|
||||
} from '@/api/workFlow/entrust.js'
|
||||
import {
|
||||
getFlowLaunchList,
|
||||
delFlowLaunch
|
||||
} from '@/api/workFlow/template'
|
||||
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
|
||||
import flowlist from '../../workFlow/flowTodo/flowList.vue'
|
||||
import SwipeItem from "@/components/SwipeItem/index"
|
||||
export default {
|
||||
components: {
|
||||
flowlist,
|
||||
SwipeItem
|
||||
},
|
||||
mixins: [MescrollMixin],
|
||||
data() {
|
||||
return {
|
||||
keyword: '',
|
||||
list: [],
|
||||
downOption: {
|
||||
use: true,
|
||||
auto: true
|
||||
},
|
||||
upOption: {
|
||||
page: {
|
||||
num: 0,
|
||||
size: 20,
|
||||
time: null
|
||||
},
|
||||
empty: {
|
||||
use: true,
|
||||
icon: resources.message.nodata,
|
||||
tip: this.$t('common.noData'),
|
||||
fixed: true,
|
||||
top: "450rpx",
|
||||
},
|
||||
textNoMore: this.$t('app.apply.noMoreData'),
|
||||
},
|
||||
entrustList: [{
|
||||
fullName: this.$t('app.my.myEntrust')
|
||||
},
|
||||
{
|
||||
fullName: this.$t('app.my.entrustMe')
|
||||
},
|
||||
{
|
||||
fullName: this.$t('app.my.myAgency')
|
||||
},
|
||||
{
|
||||
fullName: this.$t('app.my.agencyMe')
|
||||
}
|
||||
],
|
||||
titleList: ['受委托人', '委托人', '代理人', '被代理人'],
|
||||
current: 0,
|
||||
options: [{
|
||||
text: '删除',
|
||||
value: 'delete',
|
||||
style: {
|
||||
backgroundColor: '#dd524d'
|
||||
}
|
||||
}]
|
||||
}
|
||||
},
|
||||
onLoad(e) {
|
||||
uni.$on('refresh', () => {
|
||||
this.list = [];
|
||||
this.mescroll.resetUpScroll();
|
||||
})
|
||||
if (e.index) this.current = Number(e.index)
|
||||
},
|
||||
onShow() {
|
||||
uni.$on('refreshDetail', () => {
|
||||
this.list = [];
|
||||
this.mescroll.resetUpScroll();
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
actionItemDisabled(item) {
|
||||
if (this.current == 1 || this.current == 3) return true
|
||||
return !(item.status == 0 || item.status == 2)
|
||||
},
|
||||
addPage() {
|
||||
let url = '/entrustAgent/form'
|
||||
const data = {
|
||||
current: this.current,
|
||||
type: this.current == 0 ? 0 : 1
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `/pages/workFlow${url}?data=${encodeURIComponent(JSON.stringify(data))}`
|
||||
})
|
||||
},
|
||||
handleClick(data) {
|
||||
const item = this.list[data.index]
|
||||
DeleteDelagate(item.id).then(res => {
|
||||
this.$u.toast(res.msg)
|
||||
this.mescroll.resetUpScroll()
|
||||
})
|
||||
},
|
||||
upCallback(page) {
|
||||
let query = {
|
||||
currentPage: page.num,
|
||||
pageSize: page.size,
|
||||
keyword: this.keyword,
|
||||
type: this.current + 1
|
||||
}
|
||||
FlowDelegateList(query, {
|
||||
load: page.num == 1
|
||||
}).then(res => {
|
||||
this.mescroll.endSuccess(res.data.list.length);
|
||||
if (page.num == 1) this.list = [];
|
||||
// #ifndef APP-HARMONY
|
||||
const list = res.data.list.map(o => ({
|
||||
'entrustStatus': this.getEntrustStatus(o),
|
||||
'swipeAction': this.actionItemDisabled(o),
|
||||
...o
|
||||
}))
|
||||
// #endif
|
||||
// #ifdef APP-HARMONY
|
||||
const list = res.data.list.map(o =>
|
||||
Object.assign({}, {
|
||||
'entrustStatus': this.getEntrustStatus(o),
|
||||
'swipeAction': this.actionItemDisabled(o)
|
||||
}, o)
|
||||
);
|
||||
// #endif
|
||||
|
||||
this.list = this.list.concat(list);
|
||||
}).catch(() => {
|
||||
this.mescroll.endErr();
|
||||
})
|
||||
},
|
||||
// 状态
|
||||
getEntrustStatus(o) {
|
||||
let status = o.status;
|
||||
let flowStatus;
|
||||
switch (status) {
|
||||
case 0: //未生效
|
||||
flowStatus = resources.status.notEffective
|
||||
break;
|
||||
case 1: //生效中
|
||||
flowStatus = resources.status.effectuate
|
||||
break;
|
||||
default: //已失效
|
||||
flowStatus = resources.status.expired
|
||||
break;
|
||||
}
|
||||
return {
|
||||
flowStatus,
|
||||
status
|
||||
}
|
||||
},
|
||||
search() {
|
||||
// 节流,避免输入过快多次请求
|
||||
this.searchTimer && clearTimeout(this.searchTimer)
|
||||
this.searchTimer = setTimeout(() => {
|
||||
this.list = [];
|
||||
this.mescroll.resetUpScroll();
|
||||
}, 300)
|
||||
},
|
||||
change(index) {
|
||||
this.keyword = ''
|
||||
this.current = index;
|
||||
this.list = [];
|
||||
this.search()
|
||||
},
|
||||
// 详情
|
||||
goDetail(item) {
|
||||
const data = {
|
||||
...item,
|
||||
current: this.current,
|
||||
type: this.current == 0 ? 0 : 1
|
||||
};
|
||||
uni.navigateTo({
|
||||
url: `/pages/workFlow/entrustAgent/detail?data=${encodeURIComponent(JSON.stringify(data))}`
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f0f2f6;
|
||||
}
|
||||
|
||||
.search_sticky {
|
||||
z-index: 990;
|
||||
position: sticky;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.flowLaunch-v {
|
||||
width: 100%;
|
||||
|
||||
.flow-list-box {
|
||||
width: 95%;
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.common-lable {
|
||||
font-size: 24rpx;
|
||||
border-radius: 8rpx;
|
||||
color: #409EFF;
|
||||
border: 1px solid #409EFF;
|
||||
background-color: #e5f3fe;
|
||||
|
||||
}
|
||||
|
||||
.urgent-lable {
|
||||
color: #E6A23C;
|
||||
border: 1px solid #E6A23C;
|
||||
background-color: #fef6e5;
|
||||
}
|
||||
|
||||
.important-lable {
|
||||
color: #F56C6C;
|
||||
border: 1px solid #F56C6C;
|
||||
background-color: #fee5e5;
|
||||
}
|
||||
|
||||
.item-right {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
height: 88rpx;
|
||||
|
||||
.item-right-img {
|
||||
width: 102rpx;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.item-left-top {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: baseline;
|
||||
|
||||
.common-lable {
|
||||
font-size: 24rpx;
|
||||
padding: 2rpx 8rpx;
|
||||
|
||||
border-radius: 8rpx;
|
||||
color: #409EFF;
|
||||
border: 1px solid #409EFF;
|
||||
background-color: #e5f3fe;
|
||||
// margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.urgent-lable {
|
||||
color: #E6A23C;
|
||||
border: 1px solid #E6A23C;
|
||||
background-color: #fef6e5;
|
||||
}
|
||||
|
||||
.important-lable {
|
||||
color: #F56C6C;
|
||||
border: 1px solid #F56C6C;
|
||||
background-color: #fee5e5;
|
||||
}
|
||||
|
||||
.title {
|
||||
width: unset;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
31
pages/workFlow/filePreview/index.vue
Normal file
@@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<view>
|
||||
<web-view :src="fileUrl"></web-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getDownloadUrl
|
||||
} from '@/api/common'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
fileUrl: ''
|
||||
}
|
||||
},
|
||||
onLoad(e) {
|
||||
uni.setNavigationBarTitle({
|
||||
title: e.name
|
||||
})
|
||||
this.getFileUrl(e.fileId)
|
||||
},
|
||||
methods: {
|
||||
getFileUrl(fileId) {
|
||||
getDownloadUrl('workFlow', fileId).then(res => {
|
||||
this.fileUrl = this.define.baseURL + res.data.url;
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
988
pages/workFlow/flowBefore/emoji.js
Normal file
@@ -0,0 +1,988 @@
|
||||
const emojiTree = [
|
||||
[{
|
||||
"url": "100.gif",
|
||||
"alt": "[微笑]"
|
||||
},
|
||||
{
|
||||
"url": "101.gif",
|
||||
"alt": "[伤心]"
|
||||
},
|
||||
{
|
||||
"url": "102.gif",
|
||||
"alt": "[美女]"
|
||||
},
|
||||
{
|
||||
"url": "103.gif",
|
||||
"alt": "[发呆]"
|
||||
},
|
||||
{
|
||||
"url": "104.gif",
|
||||
"alt": "[墨镜]"
|
||||
},
|
||||
{
|
||||
"url": "105.gif",
|
||||
"alt": "[哭]"
|
||||
},
|
||||
{
|
||||
"url": "106.gif",
|
||||
"alt": "[羞]"
|
||||
},
|
||||
{
|
||||
"url": "107.gif",
|
||||
"alt": "[哑]"
|
||||
},
|
||||
{
|
||||
"url": "108.gif",
|
||||
"alt": "[睡]"
|
||||
},
|
||||
{
|
||||
"url": "109.gif",
|
||||
"alt": "[大哭]"
|
||||
},
|
||||
{
|
||||
"url": "110.gif",
|
||||
"alt": "[囧]"
|
||||
},
|
||||
{
|
||||
"url": "111.gif",
|
||||
"alt": "[怒]"
|
||||
},
|
||||
{
|
||||
"url": "112.gif",
|
||||
"alt": "[调皮]"
|
||||
},
|
||||
{
|
||||
"url": "113.gif",
|
||||
"alt": "[呲牙]"
|
||||
},
|
||||
{
|
||||
"url": "114.gif",
|
||||
"alt": "[惊讶]"
|
||||
},
|
||||
{
|
||||
"url": "115.gif",
|
||||
"alt": "[难过]"
|
||||
},
|
||||
{
|
||||
"url": "116.gif",
|
||||
"alt": "[酷]"
|
||||
},
|
||||
{
|
||||
"url": "117.gif",
|
||||
"alt": "[汗]"
|
||||
},
|
||||
{
|
||||
"url": "118.gif",
|
||||
"alt": "[抓狂]"
|
||||
},
|
||||
{
|
||||
"url": "119.gif",
|
||||
"alt": "[吐]"
|
||||
},
|
||||
{
|
||||
"url": "120.gif",
|
||||
"alt": "[笑]"
|
||||
},
|
||||
{
|
||||
"url": "121.gif",
|
||||
"alt": "[快乐]"
|
||||
},
|
||||
{
|
||||
"url": "122.gif",
|
||||
"alt": "[疑惑]"
|
||||
},
|
||||
{
|
||||
"url": "123.gif",
|
||||
"alt": "[傲]"
|
||||
}
|
||||
],
|
||||
[{
|
||||
"url": "124.gif",
|
||||
"alt": "[饿]"
|
||||
},
|
||||
{
|
||||
"url": "125.gif",
|
||||
"alt": "[累]"
|
||||
},
|
||||
{
|
||||
"url": "126.gif",
|
||||
"alt": "[惊恐]"
|
||||
},
|
||||
{
|
||||
"url": "127.gif",
|
||||
"alt": "[汗1]"
|
||||
},
|
||||
{
|
||||
"url": "128.gif",
|
||||
"alt": "[高兴]"
|
||||
},
|
||||
{
|
||||
"url": "129.gif",
|
||||
"alt": "[闲]"
|
||||
},
|
||||
{
|
||||
"url": "130.gif",
|
||||
"alt": "[努力]"
|
||||
},
|
||||
{
|
||||
"url": "131.gif",
|
||||
"alt": "[骂]"
|
||||
},
|
||||
{
|
||||
"url": "132.gif",
|
||||
"alt": "[疑问]"
|
||||
},
|
||||
{
|
||||
"url": "133.gif",
|
||||
"alt": "[秘密]"
|
||||
},
|
||||
{
|
||||
"url": "134.gif",
|
||||
"alt": "[乱]"
|
||||
},
|
||||
{
|
||||
"url": "135.gif",
|
||||
"alt": "[疯]"
|
||||
},
|
||||
{
|
||||
"url": "136.gif",
|
||||
"alt": "[哀]"
|
||||
},
|
||||
{
|
||||
"url": "137.gif",
|
||||
"alt": "[鬼]"
|
||||
},
|
||||
{
|
||||
"url": "138.gif",
|
||||
"alt": "[打击]"
|
||||
},
|
||||
{
|
||||
"url": "139.gif",
|
||||
"alt": "[bye]"
|
||||
},
|
||||
{
|
||||
"url": "140.gif",
|
||||
"alt": "[擦汗]"
|
||||
},
|
||||
{
|
||||
"url": "141.gif",
|
||||
"alt": "[抠]"
|
||||
},
|
||||
{
|
||||
"url": "142.gif",
|
||||
"alt": "[鼓掌]"
|
||||
},
|
||||
{
|
||||
"url": "143.gif",
|
||||
"alt": "[糟糕]"
|
||||
},
|
||||
{
|
||||
"url": "144.gif",
|
||||
"alt": "[恶搞]"
|
||||
},
|
||||
{
|
||||
"url": "145.gif",
|
||||
"alt": "[左哼哼]"
|
||||
},
|
||||
{
|
||||
"url": "146.gif",
|
||||
"alt": "[右哼哼]"
|
||||
},
|
||||
{
|
||||
"url": "147.gif",
|
||||
"alt": "[哈欠]"
|
||||
}
|
||||
],
|
||||
[{
|
||||
"url": "148.gif",
|
||||
"alt": "[看]"
|
||||
},
|
||||
{
|
||||
"url": "149.gif",
|
||||
"alt": "[委屈]"
|
||||
},
|
||||
{
|
||||
"url": "150.gif",
|
||||
"alt": "[难过1]"
|
||||
},
|
||||
{
|
||||
"url": "151.gif",
|
||||
"alt": "[坏]"
|
||||
},
|
||||
{
|
||||
"url": "152.gif",
|
||||
"alt": "[亲]"
|
||||
},
|
||||
{
|
||||
"url": "153.gif",
|
||||
"alt": "[吓]"
|
||||
},
|
||||
{
|
||||
"url": "154.gif",
|
||||
"alt": "[可怜]"
|
||||
},
|
||||
{
|
||||
"url": "155.gif",
|
||||
"alt": "[刀]"
|
||||
},
|
||||
{
|
||||
"url": "156.gif",
|
||||
"alt": "[水果]"
|
||||
},
|
||||
{
|
||||
"url": "157.gif",
|
||||
"alt": "[酒]"
|
||||
},
|
||||
{
|
||||
"url": "158.gif",
|
||||
"alt": "[篮球]"
|
||||
},
|
||||
{
|
||||
"url": "159.gif",
|
||||
"alt": "[乒乓]"
|
||||
},
|
||||
{
|
||||
"url": "160.gif",
|
||||
"alt": "[咖啡]"
|
||||
},
|
||||
{
|
||||
"url": "161.gif",
|
||||
"alt": "[美食]"
|
||||
},
|
||||
{
|
||||
"url": "162.gif",
|
||||
"alt": "[动物]"
|
||||
},
|
||||
{
|
||||
"url": "163.gif",
|
||||
"alt": "[鲜花]"
|
||||
},
|
||||
{
|
||||
"url": "164.gif",
|
||||
"alt": "[枯]"
|
||||
},
|
||||
{
|
||||
"url": "165.gif",
|
||||
"alt": "[唇]"
|
||||
},
|
||||
{
|
||||
"url": "166.gif",
|
||||
"alt": "[爱]"
|
||||
},
|
||||
{
|
||||
"url": "167.gif",
|
||||
"alt": "[分手]"
|
||||
},
|
||||
{
|
||||
"url": "168.gif",
|
||||
"alt": "[生日]"
|
||||
},
|
||||
{
|
||||
"url": "169.gif",
|
||||
"alt": "[电]"
|
||||
},
|
||||
{
|
||||
"url": "170.gif",
|
||||
"alt": "[炸弹]"
|
||||
},
|
||||
{
|
||||
"url": "171.gif",
|
||||
"alt": "[刀子]"
|
||||
}
|
||||
],
|
||||
[{
|
||||
"url": "172.gif",
|
||||
"alt": "[足球]"
|
||||
},
|
||||
{
|
||||
"url": "173.gif",
|
||||
"alt": "[瓢虫]"
|
||||
},
|
||||
{
|
||||
"url": "174.gif",
|
||||
"alt": "[翔]"
|
||||
},
|
||||
{
|
||||
"url": "175.gif",
|
||||
"alt": "[月亮]"
|
||||
},
|
||||
{
|
||||
"url": "176.gif",
|
||||
"alt": "[太阳]"
|
||||
},
|
||||
{
|
||||
"url": "177.gif",
|
||||
"alt": "[礼物]"
|
||||
},
|
||||
{
|
||||
"url": "178.gif",
|
||||
"alt": "[抱抱]"
|
||||
},
|
||||
{
|
||||
"url": "179.gif",
|
||||
"alt": "[拇指]"
|
||||
},
|
||||
{
|
||||
"url": "180.gif",
|
||||
"alt": "[贬低]"
|
||||
},
|
||||
{
|
||||
"url": "181.gif",
|
||||
"alt": "[握手]"
|
||||
},
|
||||
{
|
||||
"url": "182.gif",
|
||||
"alt": "[剪刀手]"
|
||||
},
|
||||
{
|
||||
"url": "183.gif",
|
||||
"alt": "[抱拳]"
|
||||
},
|
||||
{
|
||||
"url": "184.gif",
|
||||
"alt": "[勾引]"
|
||||
},
|
||||
{
|
||||
"url": "185.gif",
|
||||
"alt": "[拳头]"
|
||||
},
|
||||
{
|
||||
"url": "186.gif",
|
||||
"alt": "[小拇指]"
|
||||
},
|
||||
{
|
||||
"url": "187.gif",
|
||||
"alt": "[拇指八]"
|
||||
},
|
||||
{
|
||||
"url": "188.gif",
|
||||
"alt": "[食指]"
|
||||
},
|
||||
{
|
||||
"url": "189.gif",
|
||||
"alt": "[ok]"
|
||||
},
|
||||
{
|
||||
"url": "190.gif",
|
||||
"alt": "[情侣]"
|
||||
},
|
||||
{
|
||||
"url": "191.gif",
|
||||
"alt": "[爱心]"
|
||||
},
|
||||
{
|
||||
"url": "192.gif",
|
||||
"alt": "[蹦哒]"
|
||||
},
|
||||
{
|
||||
"url": "193.gif",
|
||||
"alt": "[颤抖]"
|
||||
},
|
||||
{
|
||||
"url": "194.gif",
|
||||
"alt": "[怄气]"
|
||||
},
|
||||
{
|
||||
"url": "195.gif",
|
||||
"alt": "[跳舞]"
|
||||
}
|
||||
],
|
||||
[{
|
||||
"url": "196.gif",
|
||||
"alt": "[拜]"
|
||||
},
|
||||
{
|
||||
"url": "197.gif",
|
||||
"alt": "[背着]"
|
||||
},
|
||||
{
|
||||
"url": "198.gif",
|
||||
"alt": "[伸手]"
|
||||
},
|
||||
{
|
||||
"url": "199.gif",
|
||||
"alt": "[耍帅]"
|
||||
},
|
||||
{
|
||||
"url": "200.png",
|
||||
"alt": "[微笑1]"
|
||||
},
|
||||
{
|
||||
"url": "201.png",
|
||||
"alt": "[生病]"
|
||||
},
|
||||
{
|
||||
"url": "202.png",
|
||||
"alt": "[哭泣]"
|
||||
},
|
||||
{
|
||||
"url": "203.png",
|
||||
"alt": "[吐舌]"
|
||||
},
|
||||
{
|
||||
"url": "204.png",
|
||||
"alt": "[迷糊]"
|
||||
},
|
||||
{
|
||||
"url": "205.png",
|
||||
"alt": "[瞪眼]"
|
||||
},
|
||||
{
|
||||
"url": "206.png",
|
||||
"alt": "[恐怖]"
|
||||
},
|
||||
{
|
||||
"url": "207.png",
|
||||
"alt": "[忧愁]"
|
||||
},
|
||||
{
|
||||
"url": "208.png",
|
||||
"alt": "[眨眉]"
|
||||
},
|
||||
{
|
||||
"url": "209.png",
|
||||
"alt": "[闭眼]"
|
||||
},
|
||||
{
|
||||
"url": "210.png",
|
||||
"alt": "[鄙视]"
|
||||
},
|
||||
{
|
||||
"url": "211.png",
|
||||
"alt": "[阴暗]"
|
||||
},
|
||||
{
|
||||
"url": "212.png",
|
||||
"alt": "[小鬼]"
|
||||
},
|
||||
{
|
||||
"url": "213.png",
|
||||
"alt": "[爱心1]"
|
||||
},
|
||||
{
|
||||
"url": "214.png",
|
||||
"alt": "[拜佛]"
|
||||
},
|
||||
{
|
||||
"url": "215.png",
|
||||
"alt": "[力量]"
|
||||
},
|
||||
{
|
||||
"url": "216.png",
|
||||
"alt": "[金钱]"
|
||||
},
|
||||
{
|
||||
"url": "217.png",
|
||||
"alt": "[蛋糕]"
|
||||
},
|
||||
{
|
||||
"url": "218.png",
|
||||
"alt": "[彩带]"
|
||||
},
|
||||
{
|
||||
"url": "219.png",
|
||||
"alt": "[礼物1]"
|
||||
}
|
||||
]
|
||||
]
|
||||
const emojiList = [{
|
||||
"url": "100.gif",
|
||||
"alt": "[微笑]"
|
||||
},
|
||||
{
|
||||
"url": "101.gif",
|
||||
"alt": "[伤心]"
|
||||
},
|
||||
{
|
||||
"url": "102.gif",
|
||||
"alt": "[美女]"
|
||||
},
|
||||
{
|
||||
"url": "103.gif",
|
||||
"alt": "[发呆]"
|
||||
},
|
||||
{
|
||||
"url": "104.gif",
|
||||
"alt": "[墨镜]"
|
||||
},
|
||||
{
|
||||
"url": "105.gif",
|
||||
"alt": "[哭]"
|
||||
},
|
||||
{
|
||||
"url": "106.gif",
|
||||
"alt": "[羞]"
|
||||
},
|
||||
{
|
||||
"url": "107.gif",
|
||||
"alt": "[哑]"
|
||||
},
|
||||
{
|
||||
"url": "108.gif",
|
||||
"alt": "[睡]"
|
||||
},
|
||||
{
|
||||
"url": "109.gif",
|
||||
"alt": "[大哭]"
|
||||
},
|
||||
{
|
||||
"url": "110.gif",
|
||||
"alt": "[囧]"
|
||||
},
|
||||
{
|
||||
"url": "111.gif",
|
||||
"alt": "[怒]"
|
||||
},
|
||||
{
|
||||
"url": "112.gif",
|
||||
"alt": "[调皮]"
|
||||
},
|
||||
{
|
||||
"url": "113.gif",
|
||||
"alt": "[呲牙]"
|
||||
},
|
||||
{
|
||||
"url": "114.gif",
|
||||
"alt": "[惊讶]"
|
||||
},
|
||||
{
|
||||
"url": "115.gif",
|
||||
"alt": "[难过]"
|
||||
},
|
||||
{
|
||||
"url": "116.gif",
|
||||
"alt": "[酷]"
|
||||
},
|
||||
{
|
||||
"url": "117.gif",
|
||||
"alt": "[汗]"
|
||||
},
|
||||
{
|
||||
"url": "118.gif",
|
||||
"alt": "[抓狂]"
|
||||
},
|
||||
{
|
||||
"url": "119.gif",
|
||||
"alt": "[吐]"
|
||||
},
|
||||
{
|
||||
"url": "120.gif",
|
||||
"alt": "[笑]"
|
||||
},
|
||||
{
|
||||
"url": "121.gif",
|
||||
"alt": "[快乐]"
|
||||
},
|
||||
{
|
||||
"url": "122.gif",
|
||||
"alt": "[疑惑]"
|
||||
},
|
||||
{
|
||||
"url": "123.gif",
|
||||
"alt": "[傲]"
|
||||
},
|
||||
{
|
||||
"url": "124.gif",
|
||||
"alt": "[饿]"
|
||||
},
|
||||
{
|
||||
"url": "125.gif",
|
||||
"alt": "[累]"
|
||||
},
|
||||
{
|
||||
"url": "126.gif",
|
||||
"alt": "[惊恐]"
|
||||
},
|
||||
{
|
||||
"url": "127.gif",
|
||||
"alt": "[汗1]"
|
||||
},
|
||||
{
|
||||
"url": "128.gif",
|
||||
"alt": "[高兴]"
|
||||
},
|
||||
{
|
||||
"url": "129.gif",
|
||||
"alt": "[闲]"
|
||||
},
|
||||
{
|
||||
"url": "130.gif",
|
||||
"alt": "[努力]"
|
||||
},
|
||||
{
|
||||
"url": "131.gif",
|
||||
"alt": "[骂]"
|
||||
},
|
||||
{
|
||||
"url": "132.gif",
|
||||
"alt": "[疑问]"
|
||||
},
|
||||
{
|
||||
"url": "133.gif",
|
||||
"alt": "[秘密]"
|
||||
},
|
||||
{
|
||||
"url": "134.gif",
|
||||
"alt": "[乱]"
|
||||
},
|
||||
{
|
||||
"url": "135.gif",
|
||||
"alt": "[疯]"
|
||||
},
|
||||
{
|
||||
"url": "136.gif",
|
||||
"alt": "[哀]"
|
||||
},
|
||||
{
|
||||
"url": "137.gif",
|
||||
"alt": "[鬼]"
|
||||
},
|
||||
{
|
||||
"url": "138.gif",
|
||||
"alt": "[打击]"
|
||||
},
|
||||
{
|
||||
"url": "139.gif",
|
||||
"alt": "[bye]"
|
||||
},
|
||||
{
|
||||
"url": "140.gif",
|
||||
"alt": "[擦汗]"
|
||||
},
|
||||
{
|
||||
"url": "141.gif",
|
||||
"alt": "[抠]"
|
||||
},
|
||||
{
|
||||
"url": "142.gif",
|
||||
"alt": "[鼓掌]"
|
||||
},
|
||||
{
|
||||
"url": "143.gif",
|
||||
"alt": "[糟糕]"
|
||||
},
|
||||
{
|
||||
"url": "144.gif",
|
||||
"alt": "[恶搞]"
|
||||
},
|
||||
{
|
||||
"url": "145.gif",
|
||||
"alt": "[左哼哼]"
|
||||
},
|
||||
{
|
||||
"url": "146.gif",
|
||||
"alt": "[右哼哼]"
|
||||
},
|
||||
{
|
||||
"url": "147.gif",
|
||||
"alt": "[哈欠]"
|
||||
},
|
||||
{
|
||||
"url": "148.gif",
|
||||
"alt": "[看]"
|
||||
},
|
||||
{
|
||||
"url": "149.gif",
|
||||
"alt": "[委屈]"
|
||||
},
|
||||
{
|
||||
"url": "150.gif",
|
||||
"alt": "[难过1]"
|
||||
},
|
||||
{
|
||||
"url": "151.gif",
|
||||
"alt": "[坏]"
|
||||
},
|
||||
{
|
||||
"url": "152.gif",
|
||||
"alt": "[亲]"
|
||||
},
|
||||
{
|
||||
"url": "153.gif",
|
||||
"alt": "[吓]"
|
||||
},
|
||||
{
|
||||
"url": "154.gif",
|
||||
"alt": "[可怜]"
|
||||
},
|
||||
{
|
||||
"url": "155.gif",
|
||||
"alt": "[刀]"
|
||||
},
|
||||
{
|
||||
"url": "156.gif",
|
||||
"alt": "[水果]"
|
||||
},
|
||||
{
|
||||
"url": "157.gif",
|
||||
"alt": "[酒]"
|
||||
},
|
||||
{
|
||||
"url": "158.gif",
|
||||
"alt": "[篮球]"
|
||||
},
|
||||
{
|
||||
"url": "159.gif",
|
||||
"alt": "[乒乓]"
|
||||
},
|
||||
{
|
||||
"url": "160.gif",
|
||||
"alt": "[咖啡]"
|
||||
},
|
||||
{
|
||||
"url": "161.gif",
|
||||
"alt": "[美食]"
|
||||
},
|
||||
{
|
||||
"url": "162.gif",
|
||||
"alt": "[动物]"
|
||||
},
|
||||
{
|
||||
"url": "163.gif",
|
||||
"alt": "[鲜花]"
|
||||
},
|
||||
{
|
||||
"url": "164.gif",
|
||||
"alt": "[枯]"
|
||||
},
|
||||
{
|
||||
"url": "165.gif",
|
||||
"alt": "[唇]"
|
||||
},
|
||||
{
|
||||
"url": "166.gif",
|
||||
"alt": "[爱]"
|
||||
},
|
||||
{
|
||||
"url": "167.gif",
|
||||
"alt": "[分手]"
|
||||
},
|
||||
{
|
||||
"url": "168.gif",
|
||||
"alt": "[生日]"
|
||||
},
|
||||
{
|
||||
"url": "169.gif",
|
||||
"alt": "[电]"
|
||||
},
|
||||
{
|
||||
"url": "170.gif",
|
||||
"alt": "[炸弹]"
|
||||
},
|
||||
{
|
||||
"url": "171.gif",
|
||||
"alt": "[刀子]"
|
||||
},
|
||||
{
|
||||
"url": "172.gif",
|
||||
"alt": "[足球]"
|
||||
},
|
||||
{
|
||||
"url": "173.gif",
|
||||
"alt": "[瓢虫]"
|
||||
},
|
||||
{
|
||||
"url": "174.gif",
|
||||
"alt": "[翔]"
|
||||
},
|
||||
{
|
||||
"url": "175.gif",
|
||||
"alt": "[月亮]"
|
||||
},
|
||||
{
|
||||
"url": "176.gif",
|
||||
"alt": "[太阳]"
|
||||
},
|
||||
{
|
||||
"url": "177.gif",
|
||||
"alt": "[礼物]"
|
||||
},
|
||||
{
|
||||
"url": "178.gif",
|
||||
"alt": "[抱抱]"
|
||||
},
|
||||
{
|
||||
"url": "179.gif",
|
||||
"alt": "[拇指]"
|
||||
},
|
||||
{
|
||||
"url": "180.gif",
|
||||
"alt": "[贬低]"
|
||||
},
|
||||
{
|
||||
"url": "181.gif",
|
||||
"alt": "[握手]"
|
||||
},
|
||||
{
|
||||
"url": "182.gif",
|
||||
"alt": "[剪刀手]"
|
||||
},
|
||||
{
|
||||
"url": "183.gif",
|
||||
"alt": "[抱拳]"
|
||||
},
|
||||
{
|
||||
"url": "184.gif",
|
||||
"alt": "[勾引]"
|
||||
},
|
||||
{
|
||||
"url": "185.gif",
|
||||
"alt": "[拳头]"
|
||||
},
|
||||
{
|
||||
"url": "186.gif",
|
||||
"alt": "[小拇指]"
|
||||
},
|
||||
{
|
||||
"url": "187.gif",
|
||||
"alt": "[拇指八]"
|
||||
},
|
||||
{
|
||||
"url": "188.gif",
|
||||
"alt": "[食指]"
|
||||
},
|
||||
{
|
||||
"url": "189.gif",
|
||||
"alt": "[ok]"
|
||||
},
|
||||
{
|
||||
"url": "190.gif",
|
||||
"alt": "[情侣]"
|
||||
},
|
||||
{
|
||||
"url": "191.gif",
|
||||
"alt": "[爱心]"
|
||||
},
|
||||
{
|
||||
"url": "192.gif",
|
||||
"alt": "[蹦哒]"
|
||||
},
|
||||
{
|
||||
"url": "193.gif",
|
||||
"alt": "[颤抖]"
|
||||
},
|
||||
{
|
||||
"url": "194.gif",
|
||||
"alt": "[怄气]"
|
||||
},
|
||||
{
|
||||
"url": "195.gif",
|
||||
"alt": "[跳舞]"
|
||||
},
|
||||
{
|
||||
"url": "196.gif",
|
||||
"alt": "[拜]"
|
||||
},
|
||||
{
|
||||
"url": "197.gif",
|
||||
"alt": "[背着]"
|
||||
},
|
||||
{
|
||||
"url": "198.gif",
|
||||
"alt": "[伸手]"
|
||||
},
|
||||
{
|
||||
"url": "199.gif",
|
||||
"alt": "[耍帅]"
|
||||
},
|
||||
{
|
||||
"url": "200.png",
|
||||
"alt": "[微笑1]"
|
||||
},
|
||||
{
|
||||
"url": "201.png",
|
||||
"alt": "[生病]"
|
||||
},
|
||||
{
|
||||
"url": "202.png",
|
||||
"alt": "[哭泣]"
|
||||
},
|
||||
{
|
||||
"url": "203.png",
|
||||
"alt": "[吐舌]"
|
||||
},
|
||||
{
|
||||
"url": "204.png",
|
||||
"alt": "[迷糊]"
|
||||
},
|
||||
{
|
||||
"url": "205.png",
|
||||
"alt": "[瞪眼]"
|
||||
},
|
||||
{
|
||||
"url": "206.png",
|
||||
"alt": "[恐怖]"
|
||||
},
|
||||
{
|
||||
"url": "207.png",
|
||||
"alt": "[忧愁]"
|
||||
},
|
||||
{
|
||||
"url": "208.png",
|
||||
"alt": "[眨眉]"
|
||||
},
|
||||
{
|
||||
"url": "209.png",
|
||||
"alt": "[闭眼]"
|
||||
},
|
||||
{
|
||||
"url": "210.png",
|
||||
"alt": "[鄙视]"
|
||||
},
|
||||
{
|
||||
"url": "211.png",
|
||||
"alt": "[阴暗]"
|
||||
},
|
||||
{
|
||||
"url": "212.png",
|
||||
"alt": "[小鬼]"
|
||||
},
|
||||
{
|
||||
"url": "213.png",
|
||||
"alt": "[爱心1]"
|
||||
},
|
||||
{
|
||||
"url": "214.png",
|
||||
"alt": "[拜佛]"
|
||||
},
|
||||
{
|
||||
"url": "215.png",
|
||||
"alt": "[力量]"
|
||||
},
|
||||
{
|
||||
"url": "216.png",
|
||||
"alt": "[金钱]"
|
||||
},
|
||||
{
|
||||
"url": "217.png",
|
||||
"alt": "[蛋糕]"
|
||||
},
|
||||
{
|
||||
"url": "218.png",
|
||||
"alt": "[彩带]"
|
||||
},
|
||||
{
|
||||
"url": "219.png",
|
||||
"alt": "[礼物1]"
|
||||
}
|
||||
]
|
||||
|
||||
const req = import.meta.glob('../static/emoji/*.*', {
|
||||
eager: true
|
||||
})
|
||||
|
||||
const imagesMap = {}
|
||||
|
||||
// 循环所有图片,将图片名设置成键,值为导入该图片的地址
|
||||
for (const key in req) {
|
||||
// let name = key.split('/').slice(-1)[0].split('.')[0]
|
||||
let name = key.split('/').slice(-1)[0].replace('.', '')
|
||||
// 抛出图片大对象后,文件页面直接引入后将图片的具体名称作为属性就能导入该图片
|
||||
imagesMap[name] = req[key].default
|
||||
}
|
||||
|
||||
export {
|
||||
emojiList,
|
||||
emojiTree,
|
||||
imagesMap
|
||||
}
|
||||
525
pages/workFlow/flowBefore/flowForm.vue
Normal file
@@ -0,0 +1,525 @@
|
||||
<template>
|
||||
<view class="flowBefore-v">
|
||||
<div class="flow-urgent-value" :style="{'background-color':flowUrgentList[selectflowUrgent.extra].bgColor}"
|
||||
@click="handleShowSelect">
|
||||
<span :style="{'color':flowUrgentList[selectflowUrgent.extra].color}">{{selectflowUrgent.label}}</span>
|
||||
</div>
|
||||
<view class="flowBefore-box">
|
||||
<view class="scroll-v" scroll-y>
|
||||
<childForm ref="child" :config="config" @eventReceiver="eventReceiver" v-if="!loading"
|
||||
@setBtnLoad="setBtnLoad" :key="childFormKey" />
|
||||
<ErrorForm @submitErrorForm="submitErrorForm" ref="ErrorForm" />
|
||||
<RecordTimeList :progressList="progressList" :taskInfo="taskInfo" v-if="getShowExtraPanel"
|
||||
:commentList="commentList" :taskId="config.opType==0 ? config.id:config.taskId" ref="RecordTimeList"
|
||||
:hasComment="hasComment">
|
||||
</RecordTimeList>
|
||||
</view>
|
||||
</view>
|
||||
<u-select :list="flowUrgentList" v-model="showFlowUrgent" @confirm="seltConfirm"
|
||||
:default-value="defaultValue" />
|
||||
<uni-popup mode="bottom" ref="reduceApprover" background-color='#fff'>
|
||||
<view class="approverContent">
|
||||
<view class="notice-warp">
|
||||
<view class="u-flex close-icon">
|
||||
<u-icon name="close" size="32" @click="hideReduceApprover" color="#93969c"></u-icon>
|
||||
</view>
|
||||
<view class="search-box">
|
||||
<u-search :placeholder="$t('app.apply.pleaseKeyword')" v-model="keyword" height="72"
|
||||
:show-action="false" @change="getAddSignUserList" bg-color="#f0f2f6" shape="square" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="popup">
|
||||
<view v-for="(item, index) in signUserIdList" :key="index" v-if="signUserIdList.length"
|
||||
class="list-box">
|
||||
<view class="u-flex item">
|
||||
<view class="u-flex" style="flex: 1;">
|
||||
<u-avatar :src="define.baseURL+item.headIcon"></u-avatar>
|
||||
<view class="u-m-l-10">
|
||||
<view>{{item.fullName}}</view>
|
||||
<view>{{item.organize}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" @click="deleteReduce(item.id)">
|
||||
<u-icon name="trash" size="32" color="#93969c"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<JnpfEmpty v-else />
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
Create,
|
||||
Update
|
||||
} from '@/api/workFlow/workFlowForm'
|
||||
import {
|
||||
FlowTask,
|
||||
Audit,
|
||||
Reject,
|
||||
Transfer,
|
||||
saveAudit,
|
||||
saveAssist,
|
||||
AddSignUserIdList,
|
||||
ReduceApprover,
|
||||
Candidates,
|
||||
RejectList,
|
||||
FreeApprover,
|
||||
launchRecall,
|
||||
auditRecall,
|
||||
cancel,
|
||||
SignFor,
|
||||
Transact,
|
||||
sendBack,
|
||||
back,
|
||||
Assist
|
||||
} from '@/api/workFlow/flowBefore'
|
||||
import {
|
||||
Revoke,
|
||||
Press
|
||||
} from '@/api/workFlow/flowLaunch'
|
||||
import {
|
||||
createModel,
|
||||
updateModel
|
||||
} from '@/api/apply/visualDev'
|
||||
import {
|
||||
createComment
|
||||
} from '@/api/workFlow/flowEngine'
|
||||
import {
|
||||
checkInfo
|
||||
} from '@/api/message.js'
|
||||
import resources from '@/libs/resources.js'
|
||||
import childForm from './form.vue'
|
||||
import RecordTimeList from '../components/RecordTimeList'
|
||||
import ErrorForm from '../components/ErrorForm'
|
||||
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
|
||||
import {
|
||||
useUserStore
|
||||
} from '@/store/modules/user'
|
||||
export default {
|
||||
mixins: [MescrollMixin],
|
||||
components: {
|
||||
childForm,
|
||||
ErrorForm,
|
||||
RecordTimeList
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
childFormKey: +new Date(),
|
||||
signUserIdList: [],
|
||||
keyword: '',
|
||||
formLoding: false,
|
||||
loading: false,
|
||||
taskInfo: {},
|
||||
btnInfo: [],
|
||||
nodeList: [],
|
||||
show: false,
|
||||
config: {},
|
||||
formData: {},
|
||||
recordList: [],
|
||||
properties: {},
|
||||
flowStatus: '',
|
||||
commentList: [],
|
||||
processId: "",
|
||||
title: '',
|
||||
selectflowUrgent: {
|
||||
extra: '0',
|
||||
label: '普通',
|
||||
value: 1,
|
||||
},
|
||||
showFlowUrgent: false,
|
||||
defaultValue: [0],
|
||||
flowUrgent: 1,
|
||||
flowUrgentList: [{
|
||||
label: '普通',
|
||||
color: '#409EFF',
|
||||
bgColor: '#e5f3fe',
|
||||
value: 1,
|
||||
extra: '0'
|
||||
},
|
||||
{
|
||||
label: '重要',
|
||||
color: '#E6A23C',
|
||||
bgColor: '#fef6e5',
|
||||
value: 2,
|
||||
extra: '1'
|
||||
},
|
||||
{
|
||||
label: '紧急',
|
||||
color: '#F56C6C',
|
||||
bgColor: '#fee5e5',
|
||||
value: 3,
|
||||
extra: '2'
|
||||
},
|
||||
],
|
||||
hasComment: false,
|
||||
progressList: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
},
|
||||
getShowExtraPanel() {
|
||||
return this.config.opType != '-1' && !this.loading
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init(data) {
|
||||
this.config = data
|
||||
this.config.origin = 'scan'
|
||||
this.processId = this.config.id
|
||||
/**
|
||||
* opType
|
||||
* -1 - 我发起的新建/编辑
|
||||
* 0 - 我发起的详情
|
||||
* 1 - 待办事宜
|
||||
* 2 - 已办事宜
|
||||
* 3 - 抄送事宜
|
||||
*/
|
||||
this.getBeforeInfo(this.config)
|
||||
},
|
||||
handlePreviewImage(url) {
|
||||
// #ifdef H5
|
||||
uni.previewImage({
|
||||
urls: [url],
|
||||
current: url,
|
||||
success: () => {},
|
||||
fail: () => {
|
||||
uni.showToast({
|
||||
title: '预览图片失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
getBeforeInfo() {
|
||||
let config = this.config;
|
||||
this.formData.flowId = config.flowId;
|
||||
this.loading = true;
|
||||
const query = {
|
||||
flowId: config.flowId, // 流程大Id
|
||||
opType: config.opType == 2 ? 3 : config.opType, //特殊:待办点击开始办理需要跳到在办页面
|
||||
};
|
||||
if (config.opType != "-1" && config.opType != '0') query.operatorId = config.operatorId;
|
||||
FlowTask(config?.taskId || config?.id || 0, query).then((res) => {
|
||||
this.flowInfo = res.data.flowInfo || {};
|
||||
this.formInfo = res.data.formInfo || {};
|
||||
this.taskInfo = res.data.taskInfo || {};
|
||||
this.btnInfo = res.data.btnInfo || [];
|
||||
this.progressList = res.data.progressList || [];
|
||||
config.formOperates = res.data.formOperates || [];
|
||||
config.formType = this.formInfo.type
|
||||
const fullName =
|
||||
config.opType == "-1" ?
|
||||
this.flowInfo.fullName :
|
||||
this.taskInfo.fullName;
|
||||
config.fullName = fullName;
|
||||
this.title = this.flowInfo.fullName;
|
||||
this.thisStep = this.taskInfo.thisStep || "";
|
||||
if (config.status !== 0 && config.status !== 3) {
|
||||
this.title = this.thisStep ?
|
||||
config.fullName + "/" + this.thisStep :
|
||||
config.fullName;
|
||||
}
|
||||
config.type = this.flowInfo.type;
|
||||
config.draftData = res.data.draftData || null;
|
||||
config.formData = res.data.formData || {};
|
||||
config.formEnCode = this.formInfo.enCode;
|
||||
this.nodeList = res.data.nodeList || [];
|
||||
this.properties = res.data.nodeProperties || {};
|
||||
this.recordList = (res.data.recordList || []).reverse();
|
||||
config.formConf = this.formInfo.formData;
|
||||
this.hasComment = this.flowInfo.flowNodes.global.hasComment;
|
||||
this.loading = false;
|
||||
this.formLoding = true;
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.flowInfo.fullName,
|
||||
});
|
||||
if (config.formRecords && config.title) {
|
||||
uni.setNavigationBarTitle({
|
||||
title: config.title,
|
||||
});
|
||||
}
|
||||
this.flowUrgent = this.taskInfo.flowUrgent || 1;
|
||||
const getSelectInfo = () => {
|
||||
var obj = {
|
||||
value: this.flowUrgent,
|
||||
extra: "0",
|
||||
label: "普通",
|
||||
};
|
||||
this.flowUrgentList.forEach((e, i) => {
|
||||
if (e.value == this.flowUrgent) {
|
||||
obj.extra = i;
|
||||
obj.label = e.label;
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
};
|
||||
this.selectflowUrgent = getSelectInfo();
|
||||
|
||||
if (config.opType != "-1" && config.opType != "3") config.readonly =
|
||||
true;
|
||||
config.formOperates = [];
|
||||
if (config.opType == 0) {
|
||||
if (this.properties && this.properties && this.properties.formOperates) config
|
||||
.formOperates = this.properties.formOperates || [];
|
||||
} else {
|
||||
config.formOperates = res.data.formOperates || [];
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.$nextTick(() => {
|
||||
if (!this.$refs.child || !this.$refs.child.$refs.form) {
|
||||
uni.showToast({
|
||||
title: "暂无此流程表单",
|
||||
icon: "none",
|
||||
complete: () => {
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 1500);
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.$refs.child.$refs.form.init(config)
|
||||
});
|
||||
}, 100);
|
||||
this.config = config;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f0f2f6;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.flow-urgent-value {
|
||||
position: fixed;
|
||||
top: var(--window-top);
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 60rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.flowBefore-v {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 60rpx;
|
||||
|
||||
|
||||
|
||||
.workFlowTitle {
|
||||
width: 100%;
|
||||
padding: 0 32rpx 32rpx 32rpx;
|
||||
background-color: #FFFFFF;
|
||||
font-size: 32rpx;
|
||||
font-weight: 700;
|
||||
white-space: pre-wrap;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.flowBefore-box {
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
padding-bottom: 3.3rem;
|
||||
|
||||
.sticky-box {
|
||||
z-index: 500;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.swiper-box {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.scroll-v {
|
||||
flex: 1;
|
||||
/* #ifndef MP-ALIPAY */
|
||||
flex-direction: column;
|
||||
/* #endif */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.flowStatus {
|
||||
position: absolute;
|
||||
top: 90rpx;
|
||||
right: 0;
|
||||
border: 0;
|
||||
margin: 20rpx;
|
||||
opacity: 0.7;
|
||||
z-index: 999;
|
||||
|
||||
image {
|
||||
width: 200rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.discuss_btn {
|
||||
background-color: #fff;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
// height: 88rpx;
|
||||
// box-shadow: 0 -2rpx 8rpx #e1e5ec;
|
||||
z-index: 20;
|
||||
|
||||
.custom-style {
|
||||
background-color: #2979ff;
|
||||
color: #FFFFFF;
|
||||
width: 100%;
|
||||
border-radius: 0 !important;
|
||||
|
||||
&::after {
|
||||
border: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 24rpx;
|
||||
text-align: center;
|
||||
|
||||
.confrim-btn {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.send {
|
||||
flex: 1;
|
||||
background-color: #2979ff;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.cancel {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.approverContent {
|
||||
height: 1000rpx;
|
||||
overflow-y: scroll;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.notice-warp {
|
||||
top: 0;
|
||||
height: 5.6rem;
|
||||
|
||||
.close-icon {
|
||||
height: 60rpx;
|
||||
padding: 10rpx 20rpx;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.popup {
|
||||
margin-top: 5.65rem;
|
||||
|
||||
.list-box {
|
||||
.item {
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nodeList-v {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.record-v {
|
||||
padding: 32rpx 32rpx 10rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
|
||||
.discuss_box {
|
||||
.discuss_list {
|
||||
|
||||
.time_button {
|
||||
padding-left: 110rpx;
|
||||
margin-top: 20rpx;
|
||||
padding-right: 10rpx;
|
||||
}
|
||||
|
||||
.discuss_txt {
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
|
||||
.discuss_txt_left {
|
||||
.uName {
|
||||
margin-left: 8px;
|
||||
font-size: 14px;
|
||||
font-family: PingFang SC;
|
||||
line-height: 17rpx;
|
||||
|
||||
.replyText {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.del {
|
||||
color: red;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.reply {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.discuss_content {
|
||||
font-size: 12px;
|
||||
padding-left: 70rpx;
|
||||
|
||||
.img_box {
|
||||
margin: 40rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.comment-creator-time {
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
font-family: PingFang SC;
|
||||
line-height: 17rpx;
|
||||
}
|
||||
|
||||
.comment-content-color {
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.comment-header-color {
|
||||
color: #303133;
|
||||
}
|
||||
</style>
|
||||
48
pages/workFlow/flowBefore/form.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<view>
|
||||
<template v-if="config.formType == 1">
|
||||
<dynamicForm ref="form" @eventReceiver="eventReceiver" @setBtnLoad="setBtnLoad" :config="config" />
|
||||
</template>
|
||||
<template v-if="config.formType == 2">
|
||||
<crmOrder ref="form" @eventReceiver="eventReceiver" v-if="config.formEnCode==='crmOrder'"
|
||||
:config="config" />
|
||||
<leaveApply ref="form" @eventReceiver="eventReceiver" v-if="config.formEnCode==='leaveApply'"
|
||||
:config="config" />
|
||||
<salesOrder ref="form" @eventReceiver="eventReceiver" v-if="config.formEnCode==='salesOrder'"
|
||||
:config="config" />
|
||||
<revokeApply ref="form" @eventReceiver="eventReceiver" v-if="config.formEnCode==='revoke'"
|
||||
:config="config" />
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import dynamicForm from '@/pages/workFlow/workFlowForm/dynamicForm'
|
||||
import salesOrder from '@/pages/workFlow/workFlowForm/salesOrder'
|
||||
import leaveApply from '@/pages/workFlow/workFlowForm/leaveApply'
|
||||
import crmOrder from '@/pages/workFlow/workFlowForm/crmOrder'
|
||||
import revokeApply from '@/pages/workFlow/workFlowForm/revokeApply'
|
||||
export default {
|
||||
components: {
|
||||
crmOrder,
|
||||
dynamicForm,
|
||||
leaveApply,
|
||||
salesOrder,
|
||||
revokeApply
|
||||
},
|
||||
props: {
|
||||
config: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
eventReceiver(formData, eventType) {
|
||||
this.$emit('eventReceiver', formData, eventType)
|
||||
},
|
||||
setBtnLoad(val) {
|
||||
this.$emit('setBtnLoad', val)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
1538
pages/workFlow/flowBefore/index.vue
Normal file
58
pages/workFlow/flowBefore/logError.vue
Normal file
@@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<view class="logError-v u-flex-col">
|
||||
<view class="error-prompt">
|
||||
<view class="error-prompt-title u-p-l-20 u-p-r-20">
|
||||
错误提示:
|
||||
</view>
|
||||
<view class="u-p-20 error-content">
|
||||
{{config.errorTip}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="error-prompt">
|
||||
<view class="error-prompt-title u-p-l-20 u-p-r-20">
|
||||
错误内容:
|
||||
</view>
|
||||
<view class="u-p-20 error-content">
|
||||
{{config.errorData}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
config: {},
|
||||
errorData: [],
|
||||
errorTip: {}
|
||||
}
|
||||
},
|
||||
onLoad(e) {
|
||||
this.config = JSON.parse(this.jnpf.base64.decode(e.data))
|
||||
this.errorData = JSON.parse(this.config.errorData)
|
||||
this.errorTip = JSON.parse(this.config.errorTip)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.logError-v {
|
||||
width: 100vw;
|
||||
|
||||
.error-prompt {
|
||||
.error-prompt-title {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
background-color: #edeff6;
|
||||
line-height: 80rpx;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.error-content {
|
||||
word-break: break-word;
|
||||
line-height: 50rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
519
pages/workFlow/flowBefore/revokeForm.vue
Normal file
@@ -0,0 +1,519 @@
|
||||
<template>
|
||||
<view class="flowBefore-v">
|
||||
<div class="flow-urgent-value" :style="{'background-color':flowUrgentList[selectflowUrgent.extra].bgColor}"
|
||||
@click="handleShowSelect">
|
||||
<span :style="{'color':flowUrgentList[selectflowUrgent.extra].color}">{{selectflowUrgent.label}}</span>
|
||||
</div>
|
||||
<view class="flowBefore-box">
|
||||
<view class="scroll-v" scroll-y>
|
||||
<childForm ref="child" :config="config" v-if="!loading" :key="childFormKey" />
|
||||
<RecordTimeList :progressList="progressList" :taskInfo="taskInfo" v-if="!loading"
|
||||
:commentList="commentList" :taskId="config.id" ref="RecordTimeList" @handleReply="goWriteComment"
|
||||
:hasComment="hasComment" :dataLog="dataLog" :opType="config.opType" :formID="config?.formData?.id"
|
||||
:dataLogList="dataLogList">
|
||||
</RecordTimeList>
|
||||
</view>
|
||||
</view>
|
||||
<flowBtn :actionList="actionList" :btnInfo="btnInfo" :opType="config.opType" :hideSaveBtn="config.hideSaveBtn"
|
||||
@handleBtn="handleBtn" :btnLoading="btnLoading" v-if="formLoding" :rightBtnList="rightBtnList"
|
||||
:saveBtnText="properties.saveBtnText" :hasComment="hasComment"
|
||||
:hasSignFor="flowInfo?.flowNodes?.global?.hasSignFor">
|
||||
</flowBtn>
|
||||
<u-select :list="flowUrgentList" v-model="showFlowUrgent" @confirm="seltConfirm"
|
||||
:default-value="defaultValue" />
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
getDelegateUser
|
||||
} from '@/api/workFlow/entrust.js'
|
||||
import {
|
||||
Create,
|
||||
Update
|
||||
} from '@/api/workFlow/workFlowForm'
|
||||
import {
|
||||
FlowTask,
|
||||
} from '@/api/workFlow/flowBefore'
|
||||
import {
|
||||
Revoke,
|
||||
Press
|
||||
} from '@/api/workFlow/flowLaunch'
|
||||
import {
|
||||
getOnlineLog
|
||||
} from '@/api/apply/visualDev'
|
||||
import {
|
||||
createComment
|
||||
} from '@/api/workFlow/flowEngine'
|
||||
import resources from '@/libs/resources.js'
|
||||
import childForm from './form.vue'
|
||||
import flowBtn from '../components/flowBtn'
|
||||
import RecordTimeList from '../components/RecordTimeList'
|
||||
import {
|
||||
useUserStore
|
||||
} from '@/store/modules/user'
|
||||
const sysConfigInfo = uni.getStorageSync('sysConfigInfo')
|
||||
export default {
|
||||
components: {
|
||||
childForm,
|
||||
flowBtn,
|
||||
RecordTimeList
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dataLogList: [],
|
||||
dataLog: false,
|
||||
childFormKey: +new Date(),
|
||||
formLoding: false,
|
||||
loading: false,
|
||||
taskInfo: {},
|
||||
btnInfo: [],
|
||||
show: false,
|
||||
config: {},
|
||||
formData: {},
|
||||
properties: {},
|
||||
btnLoading: false,
|
||||
commentList: [],
|
||||
title: '',
|
||||
selectflowUrgent: {
|
||||
extra: '0',
|
||||
label: '普通',
|
||||
value: 1,
|
||||
},
|
||||
showFlowUrgent: false,
|
||||
defaultValue: [0],
|
||||
flowUrgent: 1,
|
||||
flowUrgentList: [{
|
||||
label: '普通',
|
||||
color: '#409EFF',
|
||||
bgColor: '#e5f3fe',
|
||||
value: 1,
|
||||
extra: '0'
|
||||
},
|
||||
{
|
||||
label: '重要',
|
||||
color: '#E6A23C',
|
||||
bgColor: '#fef6e5',
|
||||
value: 2,
|
||||
extra: '1'
|
||||
},
|
||||
{
|
||||
label: '紧急',
|
||||
color: '#F56C6C',
|
||||
bgColor: '#fee5e5',
|
||||
value: 3,
|
||||
extra: '2'
|
||||
},
|
||||
],
|
||||
actionList: [],
|
||||
hasComment: false,
|
||||
progressList: [],
|
||||
rightBtnList: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
baseURL() {
|
||||
return this.define.baseURL
|
||||
},
|
||||
getShowExtraPanel() {
|
||||
return this.dataLog && this.config?.formData?.id || (this.config.opType != '-1' && !this.loading)
|
||||
}
|
||||
},
|
||||
onUnload() {
|
||||
uni.$off('comment')
|
||||
},
|
||||
onShow() {
|
||||
uni.$on('comment', data => {
|
||||
this.commentList = [];
|
||||
this.current = 0;
|
||||
this.addComment(data)
|
||||
})
|
||||
},
|
||||
onLoad(e) {
|
||||
this.config = JSON.parse(this.jnpf.base64.decode(e.config))
|
||||
this.$nextTick(() => {
|
||||
this.getBeforeInfo(this.config)
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
addComment(query) {
|
||||
query.taskId = this.config.id
|
||||
createComment(query).then(res => {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.RecordTimeList.change(1)
|
||||
})
|
||||
})
|
||||
},
|
||||
//流程按钮事件
|
||||
handleBtn(type, dataForm = {}) {
|
||||
if ('comment'.includes(type)) this.goWriteComment();
|
||||
},
|
||||
goWriteComment(replyId) {
|
||||
let data = {
|
||||
taskId: this.config.id
|
||||
};
|
||||
if (replyId) data.replyId = replyId;
|
||||
data = encodeURIComponent(JSON.stringify(data));
|
||||
uni.navigateTo({
|
||||
url: '/pages/workFlow/comment/index?data=' + data
|
||||
})
|
||||
},
|
||||
getBeforeInfo() {
|
||||
let config = this.config;
|
||||
this.formData.flowId = config.flowId;
|
||||
this.loading = true;
|
||||
const query = {
|
||||
flowId: config.flowId, // 流程大Id
|
||||
opType: config.opType == 2 ? 3 : config.opType, //特殊:待办点击开始办理需要跳到在办页面
|
||||
};
|
||||
if (config.opType != "-1" && config.opType != '0') query.operatorId = config.operatorId;
|
||||
FlowTask(config?.taskId || config?.id || 0, query).then((res) => {
|
||||
this.flowInfo = res.data.flowInfo || {};
|
||||
this.properties = res.data.nodeProperties || {};
|
||||
this.formInfo = res.data.formInfo || {};
|
||||
this.taskInfo = res.data.taskInfo || {};
|
||||
this.btnInfo = res.data.btnInfo || [];
|
||||
this.progressList = res.data.progressList || [];
|
||||
config.formOperates = res.data.formOperates || [];
|
||||
config.formType = this.formInfo.type
|
||||
const fullName =
|
||||
config.opType == "-1" ?
|
||||
this.flowInfo.fullName :
|
||||
this.taskInfo.fullName;
|
||||
config.fullName = fullName;
|
||||
this.title = this.flowInfo.fullName;
|
||||
this.thisStep = this.taskInfo.thisStep || "";
|
||||
if (config.status !== 0 && config.status !== 3) {
|
||||
this.title = this.thisStep ?
|
||||
config.fullName + "/" + this.thisStep :
|
||||
config.fullName;
|
||||
}
|
||||
config.type = this.flowInfo.type;
|
||||
config.draftData = res.data.draftData || null;
|
||||
config.formData = res.data.formData || {};
|
||||
let dataId = config.formData.id
|
||||
config.formEnCode = this.formInfo.enCode;
|
||||
this.recordList = (res.data.recordList || []).reverse();
|
||||
config.formConf = this.formInfo.formData;
|
||||
if (config.formConf) {
|
||||
this.dataLog = JSON.parse(config.formConf).dataLog
|
||||
if (this.dataLog) this.getOnlineLog(dataId)
|
||||
}
|
||||
this.hasComment = this.flowInfo.flowNodes.global.hasComment;
|
||||
this.formLoding = true;
|
||||
// 设置表单标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.config.formEnCode === "revoke" ? `${this.flowInfo.fullName}撤销申请` : this
|
||||
.flowInfo.fullName,
|
||||
});
|
||||
if (config.formRecords && config.title) {
|
||||
uni.setNavigationBarTitle({
|
||||
title: config.title,
|
||||
});
|
||||
}
|
||||
this.flowUrgent = this.taskInfo.flowUrgent || 1;
|
||||
const getSelectInfo = () => {
|
||||
var obj = {
|
||||
value: this.flowUrgent,
|
||||
extra: "0",
|
||||
label: "普通",
|
||||
};
|
||||
this.flowUrgentList.forEach((e, i) => {
|
||||
if (e.value == this.flowUrgent) {
|
||||
obj.extra = i;
|
||||
obj.label = e.label;
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
};
|
||||
this.selectflowUrgent = getSelectInfo();
|
||||
if (config.opType != "-1" && config.opType != "3") config.readonly =
|
||||
true;
|
||||
config.formOperates = [];
|
||||
if (config.opType == 0) {
|
||||
if (this.properties && this.properties && this.properties.formOperates) config
|
||||
.formOperates = this.properties.formOperates || [];
|
||||
} else {
|
||||
config.formOperates = res.data.formOperates || [];
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.$nextTick(() => {
|
||||
if (!this.$refs.child || !this.$refs.child.$refs.form) {
|
||||
uni.showToast({
|
||||
title: "暂无此流程表单",
|
||||
icon: "none",
|
||||
complete: () => {
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 1500);
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.$refs.child.$refs.form.init(config)
|
||||
});
|
||||
}, 100);
|
||||
this.loading = false;
|
||||
this.config = config;
|
||||
});
|
||||
},
|
||||
//获取修改记录
|
||||
getOnlineLog(dataId) {
|
||||
let modelId = this.formInfo.id
|
||||
getOnlineLog(modelId, dataId).then(res => {
|
||||
let list = res.data.list || []
|
||||
//倒序转正
|
||||
this.dataLogList = [...list].reverse()
|
||||
})
|
||||
},
|
||||
initBtnList() {
|
||||
const list = [];
|
||||
const properties = this.properties;
|
||||
const btnInfo = this.btnInfo;
|
||||
// 流程审批
|
||||
if (this.hasComment && this.config.opType != '-1' && this.rightBtnList.length) list.push({
|
||||
id: 'comment',
|
||||
text: '评论'
|
||||
});
|
||||
this.actionList = list;
|
||||
},
|
||||
// 撤销操作
|
||||
|
||||
handleShowSelect() {
|
||||
if (this.config.opType == '-1') this.showFlowUrgent = true
|
||||
},
|
||||
seltConfirm(e) {
|
||||
this.flowUrgent = e[0].value
|
||||
this.selectflowUrgent = e[0]
|
||||
this.defaultValue = [this.flowUrgentList.findIndex(item => item.value === e[0].value)] || [0]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f0f2f6;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.flow-urgent-value {
|
||||
position: fixed;
|
||||
top: var(--window-top);
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 60rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.flowBefore-v {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 60rpx;
|
||||
|
||||
|
||||
|
||||
.workFlowTitle {
|
||||
width: 100%;
|
||||
padding: 0 32rpx 32rpx 32rpx;
|
||||
background-color: #FFFFFF;
|
||||
font-size: 32rpx;
|
||||
font-weight: 700;
|
||||
white-space: pre-wrap;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.flowBefore-box {
|
||||
height: 100%;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
padding-bottom: 3.3rem;
|
||||
|
||||
.sticky-box {
|
||||
z-index: 500;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.swiper-box {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.swiper-item {
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.scroll-v {
|
||||
flex: 1;
|
||||
/* #ifndef MP-ALIPAY */
|
||||
flex-direction: column;
|
||||
/* #endif */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.flowStatus {
|
||||
position: absolute;
|
||||
top: 90rpx;
|
||||
right: 0;
|
||||
border: 0;
|
||||
margin: 20rpx;
|
||||
opacity: 0.7;
|
||||
z-index: 999;
|
||||
|
||||
image {
|
||||
width: 200rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.discuss_btn {
|
||||
background-color: #fff;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
// height: 88rpx;
|
||||
// box-shadow: 0 -2rpx 8rpx #e1e5ec;
|
||||
z-index: 20;
|
||||
|
||||
.custom-style {
|
||||
background-color: #2979ff;
|
||||
color: #FFFFFF;
|
||||
width: 100%;
|
||||
border-radius: 0 !important;
|
||||
|
||||
&::after {
|
||||
border: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 24rpx;
|
||||
text-align: center;
|
||||
|
||||
.confrim-btn {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.send {
|
||||
flex: 1;
|
||||
background-color: #2979ff;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.cancel {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.approverContent {
|
||||
height: 1000rpx;
|
||||
overflow-y: scroll;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.notice-warp {
|
||||
top: 0;
|
||||
height: 5.6rem;
|
||||
|
||||
.close-icon {
|
||||
height: 60rpx;
|
||||
padding: 10rpx 20rpx;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.popup {
|
||||
margin-top: 5.65rem;
|
||||
|
||||
.list-box {
|
||||
.item {
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nodeList-v {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.record-v {
|
||||
padding: 32rpx 32rpx 10rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
|
||||
.discuss_box {
|
||||
.discuss_list {
|
||||
|
||||
.time_button {
|
||||
padding-left: 110rpx;
|
||||
margin-top: 20rpx;
|
||||
padding-right: 10rpx;
|
||||
}
|
||||
|
||||
.discuss_txt {
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
|
||||
.discuss_txt_left {
|
||||
.uName {
|
||||
margin-left: 8px;
|
||||
font-size: 14px;
|
||||
font-family: PingFang SC;
|
||||
line-height: 17rpx;
|
||||
|
||||
.replyText {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.del {
|
||||
color: red;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.reply {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.discuss_content {
|
||||
font-size: 12px;
|
||||
padding-left: 70rpx;
|
||||
|
||||
.img_box {
|
||||
margin: 40rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.comment-creator-time {
|
||||
font-size: 12px;
|
||||
color: #999999;
|
||||
font-family: PingFang SC;
|
||||
line-height: 17rpx;
|
||||
}
|
||||
|
||||
.comment-content-color {
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.comment-header-color {
|
||||
color: #303133;
|
||||
}
|
||||
</style>
|
||||
269
pages/workFlow/flowTodo/FlowMixin.js
Normal file
@@ -0,0 +1,269 @@
|
||||
/**
|
||||
* opType
|
||||
* -1 - 我发起的新建/编辑
|
||||
* 0 - 我发起的详情
|
||||
* 1 - 待签事宜
|
||||
* 2 - 待办事宜
|
||||
* 3 - 在办事宜
|
||||
* 4 - 已办事宜
|
||||
* 5 - 抄送事宜
|
||||
* 6 - 流程监控
|
||||
*/
|
||||
const statusMap = {
|
||||
1: [{
|
||||
name: '全部',
|
||||
status: ''
|
||||
},
|
||||
{
|
||||
name: '协办',
|
||||
status: '7'
|
||||
},
|
||||
{
|
||||
name: '退回',
|
||||
status: '5'
|
||||
},
|
||||
{
|
||||
name: '超时',
|
||||
status: '-2'
|
||||
}
|
||||
],
|
||||
2: [{
|
||||
name: '全部',
|
||||
status: ''
|
||||
},
|
||||
{
|
||||
name: '协办',
|
||||
status: '7'
|
||||
},
|
||||
{
|
||||
name: '退回',
|
||||
status: '5'
|
||||
},
|
||||
{
|
||||
name: '超时',
|
||||
status: '-2'
|
||||
}
|
||||
],
|
||||
3: [{
|
||||
name: '全部',
|
||||
status: ''
|
||||
},
|
||||
{
|
||||
name: '待提交',
|
||||
status: '0'
|
||||
},
|
||||
{
|
||||
name: '进行中',
|
||||
status: '1'
|
||||
},
|
||||
{
|
||||
name: '已完成',
|
||||
status: '2'
|
||||
}
|
||||
],
|
||||
4: [{
|
||||
name: '全部',
|
||||
status: ''
|
||||
},
|
||||
{
|
||||
name: '同意',
|
||||
status: '1'
|
||||
},
|
||||
{
|
||||
name: '拒绝',
|
||||
status: '2'
|
||||
},
|
||||
{
|
||||
name: '转审',
|
||||
status: '3'
|
||||
},
|
||||
{
|
||||
name: '加签',
|
||||
status: '4'
|
||||
},
|
||||
{
|
||||
name: '退回',
|
||||
status: '5'
|
||||
}
|
||||
],
|
||||
5: [{
|
||||
name: '全部',
|
||||
status: ''
|
||||
},
|
||||
{
|
||||
name: '已读',
|
||||
status: '1'
|
||||
},
|
||||
{
|
||||
name: '未读',
|
||||
status: '0'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
import {
|
||||
getOperatorList,
|
||||
getFlowLaunchList
|
||||
} from '@/api/workFlow/template'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
mescrollTop: 206,
|
||||
statusList: [],
|
||||
tabsList: [{
|
||||
fullName: '在办',
|
||||
category: '2',
|
||||
key: 2,
|
||||
enCode: "workFlow.flowDoing"
|
||||
}, {
|
||||
fullName: '发起',
|
||||
category: null,
|
||||
key: 3,
|
||||
enCode: "workFlow.flowLaunch"
|
||||
}, {
|
||||
fullName: '已办',
|
||||
category: '3',
|
||||
key: 4,
|
||||
enCode: "workFlow.flowDone"
|
||||
}, {
|
||||
fullName: '抄送',
|
||||
category: '4',
|
||||
key: 5,
|
||||
enCode: "workFlow.flowCirculate"
|
||||
}],
|
||||
current: 0,
|
||||
subsectionIndex: 0,
|
||||
status: '',
|
||||
sysConfigInfo: {},
|
||||
menuList: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
current: {
|
||||
handler(val) {
|
||||
if (this.sysConfigInfo.flowSign == 1 && val == 0) {
|
||||
this.statusList = []
|
||||
this.mescrollTop = 206 / 2
|
||||
return
|
||||
}
|
||||
this.statusList = statusMap[this.tabsList[val].key]
|
||||
this.mescrollTop = 322 / 2
|
||||
this.category = this.tabsList[this.current].category
|
||||
},
|
||||
immediate: true,
|
||||
deep: true
|
||||
},
|
||||
},
|
||||
onLoad(e) {
|
||||
this.config = e?.data && JSON.parse(decodeURIComponent(e?.data))
|
||||
this.sysConfigInfo = uni.getStorageSync('sysConfigInfo') || {}
|
||||
this.addTabList()
|
||||
/* 从门户来到工作流 */
|
||||
if (e?.data) this.fromPortal()
|
||||
},
|
||||
methods: {
|
||||
addTabList() {
|
||||
const configToCheck = [{
|
||||
key: 'flowTodo',
|
||||
tab: {
|
||||
fullName: '待办',
|
||||
category: '1',
|
||||
key: 1,
|
||||
enCode: "workFlow.flowTodo"
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'flowSign',
|
||||
tab: {
|
||||
fullName: '待签',
|
||||
category: '0',
|
||||
key: 0,
|
||||
enCode: "workFlow.flowToSign"
|
||||
}
|
||||
}
|
||||
];
|
||||
configToCheck.forEach(config => {
|
||||
if (this.sysConfigInfo[config.key] === 1) return this.tabsList.unshift(config.tab);
|
||||
});
|
||||
this.menuList = uni.getStorageSync("menuList");
|
||||
let workFlowList = this.menuList.filter(o => o.enCode === 'workFlow')
|
||||
if (!workFlowList.length) return
|
||||
let menuData = workFlowList[0]?.children
|
||||
this.tabsList = this.tabsList.filter(tab =>
|
||||
menuData.some(menu => menu.enCode === tab.enCode)
|
||||
);
|
||||
},
|
||||
fromPortal() {
|
||||
let i = this.tabsList.findIndex(o => o.key === this.config.tabIndex)
|
||||
let item = this.tabsList[i]
|
||||
this.current = i;
|
||||
this.category = item?.category || null
|
||||
this.resetUpScroll()
|
||||
},
|
||||
/* tab1 */
|
||||
change(index) {
|
||||
let item = this.tabsList[index]
|
||||
this.current = index;
|
||||
this.status = ''
|
||||
this.keyword = ''
|
||||
this.subsectionIndex = 0
|
||||
this.category = item?.category || null
|
||||
this.resetUpScroll()
|
||||
},
|
||||
/* tab2 */
|
||||
subsection(e) {
|
||||
let item = this.statusList[e]
|
||||
this.status = item.status
|
||||
this.subsectionIndex = e
|
||||
this.resetUpScroll()
|
||||
},
|
||||
resetUpScroll() {
|
||||
this.$nextTick(() => {
|
||||
this.list = [];
|
||||
this.mescroll.resetUpScroll();
|
||||
})
|
||||
},
|
||||
/* 列表数据 */
|
||||
upCallback(page) {
|
||||
let methods = this.category ? getOperatorList : getFlowLaunchList;
|
||||
let query = {
|
||||
currentPage: page.num,
|
||||
pageSize: page.size,
|
||||
keyword: this.keyword,
|
||||
category: this.tabsList[this.current].category,
|
||||
status: this.status
|
||||
}
|
||||
methods(query, {
|
||||
load: page.num == 1
|
||||
}).then(res => {
|
||||
this.mescroll.endSuccess(res.data.list.length);
|
||||
if (page.num == 1) this.list = [];
|
||||
let flowStatus;
|
||||
const list = res.data.list.map(o => ({
|
||||
'flowStatus': this.getFlowStatus(o.status),
|
||||
'opType': this.setOpType(o.status),
|
||||
'swipeAction': this.swipeAction(o.status),
|
||||
...o
|
||||
}))
|
||||
this.list = this.list.concat(list);
|
||||
}).catch(() => {
|
||||
this.mescroll.endErr();
|
||||
})
|
||||
},
|
||||
swipeAction(status) {
|
||||
let swipeAction = true
|
||||
if (this.tabsList[this.current].key === 3 && !this.category && (status == '0' || status == '9'))
|
||||
swipeAction = false
|
||||
return swipeAction
|
||||
},
|
||||
/* 设置opType */
|
||||
setOpType(status) {
|
||||
if (this.tabsList[this.current].key == 3) return status == '0' || status == '9' || status == '8' ? '-1' : 0
|
||||
if (this.tabsList[this.current].key == 0) return 1
|
||||
if (this.tabsList[this.current].key == 1) return 2
|
||||
if (this.tabsList[this.current].key == 2) return 3
|
||||
if (this.tabsList[this.current].key == 4) return 4
|
||||
if (this.tabsList[this.current].key == 5) return 5
|
||||
}
|
||||
}
|
||||
}
|
||||
180
pages/workFlow/flowTodo/flowList.vue
Normal file
@@ -0,0 +1,180 @@
|
||||
<template>
|
||||
<view class="flowLaunch-v">
|
||||
<view class="flow-list" v-if="list.length > 0">
|
||||
<view class="flow-list-box">
|
||||
<SwipeItem :list="list" :buttons="options" @action="handleClick" ref="swipeItem" :marginB="20"
|
||||
:borderR="10">
|
||||
<template v-slot="{ item,index }">
|
||||
<view class="item" @click="goDetail(item)" :id="'item'+index" ref="mydom">
|
||||
<view class="item-left">
|
||||
<view class="item-left-top">
|
||||
<view class='common-lable-entrust' v-if="item.delegateUser">
|
||||
{{!category ? '委托' : '代理' }}
|
||||
</view>
|
||||
<view class='common-lable'
|
||||
:class="{'urgent-lable':item.flowUrgent==2,'important-lable':item.flowUrgent==3}">
|
||||
{{getLableValue(item.flowUrgent)}}
|
||||
</view>
|
||||
<text class="title u-font-28 u-line-1">{{item.fullName}}</text>
|
||||
</view>
|
||||
<text class="title u-line-1 u-font-24">审批节点:{{item.currentNodeName}}<text
|
||||
class="titInner">{{item.thisStep ? item.thisStep : ''}}</text></text>
|
||||
<text class="time title u-font-24">发起时间:<text
|
||||
class="titInner">{{item.startTime?$u.timeFormat(item.startTime, 'yyyy-mm-dd hh:MM:ss'):''}}</text></text>
|
||||
</view>
|
||||
<view class="item-right">
|
||||
<image :src="item.flowStatus" mode="widthFix" class="item-right-img">
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</SwipeItem>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
delFlowLaunch
|
||||
} from '@/api/workFlow/template'
|
||||
import SwipeItem from "@/components/SwipeItem/index"
|
||||
export default {
|
||||
name: "FlowList",
|
||||
components: {
|
||||
SwipeItem
|
||||
},
|
||||
props: {
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
swipeAction: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
category: {
|
||||
type: [String, Number],
|
||||
default: '0'
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
options: [{
|
||||
text: '删除',
|
||||
style: {
|
||||
backgroundColor: '#dd524d'
|
||||
}
|
||||
}],
|
||||
title: '',
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
open(index) {
|
||||
// 先将正在被操作的swipeAction标记为打开状态,否则由于props的特性限制,
|
||||
// 原本为'false',再次设置为'false'会无效
|
||||
this.list[index].show = true;
|
||||
this.list.map((val, idx) => {
|
||||
if (index != idx) this.list[idx].show = false;
|
||||
})
|
||||
},
|
||||
goDetail(item) {
|
||||
const config = {
|
||||
opType: item.opType,
|
||||
operatorId: item.id,
|
||||
category: this.category,
|
||||
...item
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: '/pages/workFlow/flowBefore/index?config=' +
|
||||
this.jnpf.base64.encode(JSON.stringify(config))
|
||||
})
|
||||
},
|
||||
handleClick(data) {
|
||||
const {
|
||||
index
|
||||
} = data
|
||||
const item = this.list[index]
|
||||
if ([1, 2, 3, 5].includes(item.status)) {
|
||||
this.$u.toast("流程正在审核,请勿删除")
|
||||
this.list[index].show = false
|
||||
return
|
||||
}
|
||||
delFlowLaunch(item.id).then(res => {
|
||||
this.$u.toast(res.msg)
|
||||
this.list.splice(index, 1)
|
||||
})
|
||||
},
|
||||
getLableValue(value) {
|
||||
var lableValue = ''
|
||||
switch (value) {
|
||||
case 1:
|
||||
lableValue = '普通'
|
||||
break;
|
||||
case 2:
|
||||
lableValue = '重要'
|
||||
break;
|
||||
case 3:
|
||||
lableValue = '紧急'
|
||||
break;
|
||||
default:
|
||||
lableValue = '普通'
|
||||
break;
|
||||
}
|
||||
return lableValue
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.flowLaunch-v {
|
||||
width: 100%;
|
||||
|
||||
.flow-list-box {
|
||||
width: 95%;
|
||||
|
||||
.item-left-top {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
.common-lable {
|
||||
font-size: 24rpx;
|
||||
padding: 2rpx 8rpx;
|
||||
margin-right: 8rpx;
|
||||
border-radius: 8rpx;
|
||||
color: #409EFF;
|
||||
border: 1px solid #409EFF;
|
||||
background-color: #e5f3fe;
|
||||
|
||||
&-entrust {
|
||||
margin-right: 8rpx;
|
||||
font-size: 24rpx;
|
||||
padding: 2rpx 8rpx;
|
||||
border-radius: 8rpx;
|
||||
background-color: #dbf1e1;
|
||||
color: #19be6b;
|
||||
border: 1px solid #19be6b;
|
||||
}
|
||||
}
|
||||
|
||||
.urgent-lable {
|
||||
color: #E6A23C;
|
||||
border: 1px solid #E6A23C;
|
||||
background-color: #fef6e5;
|
||||
}
|
||||
|
||||
.important-lable {
|
||||
color: #F56C6C;
|
||||
border: 1px solid #F56C6C;
|
||||
background-color: #fee5e5;
|
||||
}
|
||||
|
||||
.title {
|
||||
width: unset;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
172
pages/workFlow/flowTodo/index.vue
Normal file
@@ -0,0 +1,172 @@
|
||||
<template>
|
||||
<view class="flow-v">
|
||||
<view class="notice-warp">
|
||||
<view class="search-box">
|
||||
<u-search :placeholder="$t('app.apply.pleaseKeyword')" v-model="keyword" height="72"
|
||||
:show-action="false" @change="search" bg-color="#f0f2f6" shape="square">
|
||||
</u-search>
|
||||
</view>
|
||||
<view class="flow-tabs">
|
||||
<u-tabs ref="tabs" :list="tabsList" active-color="#0177FF" inactive-color="#303133" font-size="30"
|
||||
v-model="current" name="fullName" @change="change" height="80" :is-scroll="false"></u-tabs>
|
||||
</view>
|
||||
<view class="flow-status-tabs" v-if="statusList.length">
|
||||
<u-subsection :list="statusList" :current="subsectionIndex" name="name" active-color="#2979FF"
|
||||
inactive-color="#999999" bg-color="#F2F3F7" font-size="24" :bold="false"
|
||||
@change="subsection"></u-subsection>
|
||||
</view>
|
||||
</view>
|
||||
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback" :down="downOption"
|
||||
:up="upOption" :top="mescrollTop">
|
||||
<flowlist :list='list' :swipeAction='current != 3' :category='category' />
|
||||
</mescroll-body>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import resources from '@/libs/resources.js'
|
||||
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
|
||||
import FlowMixin from "./FlowMixin.js";
|
||||
import flowlist from './flowList.vue'
|
||||
export default {
|
||||
components: {
|
||||
flowlist
|
||||
},
|
||||
mixins: [MescrollMixin, FlowMixin],
|
||||
data() {
|
||||
return {
|
||||
activeItemStyle: {
|
||||
backgroundColor: '#fff'
|
||||
},
|
||||
keyword: '',
|
||||
category: '0',
|
||||
list: [],
|
||||
downOption: {
|
||||
use: true,
|
||||
auto: true
|
||||
},
|
||||
upOption: {
|
||||
page: {
|
||||
num: 0,
|
||||
size: 20,
|
||||
time: null
|
||||
},
|
||||
empty: {
|
||||
use: true,
|
||||
icon: resources.message.nodata,
|
||||
tip: this.$t('common.noData'),
|
||||
fixed: true,
|
||||
top: "300rpx",
|
||||
},
|
||||
textNoMore: this.$t('app.apply.noMoreData')
|
||||
},
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
uni.$off('operate')
|
||||
uni.$on('refresh', () => {
|
||||
this.list = [];
|
||||
this.mescroll.resetUpScroll();
|
||||
})
|
||||
},
|
||||
onUnload() {
|
||||
uni.$off('refresh')
|
||||
},
|
||||
methods: {
|
||||
getFlowStatus(status) {
|
||||
let flowStatus;
|
||||
//待签收
|
||||
if (this.category == '0') flowStatus = resources.status.signfor
|
||||
// 待办,在办
|
||||
if (this.category == '1' || this.category == '2') {
|
||||
//流转中
|
||||
if (status == '1') flowStatus = resources.status.circulation
|
||||
//已退回
|
||||
if (status == '5') flowStatus = resources.status.back
|
||||
//协办
|
||||
if (status == '7') flowStatus = resources.status.assist
|
||||
//转审
|
||||
if (status == '3') flowStatus = resources.status.transfer
|
||||
//撤回
|
||||
if (status == '6') flowStatus = resources.status.recall
|
||||
//撤销中
|
||||
if (status == '8') flowStatus = resources.status.revoking
|
||||
//加签
|
||||
if (status == '2') flowStatus = resources.status.addSign
|
||||
//指派
|
||||
if (status == '4') flowStatus = resources.status.assign
|
||||
//转办
|
||||
if (status == '9') flowStatus = resources.status.transfer2
|
||||
}
|
||||
//发起
|
||||
if (!this.category) {
|
||||
//待提交
|
||||
if (status == '0') flowStatus = resources.status.draft
|
||||
//进行中
|
||||
if (status == '1') flowStatus = resources.status.doing
|
||||
//已通过
|
||||
if (status == '2') flowStatus = resources.status.adopt
|
||||
//已拒绝
|
||||
if (status == '3') flowStatus = resources.status.reject
|
||||
//已终止
|
||||
if (status == '4') flowStatus = resources.status.cancel
|
||||
//已暂停
|
||||
if (status == '5') flowStatus = resources.status.pause
|
||||
//撤销中
|
||||
if (status == '6') flowStatus = resources.status.revoking
|
||||
//已撤销
|
||||
if (status == '7') flowStatus = resources.status.revoke
|
||||
//退回
|
||||
if (status == '8') flowStatus = resources.status.back
|
||||
//撤回
|
||||
if (status == '9') flowStatus = resources.status.recall
|
||||
}
|
||||
//已办
|
||||
if (this.category == '3') {
|
||||
//转审
|
||||
if (status == '7') flowStatus = resources.status.transfer
|
||||
//同意
|
||||
if (status == '1') flowStatus = resources.status.agree
|
||||
//拒绝
|
||||
if (status == '0') flowStatus = resources.status.refuse
|
||||
//加签
|
||||
if (status == '5') flowStatus = resources.status.addSign
|
||||
//退回
|
||||
if (status == '3') flowStatus = resources.status.return
|
||||
//转办
|
||||
if (status == '18') flowStatus = resources.status.transfer2
|
||||
}
|
||||
//抄送
|
||||
if (this.category == '4') {
|
||||
//进行中
|
||||
if (status == '1') flowStatus = resources.status.doing
|
||||
//已通过
|
||||
if (status == '2') flowStatus = resources.status.adopt
|
||||
//已拒绝
|
||||
if (status == '3') flowStatus = resources.status.reject
|
||||
//已退回
|
||||
if (status == '8') flowStatus = resources.status.back
|
||||
}
|
||||
return flowStatus
|
||||
},
|
||||
search() {
|
||||
// 节流,避免输入过快多次请求
|
||||
this.searchTimer && clearTimeout(this.searchTimer)
|
||||
this.searchTimer = setTimeout(() => {
|
||||
this.list = [];
|
||||
this.mescroll.resetUpScroll();
|
||||
}, 300)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f0f2f6;
|
||||
}
|
||||
|
||||
.u-tabs {
|
||||
padding-bottom: 4rpx;
|
||||
}
|
||||
</style>
|
||||
103
pages/workFlow/operate/components/CommonList.vue
Normal file
@@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<view class="common-list-v" v-if="show">
|
||||
<view class="common-list-contain">
|
||||
<view class="common-list-main u-p-20 u-flex-col">
|
||||
<view class="common-list-search" style=" ">
|
||||
<uni-search-bar radius="100" placeholder="请输入" clearButton="always" cancelButton="always"
|
||||
@cancel="cancel" v-model="searchValue" focus />
|
||||
</view>
|
||||
<view class="" style="flex: 1;margin-top: 10rpx; overflow-y: scroll;" v-if="columnList.length">
|
||||
<view class="u-line-1" style="width: 100%;height:68rpx;line-height: 68rpx;"
|
||||
v-for="(item,index) in columnList" :key="index" @click.stop="selectConfirm(item)">
|
||||
{{item.commonWordsText}}
|
||||
</view>
|
||||
</view>
|
||||
<JnpfEmpty v-else />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getSelector
|
||||
} from "@/api/commonWords.js";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
commonWordsList: [],
|
||||
searchValue: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
columnList() {
|
||||
return this.commonWordsList.filter((o) => (o.commonWordsText && o.commonWordsText.match(this.searchValue)))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.show = true
|
||||
this.getCommonList()
|
||||
},
|
||||
cancel() {
|
||||
this.close()
|
||||
},
|
||||
close() {
|
||||
this.searchValue = ""
|
||||
this.show = false
|
||||
},
|
||||
selectConfirm(item) {
|
||||
this.$emit('confirm', item)
|
||||
|
||||
this.close()
|
||||
},
|
||||
getCommonList() {
|
||||
getSelector().then((res) => {
|
||||
let list = JSON.parse(JSON.stringify(res.data.list)) || []
|
||||
this.commonWordsList = list
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.common-list-v {
|
||||
z-index: 9000;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100vh !important;
|
||||
|
||||
|
||||
|
||||
|
||||
.common-list-contain {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.common-list-main {
|
||||
background: white;
|
||||
|
||||
height: 100%;
|
||||
|
||||
|
||||
.common-list-search {
|
||||
width: 100%;
|
||||
height: 70rpx;
|
||||
|
||||
.uni-searchbar {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
|
||||
.uni-searchbar__box {
|
||||
justify-content: flex-start !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
130
pages/workFlow/operate/components/HandleOpinion.vue
Normal file
@@ -0,0 +1,130 @@
|
||||
<template>
|
||||
<view class="opinion">
|
||||
<view class="opinion-box">
|
||||
<u-input type="textarea" v-model="handleOpinion" placeholder="请输入" :inputBorder='false' @input="onInput"
|
||||
class="easyinput" :clearable="true" focus></u-input>
|
||||
<view class="u-m-t-10 u-flex opinion-inner" v-if="showCommon">
|
||||
<view class="u-flex opinion-l" v-if="commonList.length">
|
||||
<text class="u-line-1 common-txt" v-if="commonList[0]"
|
||||
@click.stop="addTextareaValue(0)">{{commonList[0].commonWordsText}}</text>
|
||||
<text class="common-txt u-m-l-10 u-line-1" v-if="commonList[1]"
|
||||
@click.stop="addTextareaValue(1)">{{commonList[1].commonWordsText}}</text>
|
||||
</view>
|
||||
<view class="u-flex opinion-r">
|
||||
<text class="txt" @click.stop="addCommonWords">设为常用语</text>
|
||||
<view class="icon-box" @click="showCommonList">
|
||||
<u-icon name="search" color="#565656" size="28"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<CommonList ref="CommonList" @confirm="confirmCommonWord"></CommonList>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CommonList from './CommonList'
|
||||
export default {
|
||||
emits: ['addCommonWords', 'update:modelValue'],
|
||||
name: 'handle-opinion',
|
||||
components: {
|
||||
CommonList
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
type: [String, Number]
|
||||
},
|
||||
commonList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
showCommon: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
modelValue: {
|
||||
handler(val) {
|
||||
this.handleOpinion = val
|
||||
},
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
handleOpinion: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
confirmCommonWord(e) {
|
||||
this.handleOpinion = e.commonWordsText
|
||||
this.$emit('update:modelValue', this.handleOpinion)
|
||||
},
|
||||
addCommonWords() {
|
||||
if (!this.handleOpinion) return this.$u.toast('请输入意见');
|
||||
this.$emit('addCommonWords')
|
||||
},
|
||||
onInput(e) {
|
||||
this.$emit('update:modelValue', e)
|
||||
},
|
||||
addTextareaValue(i) {
|
||||
this.handleOpinion += this.commonList[i].commonWordsText
|
||||
this.$emit('update:modelValue', this.handleOpinion)
|
||||
},
|
||||
showCommonList() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.CommonList.open();
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.opinion {
|
||||
width: 100%;
|
||||
|
||||
.opinion-box {
|
||||
border-radius: 8rpx;
|
||||
padding: 0 20rpx 10rpx 20rpx;
|
||||
background: #f5f5f5 !important;
|
||||
|
||||
.opinion-inner {
|
||||
|
||||
|
||||
.opinion-l {
|
||||
max-width: 62%;
|
||||
|
||||
.common-txt {
|
||||
max-width: 240rpx;
|
||||
display: inline-block;
|
||||
border: 1rpx dashed #dcdfe6;
|
||||
padding: 0 10rpx;
|
||||
background-color: #fff;
|
||||
color: #303133;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.opinion-r {
|
||||
flex: 1;
|
||||
justify-content: flex-end;
|
||||
|
||||
.txt {
|
||||
padding: 0 10rpx;
|
||||
color: #0177FF;
|
||||
}
|
||||
|
||||
.icon-box {
|
||||
width: 60rpx;
|
||||
text-align: center;
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
635
pages/workFlow/operate/index.vue
Normal file
@@ -0,0 +1,635 @@
|
||||
<template>
|
||||
<view class="flow-popup-content">
|
||||
<u-form ref="dataForm" :model="dataForm" :label-width="200" :errorType="['toast']">
|
||||
<view class="content">
|
||||
<u-form-item label="分支选择" prop="branchList" required v-if="isBranch">
|
||||
<JnpfSelect v-model="dataForm.branchList" @change="branchChange" placeholder="请选择审批分支"
|
||||
:options="branchList" multiple :props="props" />
|
||||
</u-form-item>
|
||||
<u-form-item class="back-item" label="退回节点" v-if="config.type === 'back' && config.backType"
|
||||
prop="backNodeCode" required>
|
||||
<view class="u-flex-col back-item-inner">
|
||||
<JnpfSelect v-model="dataForm.backNodeCode" :options="config.backNodeList" :props="props"
|
||||
:disabled="config.backNodeCode != 2" />
|
||||
<view class="u-m-t-20 selectNode u-flex" v-if="config.backType == 3">
|
||||
<u-radio-group v-model="dataForm.backType">
|
||||
<u-radio @change="radioChange(item)" v-for="(item, index) in list" :key="index"
|
||||
:name="item.name" :disabled="item.disabled">
|
||||
{{ item.fullName }}
|
||||
</u-radio>
|
||||
</u-radio-group>
|
||||
</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
<u-form-item label="转审给谁" prop="handleIds"
|
||||
v-if="['transfer'].includes(config.type) && propertiesType !== 'processing'" required>
|
||||
<JnpfUserSelect v-model=" dataForm.handleIds" />
|
||||
</u-form-item>
|
||||
<u-form-item label="转办给谁" prop="handleIds"
|
||||
v-if="['transfer'].includes(config.type) && propertiesType === 'processing'" required>
|
||||
<JnpfUserSelect v-model=" dataForm.handleIds" />
|
||||
</u-form-item>
|
||||
<u-form-item label="协办给谁" prop="handleVal" v-if="['assist'].includes(config.type)" required>
|
||||
<JnpfUserSelect v-model=" dataForm.handleVal" multiple @change="changeUserSelect" />
|
||||
</u-form-item>
|
||||
<view v-if="config.type === 'freeApprover'">
|
||||
<u-form-item label="加签人员" prop="addSignUserIdList" required>
|
||||
<JnpfUserSelect v-model="dataForm.addSignUserIdList" multiple />
|
||||
</u-form-item>
|
||||
<u-form-item label="加签类型">
|
||||
<JnpfSelect :options="typeList" v-model="dataForm.addSignType" @change="freeApproverChange" />
|
||||
</u-form-item>
|
||||
<u-form-item label="审批方式">
|
||||
<JnpfRadio v-model="dataForm.counterSign" :options="options" />
|
||||
</u-form-item>
|
||||
<u-form-item label="会签比例" v-if="dataForm.counterSign == 1">
|
||||
<view class="u-flex-col free-box">
|
||||
<JnpfSelect :options="ratioList" v-model="dataForm.auditRatio" />
|
||||
<text class="u-m-l-10 free-box-txt">达到会签比例则通过</text>
|
||||
</view>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<template v-for="(item, index) in candidateList" :key="index" v-if="showCandidate">
|
||||
<u-form-item :label="item.nodeName+ '审批人'" :required="!item.selected" :border-bottom="false">
|
||||
<u-input type="select" v-model="item.fullName" placeholder="请选择审批候选人" input-align="right"
|
||||
@click="openSelect(item)" />
|
||||
</u-form-item>
|
||||
<u-form-item label="已选审批人" v-if="item.selected">
|
||||
<u-input type="textarea" v-model="item.selected" class="textarea" border disabled
|
||||
placeholder="" />
|
||||
</u-form-item>
|
||||
</template>
|
||||
<u-form-item v-if="showOpinion" :label="opinionTitle">
|
||||
<HandleOpinion :commonList="commonList" v-model="dataForm.handleOpinion"
|
||||
@addCommonWords="addCommonWords" :showCommon="false"></HandleOpinion>
|
||||
</u-form-item>
|
||||
<u-form-item prop="handleOpinion" required label-position="top" :label="opinionTitle"
|
||||
v-if="showApproval">
|
||||
<HandleOpinion :commonList="commonList" v-model="dataForm.handleOpinion"
|
||||
@addCommonWords="addCommonWords"></HandleOpinion>
|
||||
</u-form-item>
|
||||
<template v-if="config.approvalField.length">
|
||||
<u-form-item label-position="left" :label="item.fieldName"
|
||||
v-for="(item,index) in config.approvalField" :key="index">
|
||||
<JnpfInput v-if="item.jnpfKey=='input'" v-model="item.value" />
|
||||
<JnpfTextarea v-if="item.jnpfKey=='textarea'" v-model="item.value" />
|
||||
<JnpfInputNumber v-if="item.jnpfKey=='inputNumber'" v-model="item.value" />
|
||||
</u-form-item>
|
||||
</template>
|
||||
<u-form-item :prop="signRule ? 'signImg' : '' " :required="signRule" v-if="config.hasSign">
|
||||
<JnpfSign v-model="dataForm.signImg" signType="ApprovalSign" />
|
||||
</u-form-item>
|
||||
<!-- #ifndef APP-HARMONY -->
|
||||
<u-form-item v-if="config.hasFile">
|
||||
<view class="uploadFile">
|
||||
<JnpfUploadFile v-model="dataForm.fileList" :limit="3" align="left" />
|
||||
</view>
|
||||
</u-form-item>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-HARMONY -->
|
||||
<u-form-item v-if="config.hasFile">
|
||||
<view class="uploadFile">
|
||||
<JnpfUploadFileH v-model="dataForm.fileList" :limit="3" align="left" />
|
||||
</view>
|
||||
</u-form-item>
|
||||
<!-- #endif -->
|
||||
<u-form-item label="抄送人员" v-if="showCustomCopy">
|
||||
<JnpfUserSelect v-model="copyIds" multiple />
|
||||
</u-form-item>
|
||||
</view>
|
||||
</u-form>
|
||||
<view class="flowBefore-actions">
|
||||
<CustomButton class="u-flex buttom-btn-left-inner" :btnText="$t('common.cancelText')"
|
||||
btnIcon="icon-ym icon-ym-add-cancel" customIcon />
|
||||
<u-button class="buttom-btn" type="primary" @click="confirm('confirm')">{{$t('common.okText')}}
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import CustomButton from '@/components/CustomButton'
|
||||
import HandleOpinion from './components/HandleOpinion.vue'
|
||||
import {
|
||||
getSelector,
|
||||
Create
|
||||
} from '@/api/commonWords'
|
||||
export default {
|
||||
components: {
|
||||
HandleOpinion,
|
||||
CustomButton
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
copyIds: [],
|
||||
selectList: [],
|
||||
candidateList: [],
|
||||
commonList: [],
|
||||
title: '',
|
||||
label: '',
|
||||
name: {
|
||||
'reject': '拒绝',
|
||||
'launchRecall': '撤回',
|
||||
'auditRecall': '撤回',
|
||||
'audit': '同意',
|
||||
'back': '退回',
|
||||
'freeApprover': '加签',
|
||||
'transfer': '转审'
|
||||
},
|
||||
ratioList: [{
|
||||
fullName: '10%',
|
||||
id: 10
|
||||
}, {
|
||||
fullName: '20%',
|
||||
id: 20
|
||||
}, {
|
||||
fullName: '30%',
|
||||
id: 30
|
||||
}, {
|
||||
fullName: '40%',
|
||||
id: 40
|
||||
}, {
|
||||
fullName: '50%',
|
||||
id: 50
|
||||
}, {
|
||||
fullName: '60%',
|
||||
id: 60
|
||||
}, {
|
||||
fullName: '70%',
|
||||
id: 70
|
||||
}, {
|
||||
fullName: '80%',
|
||||
id: 80
|
||||
}, {
|
||||
fullName: '90%',
|
||||
id: 90
|
||||
}, {
|
||||
fullName: '100%',
|
||||
id: 100
|
||||
}],
|
||||
typeList: [{
|
||||
fullName: '审批前',
|
||||
id: 1
|
||||
}, {
|
||||
fullName: '审批后',
|
||||
id: 2
|
||||
}],
|
||||
options: [{
|
||||
fullName: '或签',
|
||||
id: 0
|
||||
}, {
|
||||
fullName: '会签',
|
||||
id: 1
|
||||
},
|
||||
{
|
||||
fullName: "依次审批",
|
||||
id: 2,
|
||||
}
|
||||
],
|
||||
list: [{
|
||||
fullName: "重新审批",
|
||||
disabled: false,
|
||||
name: 1,
|
||||
},
|
||||
{
|
||||
fullName: "直接提交给我",
|
||||
disabled: false,
|
||||
name: 2,
|
||||
},
|
||||
],
|
||||
props: {
|
||||
label: 'nodeName',
|
||||
value: 'nodeCode'
|
||||
},
|
||||
showCommonWords: false,
|
||||
dataForm: {
|
||||
auditRatio: 100,
|
||||
counterSign: 0,
|
||||
addSignType: 1,
|
||||
handleIds: '',
|
||||
handleVal: [],
|
||||
addSignUserIdList: '',
|
||||
fileList: [],
|
||||
handleOpinion: "",
|
||||
signImg: "",
|
||||
copyIds: "",
|
||||
branchList: [],
|
||||
candidateList: {},
|
||||
backNodeCode: "",
|
||||
backType: 1
|
||||
},
|
||||
config: {},
|
||||
show: false,
|
||||
selectVal: {},
|
||||
isCandidates: false,
|
||||
rules: {
|
||||
branchList: [{
|
||||
required: true,
|
||||
message: '请选择分支',
|
||||
type: 'array',
|
||||
trigger: 'blur,change'
|
||||
}],
|
||||
backNodeCode: [{
|
||||
required: true,
|
||||
message: '请选择退回节点',
|
||||
trigger: 'blur,change'
|
||||
}],
|
||||
signImg: [{
|
||||
required: true,
|
||||
message: '请签名',
|
||||
trigger: 'blur,change'
|
||||
}],
|
||||
addSignUserIdList: [{
|
||||
required: true,
|
||||
message: '请选择加签人员',
|
||||
type: 'array',
|
||||
trigger: 'blur,change'
|
||||
}],
|
||||
handleIds: [{
|
||||
required: true,
|
||||
message: '请选择人员',
|
||||
trigger: 'blur,change'
|
||||
}],
|
||||
handleVal: [{
|
||||
required: true,
|
||||
message: '请选择协办人员',
|
||||
trigger: 'blur,change',
|
||||
type: 'array'
|
||||
}],
|
||||
handleOpinion: [{
|
||||
required: true,
|
||||
message: '请输入意见',
|
||||
trigger: 'blur,change'
|
||||
}]
|
||||
},
|
||||
isCandidate: false,
|
||||
propertiesType: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isBranch() {
|
||||
let show = false
|
||||
if (this.candidateType !== 3) show = true;
|
||||
this.branchList = this.config.branchList || [];
|
||||
if (!this.branchList.length) show = false;
|
||||
if (this.config.type === 'freeApprover' && this.dataForm.addSignType === 1) show = false;
|
||||
return show
|
||||
},
|
||||
showApproval() {
|
||||
return ['audit', 'reject', 'approvalButton'].includes(this.config.type)
|
||||
},
|
||||
showCustomCopy() {
|
||||
return this.config.isCustomCopy && ['audit', 'reject'].includes(this.config.type)
|
||||
},
|
||||
showCandidate() {
|
||||
return !['transfer', 'revoke', 'recall', 'back', 'assist'].includes(this.config.type) && this.isCandidate
|
||||
},
|
||||
showOpinion() {
|
||||
const list = ['transfer', 'assist', 'revoke', 'auditRecall', 'launchRecall', 'back', 'freeApprover']
|
||||
return list.includes(this.config.type)
|
||||
},
|
||||
opinionTitle() {
|
||||
const typeMap = {
|
||||
'transfer': '转审原因',
|
||||
'revoke': '撤销原因',
|
||||
'assist': '协办原因',
|
||||
'back': '退回意见',
|
||||
'freeApprover': '加签意见',
|
||||
'launchRecall': '撤回原因',
|
||||
'auditRecall': '撤回原因',
|
||||
'audit': '审批意见',
|
||||
'reject': '审批意见'
|
||||
};
|
||||
const specialTypeMap = {
|
||||
'transfer': {
|
||||
label: '转办原因'
|
||||
},
|
||||
'audit': {
|
||||
label: '办理意见'
|
||||
}
|
||||
};
|
||||
const setFormRules = (rules) => {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.dataForm.setRules(rules);
|
||||
});
|
||||
};
|
||||
const type = this.config.type;
|
||||
let resultLabel = typeMap[type] || '';
|
||||
if (specialTypeMap[type] && this.propertiesType === 'processing') resultLabel = specialTypeMap[type].label;
|
||||
return resultLabel;
|
||||
},
|
||||
fileLabel() {
|
||||
const type = this.config.type;
|
||||
const typeMap = {
|
||||
'auditRecall': '撤回附件',
|
||||
'freeApprover': '加签附件',
|
||||
'back': '退回附件',
|
||||
'transfer': '转审附件',
|
||||
'audit': '审批附件',
|
||||
'reject': '审批附件'
|
||||
};
|
||||
if (type === 'transfer' && this.propertiesType === 'processing') return '转办附件';
|
||||
if (type === 'audit' && this.propertiesType === 'processing') return '办理附件';
|
||||
const result = typeMap[type] || '';
|
||||
return result;
|
||||
},
|
||||
signRule() {
|
||||
return this.config.hasSign && (['audit', 'reject'].includes(this.config.type))
|
||||
}
|
||||
},
|
||||
onLoad(data) {
|
||||
try {
|
||||
this.config = JSON.parse(decodeURIComponent(data.config));
|
||||
} catch {
|
||||
this.config = JSON.parse(data.config);
|
||||
}
|
||||
uni.$on("confirm", (data, nodeCode) => {
|
||||
this.selectConfirm(data, nodeCode);
|
||||
});
|
||||
this.init()
|
||||
},
|
||||
onReady() {
|
||||
this.$refs.dataForm.setRules(this.rules);
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.candidateType = this.config.candidateType; /* 1==分支 2==候选人 3==直接通过*/
|
||||
this.candidateList = this.config.candidateList || [];
|
||||
this.propertiesType = this.config?.propertiesType
|
||||
this.getSelector()
|
||||
this.handleLabel()
|
||||
this.config.candidateList.map(o => {
|
||||
this.isCandidates = o.isCandidates
|
||||
})
|
||||
this.copyIds = this.config?.circulateUser || ''
|
||||
this.dataForm.backNodeCode = this.config?.backNodeList?.length ? this.config.backNodeList[0].nodeCode : '';
|
||||
if (this.candidateType != 3) this.isCandidate = true;
|
||||
this.branchList = this.config.branchList || [];
|
||||
if (this.candidateType == 1) {
|
||||
let list = [];
|
||||
this.isCandidate = false;
|
||||
const defaultList = this.candidateList;
|
||||
for (let i = 0; i < this.dataForm.branchList.length; i++) {
|
||||
inner: for (let j = 0; j < this.branchList.length; j++) {
|
||||
let o = this.branchList[j];
|
||||
if (this.dataForm.branchList[i] === o.nodeCode && o.isCandidates) {
|
||||
this.isCandidate = true;
|
||||
list.push({
|
||||
...o,
|
||||
label: o.nodeName + "审批人",
|
||||
});
|
||||
break inner;
|
||||
}
|
||||
}
|
||||
this.candidateList = [...defaultList, ...list];
|
||||
}
|
||||
}
|
||||
this.userInfo = uni.getStorageSync("userInfo") || {};
|
||||
this.dataForm.signImg = this.userInfo.signImg;
|
||||
if (this.config.type === 'freeApprover' && this.dataForm.addSignType == '1') this.isCandidates = false
|
||||
},
|
||||
handleLabel() {
|
||||
const config = this.config;
|
||||
const {
|
||||
type,
|
||||
propertiesType
|
||||
} = config;
|
||||
const typeMapping = {
|
||||
'transfer': {
|
||||
title: propertiesType === 'processing' ? '转办' : '转审',
|
||||
label: '转审'
|
||||
},
|
||||
'assist': {
|
||||
title: '协办',
|
||||
label: '协办'
|
||||
},
|
||||
'revoke': {
|
||||
title: '撤销流程',
|
||||
label: '撤销'
|
||||
},
|
||||
'launchRecall': {
|
||||
title: '撤回流程',
|
||||
label: '撤回'
|
||||
},
|
||||
'reject': {
|
||||
title: '审批拒绝',
|
||||
label: '拒绝'
|
||||
},
|
||||
'audit': (propertiesType) => ({
|
||||
title: propertiesType === 'processing' ? '办理' : '审批',
|
||||
label: '审批'
|
||||
}),
|
||||
'auditRecall': {
|
||||
title: '撤回审核',
|
||||
label: '撤回'
|
||||
},
|
||||
'freeApprover': {
|
||||
title: '加签',
|
||||
label: '加签'
|
||||
},
|
||||
'back': {
|
||||
title: '退回',
|
||||
label: '退回'
|
||||
},
|
||||
'submit': {
|
||||
title: '提交审核',
|
||||
label: '提交审核'
|
||||
}
|
||||
};
|
||||
const getTitleAndLabel = (typeKey, propertiesType) => {
|
||||
const mapping = typeMapping[typeKey];
|
||||
if (typeof mapping === 'function') return mapping(propertiesType);
|
||||
return mapping || {
|
||||
title: '',
|
||||
label: ''
|
||||
};
|
||||
};
|
||||
const {
|
||||
title,
|
||||
label
|
||||
} = getTitleAndLabel(type, propertiesType);
|
||||
this.title = title;
|
||||
this.label = label;
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.title
|
||||
});
|
||||
},
|
||||
changeUserSelect(e) {
|
||||
this.dataForm.handleIds = e.join()
|
||||
},
|
||||
branchChange(e, list) {
|
||||
this.dataForm.branchList = e;
|
||||
this.candidateList = []
|
||||
this.init();
|
||||
},
|
||||
openSelect(item) {
|
||||
item.formData = this.config.formData;
|
||||
item.taskId = this.config.operatorId;
|
||||
item.selectList = item.selectList || [];
|
||||
item.candidateList = JSON.stringify(this.candidateList);
|
||||
item.delegateUser = this.config.delegateUser
|
||||
uni.navigateTo({
|
||||
url: "/pages/workFlow/candiDateUserSelect/index?data=" +
|
||||
encodeURIComponent(JSON.stringify(item)),
|
||||
});
|
||||
},
|
||||
selectConfirm(data, nodeCode) {
|
||||
let users = [];
|
||||
const item = this.candidateList.filter(o => o.nodeCode == nodeCode)[0] || {}
|
||||
item.value = data.map(o => o.id) || []
|
||||
item.fullName = (data.map(o => o.fullName) || []).join(',') || ''
|
||||
item.selectList = data || []
|
||||
for (let i = 0; i < this.candidateList.length; i++) {
|
||||
for (let j = 0; j < data.length; j++) {
|
||||
if (data[j].nodeCode === this.candidateList[i].nodeCode) {
|
||||
users.push(data[j].id);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.$set(this.dataForm.candidateList, nodeCode, users);
|
||||
},
|
||||
getSelector() {
|
||||
getSelector().then(res => {
|
||||
this.commonList = res.data.list || []
|
||||
})
|
||||
},
|
||||
confirmCommonWord(e) {
|
||||
this.dataForm.handleOpinion = e.commonWordsText
|
||||
},
|
||||
handlePress(e) {
|
||||
this.$emit('handlePress')
|
||||
},
|
||||
addCommonWords() {
|
||||
let data = {
|
||||
commonWordsText: this.dataForm.handleOpinion,
|
||||
commonWordsType: 1
|
||||
}
|
||||
Create(data).then(res => {
|
||||
this.$u.toast(res.msg);
|
||||
})
|
||||
},
|
||||
freeApproverChange(e) {
|
||||
this.isCandidates = false;
|
||||
if (this.config.hasFreeApprover && e == 2 && this.candidateList.length) this.isCandidates = true;
|
||||
},
|
||||
confirm() {
|
||||
if (this.config.type === 'freeApprover') {
|
||||
this.dataForm.addSignParameter = {
|
||||
'addSignUserIdList': this.dataForm.addSignUserIdList,
|
||||
'auditRatio': this.dataForm.auditRatio,
|
||||
'counterSign': this.dataForm.counterSign,
|
||||
'addSignType': this.dataForm.addSignType
|
||||
}
|
||||
}
|
||||
if (!this.config.hasSign) delete this.dataForm.signImg
|
||||
this.dataForm.copyIds = Array.isArray(this.copyIds) && this.copyIds.length && this.copyIds.join()
|
||||
if (this.config.backType !== 3) this.dataForm.backType = this.config.backType
|
||||
let data = {
|
||||
...this.dataForm,
|
||||
eventType: ['auditRecall', 'launchRecall'].includes(this.config.type) ? 'recall' : this.config
|
||||
.type,
|
||||
approvalField: this.config.approvalField
|
||||
}
|
||||
if (this.isCandidates || this.isCandidate) {
|
||||
let candidateList = {};
|
||||
for (let i = 0; i < this.candidateList.length; i++) {
|
||||
let item = this.candidateList[i]
|
||||
if (!item.selected && !item.value?.length) return this.$u.toast('候选人不能为空')
|
||||
candidateList[item.nodeCode] = item.value || [];
|
||||
}
|
||||
data.candidateList = candidateList;
|
||||
}
|
||||
this.$refs.dataForm.validate(valid => {
|
||||
if (valid) {
|
||||
uni.$emit('operate', data)
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 500)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
height: 100%;
|
||||
background-color: #fff !important;
|
||||
}
|
||||
|
||||
::v-deep .u-form-item--left {
|
||||
align-items: flex-start !important;
|
||||
}
|
||||
|
||||
::v-deep .u-form-item {
|
||||
line-height: 1.5rem !important;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
::v-deep .u-input--border {
|
||||
border: 1rpx solid #f5f5f5 !important;
|
||||
}
|
||||
|
||||
.buttom-btn-left-inner {
|
||||
width: 50% !important;
|
||||
}
|
||||
|
||||
.free-box {
|
||||
width: 100%;
|
||||
|
||||
.free-box-txt {
|
||||
text-align: end;
|
||||
}
|
||||
}
|
||||
|
||||
.flow-popup-content {
|
||||
padding-bottom: 88rpx;
|
||||
|
||||
::v-deep .u-form {
|
||||
.content {
|
||||
.u-form-item {
|
||||
.u-form-item__body {
|
||||
.u-form-item--left {
|
||||
// align-items: center !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.signature-box {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0 20rpx;
|
||||
|
||||
.back-item {
|
||||
.back-item-inner {
|
||||
justify-content: end;
|
||||
width: 100%;
|
||||
|
||||
.selectNode {
|
||||
width: 100%;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.head-title {
|
||||
height: 80rpx;
|
||||
justify-content: space-between;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.uploadFile {
|
||||
width: 100%;
|
||||
padding-bottom: 8rpx;
|
||||
border-top: 1rpx solid #fbfbfc;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
84
pages/workFlow/operate/revoke.vue
Normal file
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<view class="flow-popup-content">
|
||||
<u-form ref="dataForm" :model="dataForm" :label-width="150" :errorType="['toast']">
|
||||
<view class="content">
|
||||
<u-form-item label="撤销原因">
|
||||
<HandleOpinion v-model="dataForm.handleOpinion" :showCommon="false"></HandleOpinion>
|
||||
</u-form-item>
|
||||
</view>
|
||||
</u-form>
|
||||
<view class="flowBefore-actions">
|
||||
<view class="u-flex-col buttom-btn-left-inner" @click.stop="jnpf.goBack()">
|
||||
<u-icon name="icon-ym" size="24" custom-prefix="icon-ym icon-ym-add-cancel"></u-icon>
|
||||
<text>取消</text>
|
||||
</view>
|
||||
<u-button class="buttom-btn" type="primary" @click="confirm('confirm')">确定
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import HandleOpinion from './components/HandleOpinion.vue'
|
||||
import {
|
||||
getSelector,
|
||||
Create
|
||||
} from '@/api/commonWords'
|
||||
export default {
|
||||
components: {
|
||||
HandleOpinion
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dataForm: {
|
||||
handleOpinion: ""
|
||||
},
|
||||
config: {}
|
||||
};
|
||||
},
|
||||
onLoad(data) {
|
||||
try {
|
||||
this.config = JSON.parse(decodeURIComponent(data.config));
|
||||
} catch {
|
||||
this.config = JSON.parse(data.config);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
confirm() {
|
||||
let data = {
|
||||
...this.dataForm,
|
||||
eventType: this.config.type
|
||||
}
|
||||
uni.$emit('operate', data)
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
height: 100%;
|
||||
background-color: #fff !important;
|
||||
}
|
||||
|
||||
::v-deep .u-form-item--left {
|
||||
align-items: flex-start !important;
|
||||
}
|
||||
|
||||
.buttom-btn-left-inner {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.flow-popup-content {
|
||||
.signature-box {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
76
pages/workFlow/scanForm/index.vue
Normal file
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<view class="dynamicModel-v">
|
||||
<view class="jnpf-wrap jnpf-wrap-form" v-if="isShow">
|
||||
<childForm ref="child" :config="config" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import childForm from '@/pages/workFlow/flowBefore/form'
|
||||
import {
|
||||
getConfigData
|
||||
} from '@/api/apply/visualDev'
|
||||
import {
|
||||
getStartFormInfo
|
||||
} from '@/api/workFlow/workFlowForm'
|
||||
export default {
|
||||
name: 'scanForm',
|
||||
components: {
|
||||
childForm
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
config: {},
|
||||
formConf: {},
|
||||
isShow: false,
|
||||
formInfo: {},
|
||||
}
|
||||
},
|
||||
onLoad(data) {
|
||||
let obj = JSON.parse(data.config)
|
||||
this.initData(obj)
|
||||
},
|
||||
methods: {
|
||||
initData(data) {
|
||||
if (data.previewType === 'initiationForm') {
|
||||
uni.setNavigationBarTitle({
|
||||
title: data.title
|
||||
})
|
||||
getStartFormInfo(data.taskId).then(res => {
|
||||
this.formInfo = res.data.formInfo;
|
||||
this.config = {
|
||||
...data,
|
||||
formData: res.data.formData || {},
|
||||
formConf: this.formInfo.formData,
|
||||
readonly: true,
|
||||
formType: 1
|
||||
}
|
||||
this.isShow = true
|
||||
})
|
||||
} else {
|
||||
getConfigData(data.id, {
|
||||
type: data.previewType
|
||||
}).then(res => {
|
||||
if (!res.data || !res.data.formData) return
|
||||
this.config = {
|
||||
formEnCode: data.enCode,
|
||||
flowId: res.data.id,
|
||||
formConf: res.data.formData
|
||||
}
|
||||
this.isShow = true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f0f2f6;
|
||||
}
|
||||
|
||||
.dynamicModel-v {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
546
pages/workFlow/schedule/calendar/calendar.js
Normal file
@@ -0,0 +1,546 @@
|
||||
/**
|
||||
* @1900-2100区间内的公历、农历互转
|
||||
* @charset UTF-8
|
||||
* @github https://github.com/jjonline/calendar.js
|
||||
* @Author Jea杨(JJonline@JJonline.Cn)
|
||||
* @Time 2014-7-21
|
||||
* @Time 2016-8-13 Fixed 2033hex、Attribution Annals
|
||||
* @Time 2016-9-25 Fixed lunar LeapMonth Param Bug
|
||||
* @Time 2017-7-24 Fixed use getTerm Func Param Error.use solar year,NOT lunar year
|
||||
* @Version 1.0.3
|
||||
* @公历转农历:calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0]
|
||||
* @农历转公历:calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0]
|
||||
*/
|
||||
/* eslint-disable */
|
||||
var calendar = {
|
||||
|
||||
/**
|
||||
* 农历1900-2100的润大小信息表
|
||||
* @Array Of Property
|
||||
* @return Hex
|
||||
*/
|
||||
lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, // 1900-1909
|
||||
0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, // 1910-1919
|
||||
0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, // 1920-1929
|
||||
0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, // 1930-1939
|
||||
0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, // 1940-1949
|
||||
0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, // 1950-1959
|
||||
0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, // 1960-1969
|
||||
0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, // 1970-1979
|
||||
0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, // 1980-1989
|
||||
0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, // 1990-1999
|
||||
0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, // 2000-2009
|
||||
0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, // 2010-2019
|
||||
0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, // 2020-2029
|
||||
0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, // 2030-2039
|
||||
0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, // 2040-2049
|
||||
/** Add By JJonline@JJonline.Cn**/
|
||||
0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, // 2050-2059
|
||||
0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, // 2060-2069
|
||||
0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, // 2070-2079
|
||||
0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, // 2080-2089
|
||||
0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, // 2090-2099
|
||||
0x0d520], // 2100
|
||||
|
||||
/**
|
||||
* 公历每个月份的天数普通表
|
||||
* @Array Of Property
|
||||
* @return Number
|
||||
*/
|
||||
solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
|
||||
|
||||
/**
|
||||
* 天干地支之天干速查表
|
||||
* @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"]
|
||||
* @return Cn string
|
||||
*/
|
||||
Gan: ['\u7532', '\u4e59', '\u4e19', '\u4e01', '\u620a', '\u5df1', '\u5e9a', '\u8f9b', '\u58ec', '\u7678'],
|
||||
|
||||
/**
|
||||
* 天干地支之地支速查表
|
||||
* @Array Of Property
|
||||
* @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"]
|
||||
* @return Cn string
|
||||
*/
|
||||
Zhi: ['\u5b50', '\u4e11', '\u5bc5', '\u536f', '\u8fb0', '\u5df3', '\u5348', '\u672a', '\u7533', '\u9149', '\u620c', '\u4ea5'],
|
||||
|
||||
/**
|
||||
* 天干地支之地支速查表<=>生肖
|
||||
* @Array Of Property
|
||||
* @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"]
|
||||
* @return Cn string
|
||||
*/
|
||||
Animals: ['\u9f20', '\u725b', '\u864e', '\u5154', '\u9f99', '\u86c7', '\u9a6c', '\u7f8a', '\u7334', '\u9e21', '\u72d7', '\u732a'],
|
||||
|
||||
/**
|
||||
* 24节气速查表
|
||||
* @Array Of Property
|
||||
* @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"]
|
||||
* @return Cn string
|
||||
*/
|
||||
solarTerm: ['\u5c0f\u5bd2', '\u5927\u5bd2', '\u7acb\u6625', '\u96e8\u6c34', '\u60ca\u86f0', '\u6625\u5206', '\u6e05\u660e', '\u8c37\u96e8', '\u7acb\u590f', '\u5c0f\u6ee1', '\u8292\u79cd', '\u590f\u81f3', '\u5c0f\u6691', '\u5927\u6691', '\u7acb\u79cb', '\u5904\u6691', '\u767d\u9732', '\u79cb\u5206', '\u5bd2\u9732', '\u971c\u964d', '\u7acb\u51ac', '\u5c0f\u96ea', '\u5927\u96ea', '\u51ac\u81f3'],
|
||||
|
||||
/**
|
||||
* 1900-2100各年的24节气日期速查表
|
||||
* @Array Of Property
|
||||
* @return 0x string For splice
|
||||
*/
|
||||
sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f',
|
||||
'97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
|
||||
'97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa',
|
||||
'97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f',
|
||||
'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f',
|
||||
'97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa',
|
||||
'97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2',
|
||||
'9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f',
|
||||
'97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e',
|
||||
'97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
|
||||
'97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722',
|
||||
'9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f',
|
||||
'97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
|
||||
'97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
|
||||
'97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722',
|
||||
'9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f',
|
||||
'97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
|
||||
'97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
|
||||
'9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722',
|
||||
'7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
|
||||
'97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
|
||||
'97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
|
||||
'9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722',
|
||||
'7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
|
||||
'97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
|
||||
'97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
|
||||
'9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722',
|
||||
'7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
|
||||
'97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
|
||||
'9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
|
||||
'7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
|
||||
'7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
|
||||
'97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
|
||||
'9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
|
||||
'7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
|
||||
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
|
||||
'97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
|
||||
'9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
|
||||
'7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721',
|
||||
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2',
|
||||
'977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
|
||||
'7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
|
||||
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd',
|
||||
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
|
||||
'977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
|
||||
'7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
|
||||
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd',
|
||||
'7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
|
||||
'977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
|
||||
'7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721',
|
||||
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5',
|
||||
'7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722',
|
||||
'7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
|
||||
'7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
|
||||
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35',
|
||||
'7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
|
||||
'7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721',
|
||||
'7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd',
|
||||
'7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35',
|
||||
'7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
|
||||
'7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721',
|
||||
'7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5',
|
||||
'7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35',
|
||||
'665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
|
||||
'7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
|
||||
'7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35',
|
||||
'7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722'],
|
||||
|
||||
/**
|
||||
* 数字转中文速查表
|
||||
* @Array Of Property
|
||||
* @trans ['日','一','二','三','四','五','六','七','八','九','十']
|
||||
* @return Cn string
|
||||
*/
|
||||
nStr1: ['\u65e5', '\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341'],
|
||||
|
||||
/**
|
||||
* 日期转农历称呼速查表
|
||||
* @Array Of Property
|
||||
* @trans ['初','十','廿','卅']
|
||||
* @return Cn string
|
||||
*/
|
||||
nStr2: ['\u521d', '\u5341', '\u5eff', '\u5345'],
|
||||
|
||||
/**
|
||||
* 月份转农历称呼速查表
|
||||
* @Array Of Property
|
||||
* @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊']
|
||||
* @return Cn string
|
||||
*/
|
||||
nStr3: ['\u6b63', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341', '\u51ac', '\u814a'],
|
||||
|
||||
/**
|
||||
* 返回农历y年一整年的总天数
|
||||
* @param lunar Year
|
||||
* @return Number
|
||||
* @eg:var count = calendar.lYearDays(1987) ;//count=387
|
||||
*/
|
||||
lYearDays: function (y) {
|
||||
var i; var sum = 348
|
||||
for (i = 0x8000; i > 0x8; i >>= 1) { sum += (this.lunarInfo[y - 1900] & i) ? 1 : 0 }
|
||||
return (sum + this.leapDays(y))
|
||||
},
|
||||
|
||||
/**
|
||||
* 返回农历y年闰月是哪个月;若y年没有闰月 则返回0
|
||||
* @param lunar Year
|
||||
* @return Number (0-12)
|
||||
* @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6
|
||||
*/
|
||||
leapMonth: function (y) { // 闰字编码 \u95f0
|
||||
return (this.lunarInfo[y - 1900] & 0xf)
|
||||
},
|
||||
|
||||
/**
|
||||
* 返回农历y年闰月的天数 若该年没有闰月则返回0
|
||||
* @param lunar Year
|
||||
* @return Number (0、29、30)
|
||||
* @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29
|
||||
*/
|
||||
leapDays: function (y) {
|
||||
if (this.leapMonth(y)) {
|
||||
return ((this.lunarInfo[y - 1900] & 0x10000) ? 30 : 29)
|
||||
}
|
||||
return (0)
|
||||
},
|
||||
|
||||
/**
|
||||
* 返回农历y年m月(非闰月)的总天数,计算m为闰月时的天数请使用leapDays方法
|
||||
* @param lunar Year
|
||||
* @return Number (-1、29、30)
|
||||
* @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29
|
||||
*/
|
||||
monthDays: function (y, m) {
|
||||
if (m > 12 || m < 1) { return -1 }// 月份参数从1至12,参数错误返回-1
|
||||
return ((this.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29)
|
||||
},
|
||||
|
||||
/**
|
||||
* 返回公历(!)y年m月的天数
|
||||
* @param solar Year
|
||||
* @return Number (-1、28、29、30、31)
|
||||
* @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30
|
||||
*/
|
||||
solarDays: function (y, m) {
|
||||
if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1
|
||||
var ms = m - 1
|
||||
if (ms == 1) { // 2月份的闰平规律测算后确认返回28或29
|
||||
return (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) ? 29 : 28)
|
||||
} else {
|
||||
return (this.solarMonth[ms])
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 农历年份转换为干支纪年
|
||||
* @param lYear 农历年的年份数
|
||||
* @return Cn string
|
||||
*/
|
||||
toGanZhiYear: function (lYear) {
|
||||
var ganKey = (lYear - 3) % 10
|
||||
var zhiKey = (lYear - 3) % 12
|
||||
if (ganKey == 0) ganKey = 10// 如果余数为0则为最后一个天干
|
||||
if (zhiKey == 0) zhiKey = 12// 如果余数为0则为最后一个地支
|
||||
return this.Gan[ganKey - 1] + this.Zhi[zhiKey - 1]
|
||||
},
|
||||
|
||||
/**
|
||||
* 公历月、日判断所属星座
|
||||
* @param cMonth [description]
|
||||
* @param cDay [description]
|
||||
* @return Cn string
|
||||
*/
|
||||
toAstro: function (cMonth, cDay) {
|
||||
var s = '\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf'
|
||||
var arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22]
|
||||
return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + '\u5ea7'// 座
|
||||
},
|
||||
|
||||
/**
|
||||
* 传入offset偏移量返回干支
|
||||
* @param offset 相对甲子的偏移量
|
||||
* @return Cn string
|
||||
*/
|
||||
toGanZhi: function (offset) {
|
||||
return this.Gan[offset % 10] + this.Zhi[offset % 12]
|
||||
},
|
||||
|
||||
/**
|
||||
* 传入公历(!)y年获得该年第n个节气的公历日期
|
||||
* @param y公历年(1900-2100);n二十四节气中的第几个节气(1~24);从n=1(小寒)算起
|
||||
* @return day Number
|
||||
* @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春
|
||||
*/
|
||||
getTerm: function (y, n) {
|
||||
if (y < 1900 || y > 2100) { return -1 }
|
||||
if (n < 1 || n > 24) { return -1 }
|
||||
var _table = this.sTermInfo[y - 1900]
|
||||
var _info = [
|
||||
parseInt('0x' + _table.substr(0, 5)).toString(),
|
||||
parseInt('0x' + _table.substr(5, 5)).toString(),
|
||||
parseInt('0x' + _table.substr(10, 5)).toString(),
|
||||
parseInt('0x' + _table.substr(15, 5)).toString(),
|
||||
parseInt('0x' + _table.substr(20, 5)).toString(),
|
||||
parseInt('0x' + _table.substr(25, 5)).toString()
|
||||
]
|
||||
var _calday = [
|
||||
_info[0].substr(0, 1),
|
||||
_info[0].substr(1, 2),
|
||||
_info[0].substr(3, 1),
|
||||
_info[0].substr(4, 2),
|
||||
|
||||
_info[1].substr(0, 1),
|
||||
_info[1].substr(1, 2),
|
||||
_info[1].substr(3, 1),
|
||||
_info[1].substr(4, 2),
|
||||
|
||||
_info[2].substr(0, 1),
|
||||
_info[2].substr(1, 2),
|
||||
_info[2].substr(3, 1),
|
||||
_info[2].substr(4, 2),
|
||||
|
||||
_info[3].substr(0, 1),
|
||||
_info[3].substr(1, 2),
|
||||
_info[3].substr(3, 1),
|
||||
_info[3].substr(4, 2),
|
||||
|
||||
_info[4].substr(0, 1),
|
||||
_info[4].substr(1, 2),
|
||||
_info[4].substr(3, 1),
|
||||
_info[4].substr(4, 2),
|
||||
|
||||
_info[5].substr(0, 1),
|
||||
_info[5].substr(1, 2),
|
||||
_info[5].substr(3, 1),
|
||||
_info[5].substr(4, 2)
|
||||
]
|
||||
return parseInt(_calday[n - 1])
|
||||
},
|
||||
|
||||
/**
|
||||
* 传入农历数字月份返回汉语通俗表示法
|
||||
* @param lunar month
|
||||
* @return Cn string
|
||||
* @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月'
|
||||
*/
|
||||
toChinaMonth: function (m) { // 月 => \u6708
|
||||
if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1
|
||||
var s = this.nStr3[m - 1]
|
||||
s += '\u6708'// 加上月字
|
||||
return s
|
||||
},
|
||||
|
||||
/**
|
||||
* 传入农历日期数字返回汉字表示法
|
||||
* @param lunar day
|
||||
* @return Cn string
|
||||
* @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一'
|
||||
*/
|
||||
toChinaDay: function (d) { // 日 => \u65e5
|
||||
var s
|
||||
switch (d) {
|
||||
case 10:
|
||||
s = '\u521d\u5341'; break
|
||||
case 20:
|
||||
s = '\u4e8c\u5341'; break
|
||||
break
|
||||
case 30:
|
||||
s = '\u4e09\u5341'; break
|
||||
break
|
||||
default :
|
||||
s = this.nStr2[Math.floor(d / 10)]
|
||||
s += this.nStr1[d % 10]
|
||||
}
|
||||
return (s)
|
||||
},
|
||||
|
||||
/**
|
||||
* 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春”
|
||||
* @param y year
|
||||
* @return Cn string
|
||||
* @eg:var animal = calendar.getAnimal(1987) ;//animal='兔'
|
||||
*/
|
||||
getAnimal: function (y) {
|
||||
return this.Animals[(y - 4) % 12]
|
||||
},
|
||||
|
||||
/**
|
||||
* 传入阳历年月日获得详细的公历、农历object信息 <=>JSON
|
||||
* @param y solar year
|
||||
* @param m solar month
|
||||
* @param d solar day
|
||||
* @return JSON object
|
||||
* @eg:console.log(calendar.solar2lunar(1987,11,01));
|
||||
*/
|
||||
solar2lunar: function (y, m, d) { // 参数区间1900.1.31~2100.12.31
|
||||
// 年份限定、上限
|
||||
if (y < 1900 || y > 2100) {
|
||||
return -1// undefined转换为数字变为NaN
|
||||
}
|
||||
// 公历传参最下限
|
||||
if (y == 1900 && m == 1 && d < 31) {
|
||||
return -1
|
||||
}
|
||||
// 未传参 获得当天
|
||||
if (!y) {
|
||||
var objDate = new Date()
|
||||
} else {
|
||||
var objDate = new Date(y, parseInt(m) - 1, d)
|
||||
}
|
||||
var i; var leap = 0; var temp = 0
|
||||
// 修正ymd参数
|
||||
var y = objDate.getFullYear()
|
||||
var m = objDate.getMonth() + 1
|
||||
var d = objDate.getDate()
|
||||
var offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0, 31)) / 86400000
|
||||
for (i = 1900; i < 2101 && offset > 0; i++) {
|
||||
temp = this.lYearDays(i)
|
||||
offset -= temp
|
||||
}
|
||||
if (offset < 0) {
|
||||
offset += temp; i--
|
||||
}
|
||||
|
||||
// 是否今天
|
||||
var isTodayObj = new Date()
|
||||
var isToday = false
|
||||
if (isTodayObj.getFullYear() == y && isTodayObj.getMonth() + 1 == m && isTodayObj.getDate() == d) {
|
||||
isToday = true
|
||||
}
|
||||
// 星期几
|
||||
var nWeek = objDate.getDay()
|
||||
var cWeek = this.nStr1[nWeek]
|
||||
// 数字表示周几顺应天朝周一开始的惯例
|
||||
if (nWeek == 0) {
|
||||
nWeek = 7
|
||||
}
|
||||
// 农历年
|
||||
var year = i
|
||||
var leap = this.leapMonth(i) // 闰哪个月
|
||||
var isLeap = false
|
||||
|
||||
// 效验闰月
|
||||
for (i = 1; i < 13 && offset > 0; i++) {
|
||||
// 闰月
|
||||
if (leap > 0 && i == (leap + 1) && isLeap == false) {
|
||||
--i
|
||||
isLeap = true; temp = this.leapDays(year) // 计算农历闰月天数
|
||||
} else {
|
||||
temp = this.monthDays(year, i)// 计算农历普通月天数
|
||||
}
|
||||
// 解除闰月
|
||||
if (isLeap == true && i == (leap + 1)) { isLeap = false }
|
||||
offset -= temp
|
||||
}
|
||||
// 闰月导致数组下标重叠取反
|
||||
if (offset == 0 && leap > 0 && i == leap + 1) {
|
||||
if (isLeap) {
|
||||
isLeap = false
|
||||
} else {
|
||||
isLeap = true; --i
|
||||
}
|
||||
}
|
||||
if (offset < 0) {
|
||||
offset += temp; --i
|
||||
}
|
||||
// 农历月
|
||||
var month = i
|
||||
// 农历日
|
||||
var day = offset + 1
|
||||
// 天干地支处理
|
||||
var sm = m - 1
|
||||
var gzY = this.toGanZhiYear(year)
|
||||
|
||||
// 当月的两个节气
|
||||
// bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year`
|
||||
var firstNode = this.getTerm(y, (m * 2 - 1))// 返回当月「节」为几日开始
|
||||
var secondNode = this.getTerm(y, (m * 2))// 返回当月「节」为几日开始
|
||||
|
||||
// 依据12节气修正干支月
|
||||
var gzM = this.toGanZhi((y - 1900) * 12 + m + 11)
|
||||
if (d >= firstNode) {
|
||||
gzM = this.toGanZhi((y - 1900) * 12 + m + 12)
|
||||
}
|
||||
|
||||
// 传入的日期的节气与否
|
||||
var isTerm = false
|
||||
var Term = null
|
||||
if (firstNode == d) {
|
||||
isTerm = true
|
||||
Term = this.solarTerm[m * 2 - 2]
|
||||
}
|
||||
if (secondNode == d) {
|
||||
isTerm = true
|
||||
Term = this.solarTerm[m * 2 - 1]
|
||||
}
|
||||
// 日柱 当月一日与 1900/1/1 相差天数
|
||||
var dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10
|
||||
var gzD = this.toGanZhi(dayCyclical + d - 1)
|
||||
// 该日期所属的星座
|
||||
var astro = this.toAstro(m, d)
|
||||
|
||||
return { 'lYear': year, 'lMonth': month, 'lDay': day, 'Animal': this.getAnimal(year), 'IMonthCn': (isLeap ? '\u95f0' : '') + this.toChinaMonth(month), 'IDayCn': this.toChinaDay(day), 'cYear': y, 'cMonth': m, 'cDay': d, 'gzYear': gzY, 'gzMonth': gzM, 'gzDay': gzD, 'isToday': isToday, 'isLeap': isLeap, 'nWeek': nWeek, 'ncWeek': '\u661f\u671f' + cWeek, 'isTerm': isTerm, 'Term': Term, 'astro': astro }
|
||||
},
|
||||
|
||||
/**
|
||||
* 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON
|
||||
* @param y lunar year
|
||||
* @param m lunar month
|
||||
* @param d lunar day
|
||||
* @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可]
|
||||
* @return JSON object
|
||||
* @eg:console.log(calendar.lunar2solar(1987,9,10));
|
||||
*/
|
||||
lunar2solar: function (y, m, d, isLeapMonth) { // 参数区间1900.1.31~2100.12.1
|
||||
var isLeapMonth = !!isLeapMonth
|
||||
var leapOffset = 0
|
||||
var leapMonth = this.leapMonth(y)
|
||||
var leapDay = this.leapDays(y)
|
||||
if (isLeapMonth && (leapMonth != m)) { return -1 }// 传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同
|
||||
if (y == 2100 && m == 12 && d > 1 || y == 1900 && m == 1 && d < 31) { return -1 }// 超出了最大极限值
|
||||
var day = this.monthDays(y, m)
|
||||
var _day = day
|
||||
// bugFix 2016-9-25
|
||||
// if month is leap, _day use leapDays method
|
||||
if (isLeapMonth) {
|
||||
_day = this.leapDays(y, m)
|
||||
}
|
||||
if (y < 1900 || y > 2100 || d > _day) { return -1 }// 参数合法性效验
|
||||
|
||||
// 计算农历的时间差
|
||||
var offset = 0
|
||||
for (var i = 1900; i < y; i++) {
|
||||
offset += this.lYearDays(i)
|
||||
}
|
||||
var leap = 0; var isAdd = false
|
||||
for (var i = 1; i < m; i++) {
|
||||
leap = this.leapMonth(y)
|
||||
if (!isAdd) { // 处理闰月
|
||||
if (leap <= i && leap > 0) {
|
||||
offset += this.leapDays(y); isAdd = true
|
||||
}
|
||||
}
|
||||
offset += this.monthDays(y, i)
|
||||
}
|
||||
// 转换闰月农历 需补充该年闰月的前一个月的时差
|
||||
if (isLeapMonth) { offset += day }
|
||||
// 1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点)
|
||||
var stmap = Date.UTC(1900, 1, 30, 0, 0, 0)
|
||||
var calObj = new Date((offset + d - 31) * 86400000 + stmap)
|
||||
var cY = calObj.getUTCFullYear()
|
||||
var cM = calObj.getUTCMonth() + 1
|
||||
var cD = calObj.getUTCDate()
|
||||
|
||||
return this.solar2lunar(cY, cM, cD)
|
||||
}
|
||||
}
|
||||
|
||||
export default calendar
|
||||
12
pages/workFlow/schedule/calendar/i18n/en.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"uni-calender.ok": "ok",
|
||||
"uni-calender.cancel": "cancel",
|
||||
"uni-calender.today": "today",
|
||||
"uni-calender.MON": "MON",
|
||||
"uni-calender.TUE": "TUE",
|
||||
"uni-calender.WED": "WED",
|
||||
"uni-calender.THU": "THU",
|
||||
"uni-calender.FRI": "FRI",
|
||||
"uni-calender.SAT": "SAT",
|
||||
"uni-calender.SUN": "SUN"
|
||||
}
|
||||
8
pages/workFlow/schedule/calendar/i18n/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import en from './en.json'
|
||||
import zhHans from './zh-Hans.json'
|
||||
import zhHant from './zh-Hant.json'
|
||||
export default {
|
||||
en,
|
||||
'zh-Hans': zhHans,
|
||||
'zh-Hant': zhHant
|
||||
}
|
||||
12
pages/workFlow/schedule/calendar/i18n/zh-Hans.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"uni-calender.ok": "确定",
|
||||
"uni-calender.cancel": "取消",
|
||||
"uni-calender.today": "今日",
|
||||
"uni-calender.SUN": "日",
|
||||
"uni-calender.MON": "一",
|
||||
"uni-calender.TUE": "二",
|
||||
"uni-calender.WED": "三",
|
||||
"uni-calender.THU": "四",
|
||||
"uni-calender.FRI": "五",
|
||||
"uni-calender.SAT": "六"
|
||||
}
|
||||
12
pages/workFlow/schedule/calendar/i18n/zh-Hant.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"uni-calender.ok": "確定",
|
||||
"uni-calender.cancel": "取消",
|
||||
"uni-calender.today": "今日",
|
||||
"uni-calender.SUN": "日",
|
||||
"uni-calender.MON": "一",
|
||||
"uni-calender.TUE": "二",
|
||||
"uni-calender.WED": "三",
|
||||
"uni-calender.THU": "四",
|
||||
"uni-calender.FRI": "五",
|
||||
"uni-calender.SAT": "六"
|
||||
}
|
||||
194
pages/workFlow/schedule/calendar/uni-calendar-item.vue
Normal file
@@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<view class="uni-calendar-item__weeks-box" :class="{
|
||||
'uni-calendar-item--disable':weeks.disable,
|
||||
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
|
||||
'uni-calendar-item--checked':(calendar.fullDate === weeks.fullDate && !weeks.isDay) ,
|
||||
'uni-calendar-item--before-checked':weeks.beforeMultiple,
|
||||
'uni-calendar-item--multiple': weeks.multiple,
|
||||
'uni-calendar-item--after-checked':weeks.afterMultiple,
|
||||
}" @click="choiceDate(weeks)">
|
||||
<view class="uni-calendar-item__weeks-box-item">
|
||||
<text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
|
||||
<text class="uni-calendar-item__weeks-box-text" :class="{
|
||||
'uni-calendar-item--isDay-text': weeks.isDay,
|
||||
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
|
||||
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
|
||||
'uni-calendar-item--before-checked':weeks.beforeMultiple,
|
||||
'uni-calendar-item--multiple': weeks.multiple,
|
||||
'uni-calendar-item--after-checked':weeks.afterMultiple,
|
||||
'uni-calendar-item--disable':weeks.disable,
|
||||
}">{{weeks.date}}</text>
|
||||
<text v-if="!lunar&&!weeks.extraInfo && weeks.isDay" class="uni-calendar-item__weeks-lunar-text" :class="{
|
||||
'uni-calendar-item--isDay-text':weeks.isDay,
|
||||
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
|
||||
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
|
||||
'uni-calendar-item--before-checked':weeks.beforeMultiple,
|
||||
'uni-calendar-item--multiple': weeks.multiple,
|
||||
'uni-calendar-item--after-checked':weeks.afterMultiple,
|
||||
}">{{todayText}}</text>
|
||||
<text v-if="lunar" class="uni-calendar-item__weeks-lunar-text" :class="{
|
||||
'uni-calendar-item--isDay-text':weeks.isDay,
|
||||
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
|
||||
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
|
||||
'uni-calendar-item--before-checked':weeks.beforeMultiple,
|
||||
'uni-calendar-item--multiple': weeks.multiple,
|
||||
'uni-calendar-item--after-checked':weeks.afterMultiple,
|
||||
'uni-calendar-item--disable':weeks.disable,
|
||||
}">{{weeks.isDay ? todayText : (weeks.lunar.IDayCn === '初一'?weeks.lunar.IMonthCn:weeks.lunar.IDayCn)}}</text>
|
||||
<text v-if="weeks.extraInfo&&weeks.extraInfo.info" class="uni-calendar-item__weeks-lunar-text" :class="{
|
||||
'uni-calendar-item--extra':weeks.extraInfo.info,
|
||||
'uni-calendar-item--isDay-text':weeks.isDay,
|
||||
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
|
||||
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
|
||||
'uni-calendar-item--before-checked':weeks.beforeMultiple,
|
||||
'uni-calendar-item--multiple': weeks.multiple,
|
||||
'uni-calendar-item--after-checked':weeks.afterMultiple,
|
||||
'uni-calendar-item--disable':weeks.disable,
|
||||
}">{{weeks.extraInfo.info}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
initVueI18n
|
||||
} from '@dcloudio/uni-i18n'
|
||||
import i18nMessages from './i18n/index.js'
|
||||
const {
|
||||
t
|
||||
} = initVueI18n(i18nMessages)
|
||||
|
||||
export default {
|
||||
emits: ['change'],
|
||||
props: {
|
||||
weeks: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
calendar: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
selected: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
},
|
||||
lunar: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
todayText() {
|
||||
return t("uni-calender.today")
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
choiceDate(weeks) {
|
||||
this.$emit('change', weeks)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$uni-font-size-base: 14px;
|
||||
$uni-text-color: #333;
|
||||
$uni-font-size-sm: 12px;
|
||||
$uni-color-error: #e43d33;
|
||||
$uni-opacity-disabled: 0.3;
|
||||
$uni-text-color-disable: #c0c0c0;
|
||||
$uni-primary: #2979ff !default;
|
||||
|
||||
.uni-calendar-item__weeks-box {
|
||||
flex: 1;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.uni-calendar-item__weeks-box-text {
|
||||
font-size: 16px;
|
||||
color: $uni-text-color;
|
||||
line-height: 36rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.uni-calendar-item__weeks-lunar-text {
|
||||
font-size: $uni-font-size-sm;
|
||||
color: $uni-text-color;
|
||||
}
|
||||
|
||||
.uni-calendar-item__weeks-box-item {
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
}
|
||||
|
||||
.uni-calendar-item__weeks-box-circle {
|
||||
position: absolute;
|
||||
right: 42rpx;
|
||||
bottom: 1rpx;
|
||||
font-size: 20rpx;
|
||||
line-height: 1;
|
||||
display: block;
|
||||
padding: 8rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #FE5146;
|
||||
|
||||
}
|
||||
|
||||
.uni-calendar-item--disable {
|
||||
background-color: rgba(249, 249, 249, $uni-opacity-disabled);
|
||||
color: $uni-text-color-disable;
|
||||
}
|
||||
|
||||
.uni-calendar-item--isDay-text {
|
||||
color: $uni-color-primary;
|
||||
}
|
||||
|
||||
.uni-calendar-item--isDay {
|
||||
background-color: $uni-color-primary;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.uni-calendar-item--extra {
|
||||
color: $uni-color-error;
|
||||
}
|
||||
|
||||
.uni-calendar-item--checked {
|
||||
background-color: $uni-color-primary;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.uni-calendar-item--multiple {
|
||||
background-color: $uni-color-primary;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.uni-calendar-item--before-checked {
|
||||
background-color: #ff5a5f;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.uni-calendar-item--after-checked {
|
||||
background-color: #ff5a5f;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
579
pages/workFlow/schedule/calendar/uni-calendar.vue
Normal file
@@ -0,0 +1,579 @@
|
||||
<template>
|
||||
<view class="uni-calendar">
|
||||
<view v-if="!insert&&show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}"
|
||||
@click="clean"></view>
|
||||
<view v-if="insert || show" class="uni-calendar__content"
|
||||
:class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow}">
|
||||
<view v-if="!insert" class="uni-calendar__header uni-calendar--fixed-top">
|
||||
<view class="uni-calendar__header-btn-box" @click="close">
|
||||
<text class="uni-calendar__header-text uni-calendar--fixed-width">{{cancelText}}</text>
|
||||
</view>
|
||||
<view class="uni-calendar__header-btn-box" @click="confirm">
|
||||
<text class="uni-calendar__header-text uni-calendar--fixed-width">{{okText}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="uni-calendar__header">
|
||||
<view class="uni-calendar__header-btn-box" @click.stop="pre">
|
||||
<view class="uni-calendar__header-btn uni-calendar--left"></view>
|
||||
</view>
|
||||
<picker mode="date" :value="date" fields="month" @change="bindDateChange">
|
||||
<text
|
||||
class="uni-calendar__header-text">{{ (nowDate.year||'') + '年' +( nowDate.month||'') + '月'}}</text>
|
||||
</picker>
|
||||
<view class="uni-calendar__header-btn-box" @click.stop="next">
|
||||
<view class="uni-calendar__header-btn uni-calendar--right"></view>
|
||||
</view>
|
||||
<text class="uni-calendar__backtoday" @click="backToday">回到今天</text>
|
||||
|
||||
</view>
|
||||
<view class="uni-calendar__box">
|
||||
<view v-if="showMonth" class="uni-calendar__box-bg">
|
||||
<text class="uni-calendar__box-bg-text">{{nowDate.month}}</text>
|
||||
</view>
|
||||
<view class="uni-calendar__weeks">
|
||||
<view class="uni-calendar__weeks-day">
|
||||
<text class="uni-calendar__weeks-day-text">{{SUNText}}</text>
|
||||
</view>
|
||||
<view class="uni-calendar__weeks-day">
|
||||
<text class="uni-calendar__weeks-day-text">{{monText}}</text>
|
||||
</view>
|
||||
<view class="uni-calendar__weeks-day">
|
||||
<text class="uni-calendar__weeks-day-text">{{TUEText}}</text>
|
||||
</view>
|
||||
<view class="uni-calendar__weeks-day">
|
||||
<text class="uni-calendar__weeks-day-text">{{WEDText}}</text>
|
||||
</view>
|
||||
<view class="uni-calendar__weeks-day">
|
||||
<text class="uni-calendar__weeks-day-text">{{THUText}}</text>
|
||||
</view>
|
||||
<view class="uni-calendar__weeks-day">
|
||||
<text class="uni-calendar__weeks-day-text">{{FRIText}}</text>
|
||||
</view>
|
||||
<view class="uni-calendar__weeks-day">
|
||||
<text class="uni-calendar__weeks-day-text">{{SATText}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex">
|
||||
<view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex">
|
||||
<calendar-item class="uni-calendar-item--hook" :weeks="weeks" :calendar="calendar"
|
||||
:selected="selected" :lunar="lunar" @change="choiceDate"></calendar-item>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Calendar from './util.js';
|
||||
import CalendarItem from './uni-calendar-item.vue'
|
||||
|
||||
import {
|
||||
initVueI18n
|
||||
} from '@dcloudio/uni-i18n'
|
||||
import i18nMessages from './i18n/index.js'
|
||||
const {
|
||||
t
|
||||
} = initVueI18n(i18nMessages)
|
||||
|
||||
/**
|
||||
* Calendar 日历
|
||||
* @description 日历组件可以查看日期,选择任意范围内的日期,打点操作。常用场景如:酒店日期预订、火车机票选择购买日期、上下班打卡等
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=56
|
||||
* @property {String} date 自定义当前时间,默认为今天
|
||||
* @property {Boolean} lunar 显示农历
|
||||
* @property {String} startDate 日期选择范围-开始日期
|
||||
* @property {String} endDate 日期选择范围-结束日期
|
||||
* @property {Boolean} range 范围选择
|
||||
* @property {Boolean} insert = [true|false] 插入模式,默认为false
|
||||
* @value true 弹窗模式
|
||||
* @value false 插入模式
|
||||
* @property {Boolean} clearDate = [true|false] 弹窗模式是否清空上次选择内容
|
||||
* @property {Array} selected 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}]
|
||||
* @property {Boolean} showMonth 是否选择月份为背景
|
||||
* @event {Function} change 日期改变,`insert :ture` 时生效
|
||||
* @event {Function} confirm 确认选择`insert :false` 时生效
|
||||
* @event {Function} monthSwitch 切换月份时触发
|
||||
* @example <uni-calendar :insert="true":lunar="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
|
||||
*/
|
||||
export default {
|
||||
components: {
|
||||
CalendarItem
|
||||
},
|
||||
emits: ['close', 'confirm', 'change', 'monthSwitch', 'initdate'],
|
||||
props: {
|
||||
date: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
selected: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
lunar: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
startDate: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
endDate: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
range: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
insert: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
showMonth: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
clearDate: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
weeks: [],
|
||||
calendar: {},
|
||||
nowDate: '',
|
||||
aniMaskShow: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
/**
|
||||
* for i18n
|
||||
*/
|
||||
|
||||
okText() {
|
||||
return t("uni-calender.ok")
|
||||
},
|
||||
cancelText() {
|
||||
return t("uni-calender.cancel")
|
||||
},
|
||||
todayText() {
|
||||
return t("uni-calender.today")
|
||||
},
|
||||
monText() {
|
||||
return t("uni-calender.MON")
|
||||
},
|
||||
TUEText() {
|
||||
return t("uni-calender.TUE")
|
||||
},
|
||||
WEDText() {
|
||||
return t("uni-calender.WED")
|
||||
},
|
||||
THUText() {
|
||||
return t("uni-calender.THU")
|
||||
},
|
||||
FRIText() {
|
||||
return t("uni-calender.FRI")
|
||||
},
|
||||
SATText() {
|
||||
return t("uni-calender.SAT")
|
||||
},
|
||||
SUNText() {
|
||||
return t("uni-calender.SUN")
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
date(newVal) {
|
||||
// this.cale.setDate(newVal)
|
||||
this.init(newVal)
|
||||
},
|
||||
startDate(val) {
|
||||
this.cale.resetSatrtDate(val)
|
||||
this.cale.setDate(this.nowDate.fullDate)
|
||||
this.weeks = this.cale.weeks
|
||||
},
|
||||
endDate(val) {
|
||||
this.cale.resetEndDate(val)
|
||||
this.cale.setDate(this.nowDate.fullDate)
|
||||
this.weeks = this.cale.weeks
|
||||
},
|
||||
selected(newVal) {
|
||||
this.cale.setSelectInfo(this.nowDate.fullDate, newVal)
|
||||
this.weeks = this.cale.weeks
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.cale = new Calendar({
|
||||
selected: this.selected,
|
||||
startDate: this.startDate,
|
||||
endDate: this.endDate,
|
||||
range: this.range,
|
||||
})
|
||||
this.init(this.date)
|
||||
},
|
||||
methods: {
|
||||
// 取消穿透
|
||||
clean() {},
|
||||
bindDateChange(e) {
|
||||
const value = e.detail.value + '-1'
|
||||
this.setDate(value)
|
||||
|
||||
const {
|
||||
year,
|
||||
month
|
||||
} = this.cale.getDate(value)
|
||||
this.$emit('monthSwitch', {
|
||||
year,
|
||||
month
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 初始化日期显示
|
||||
* @param {Object} date
|
||||
*/
|
||||
init(date) {
|
||||
this.cale.setDate(date)
|
||||
this.weeks = this.cale.weeks
|
||||
this.nowDate = this.calendar = this.cale.getInfo(date)
|
||||
this.$emit('initdate', this.cale, this.nowDate);
|
||||
},
|
||||
/**
|
||||
* 打开日历弹窗
|
||||
*/
|
||||
open() {
|
||||
// 弹窗模式并且清理数据
|
||||
if (this.clearDate && !this.insert) {
|
||||
this.cale.cleanMultipleStatus()
|
||||
// this.cale.setDate(this.date)
|
||||
this.init(this.date)
|
||||
}
|
||||
this.show = true
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.aniMaskShow = true
|
||||
}, 50)
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 关闭日历弹窗
|
||||
*/
|
||||
close() {
|
||||
this.aniMaskShow = false
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.show = false
|
||||
this.$emit('close')
|
||||
}, 300)
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 确认按钮
|
||||
*/
|
||||
confirm() {
|
||||
this.setEmit('confirm')
|
||||
this.close()
|
||||
},
|
||||
/**
|
||||
* 变化触发
|
||||
*/
|
||||
change() {
|
||||
if (!this.insert) return
|
||||
this.setEmit('change')
|
||||
},
|
||||
/**
|
||||
* 选择月份触发
|
||||
*/
|
||||
monthSwitch() {
|
||||
let {
|
||||
year,
|
||||
month
|
||||
} = this.nowDate
|
||||
this.$emit('monthSwitch', {
|
||||
year,
|
||||
month: Number(month)
|
||||
})
|
||||
this.$emit('initdate', this.cale, this.cale.date);
|
||||
},
|
||||
/**
|
||||
* 派发事件
|
||||
* @param {Object} name
|
||||
*/
|
||||
setEmit(name) {
|
||||
let {
|
||||
year,
|
||||
month,
|
||||
date,
|
||||
fullDate,
|
||||
lunar,
|
||||
extraInfo
|
||||
} = this.calendar
|
||||
this.$emit(name, {
|
||||
range: this.cale.multipleStatus,
|
||||
year,
|
||||
month,
|
||||
date,
|
||||
fulldate: fullDate,
|
||||
lunar,
|
||||
extraInfo: extraInfo || {},
|
||||
cale: this.cale
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 选择天触发
|
||||
* @param {Object} weeks
|
||||
*/
|
||||
choiceDate(weeks) {
|
||||
if (weeks.disable) return
|
||||
this.calendar = weeks
|
||||
// 设置多选
|
||||
this.cale.setMultiple(this.calendar.fullDate)
|
||||
this.weeks = this.cale.weeks
|
||||
this.change()
|
||||
},
|
||||
/**
|
||||
* 回到今天
|
||||
*/
|
||||
backToday() {
|
||||
const nowYearMonth = `${this.nowDate.year}-${this.nowDate.month}`
|
||||
const date = this.cale.getDate(new Date())
|
||||
const todayYearMonth = `${date.year}-${date.month}`
|
||||
|
||||
// if (nowYearMonth !== todayYearMonth) {
|
||||
// this.monthSwitch()
|
||||
// }
|
||||
this.init(date.fullDate)
|
||||
// this.change()
|
||||
},
|
||||
/**
|
||||
* 上个月
|
||||
*/
|
||||
pre() {
|
||||
const preDate = this.cale.getDate(this.nowDate.fullDate, -1, 'month').fullDate
|
||||
this.setDate(preDate)
|
||||
this.monthSwitch()
|
||||
|
||||
},
|
||||
/**
|
||||
* 下个月
|
||||
*/
|
||||
next() {
|
||||
const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate
|
||||
this.setDate(nextDate)
|
||||
this.monthSwitch()
|
||||
},
|
||||
/**
|
||||
* 设置日期
|
||||
* @param {Object} date
|
||||
*/
|
||||
setDate(date) {
|
||||
this.cale.setDate(date)
|
||||
this.weeks = this.cale.weeks
|
||||
this.nowDate = this.cale.getInfo(date)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$uni-bg-color-mask: rgba($color: #000000, $alpha: 0.4);
|
||||
$uni-border-color: #EDEDED;
|
||||
$uni-text-color: #333;
|
||||
$uni-bg-color-hover: #f1f1f1;
|
||||
$uni-font-size-base: 14px;
|
||||
$uni-text-color-placeholder: #808080;
|
||||
$uni-color-subtitle: #555555;
|
||||
$uni-text-color-grey: #999;
|
||||
|
||||
.uni-calendar {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.uni-calendar__mask {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: $uni-bg-color-mask;
|
||||
transition-property: opacity;
|
||||
transition-duration: 0.3s;
|
||||
opacity: 0;
|
||||
/* #ifndef APP-NVUE */
|
||||
z-index: 99;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-calendar--mask-show {
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
.uni-calendar--fixed {
|
||||
position: fixed;
|
||||
/* #ifdef APP-NVUE */
|
||||
bottom: 0;
|
||||
/* #endif */
|
||||
left: 0;
|
||||
right: 0;
|
||||
transition-property: transform;
|
||||
transition-duration: 0.3s;
|
||||
transform: translateY(460px);
|
||||
/* #ifndef APP-NVUE */
|
||||
bottom: calc(var(--window-bottom));
|
||||
z-index: 99;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-calendar--ani-show {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.uni-calendar__content {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.uni-calendar__header {
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 50px;
|
||||
border-bottom-color: $uni-border-color;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.uni-calendar--fixed-top {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
border-top-color: $uni-border-color;
|
||||
border-top-style: solid;
|
||||
border-top-width: 1px;
|
||||
}
|
||||
|
||||
.uni-calendar--fixed-width {
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.uni-calendar__backtoday {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 25rpx;
|
||||
padding: 0 5px;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
font-size: 12px;
|
||||
color: $uni-text-color;
|
||||
background-color: $uni-bg-color-hover;
|
||||
margin-right: 28rpx;
|
||||
}
|
||||
|
||||
.uni-calendar__header-text {
|
||||
text-align: center;
|
||||
width: 100px;
|
||||
font-size: $uni-font-size-base;
|
||||
color: $uni-text-color;
|
||||
}
|
||||
|
||||
.uni-calendar__header-btn-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.uni-calendar__header-btn {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-left-color: $uni-text-color-placeholder;
|
||||
border-left-style: solid;
|
||||
border-left-width: 2px;
|
||||
border-top-color: $uni-color-subtitle;
|
||||
border-top-style: solid;
|
||||
border-top-width: 2px;
|
||||
}
|
||||
|
||||
.uni-calendar--left {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.uni-calendar--right {
|
||||
transform: rotate(135deg);
|
||||
}
|
||||
|
||||
|
||||
.uni-calendar__weeks {
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
margin: 10rpx 0;
|
||||
}
|
||||
|
||||
.uni-calendar__weeks-item {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.uni-calendar__weeks-day {
|
||||
flex: 1;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 45px;
|
||||
border-bottom-color: #F5F5F5;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.uni-calendar__weeks-day-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.uni-calendar__box {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.uni-calendar__box-bg {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.uni-calendar__box-bg-text {
|
||||
font-size: 200px;
|
||||
font-weight: bold;
|
||||
color: $uni-text-color-grey;
|
||||
opacity: 0.1;
|
||||
text-align: center;
|
||||
/* #ifndef APP-NVUE */
|
||||
line-height: 1;
|
||||
/* #endif */
|
||||
}
|
||||
</style>
|
||||
386
pages/workFlow/schedule/calendar/util.js
Normal file
@@ -0,0 +1,386 @@
|
||||
import CALENDAR from './calendar.js'
|
||||
|
||||
class Calendar {
|
||||
constructor({
|
||||
date,
|
||||
selected,
|
||||
startDate,
|
||||
endDate,
|
||||
range
|
||||
} = {}) {
|
||||
// 当前日期
|
||||
this.date = this.getDate(new Date()) // 当前初入日期
|
||||
// 打点信息
|
||||
this.selected = selected || [];
|
||||
// 范围开始
|
||||
this.startDate = startDate
|
||||
// 范围结束
|
||||
this.endDate = endDate
|
||||
this.range = range
|
||||
// 多选状态
|
||||
this.cleanMultipleStatus()
|
||||
// 每周日期
|
||||
this.weeks = {}
|
||||
// this._getWeek(this.date.fullDate)
|
||||
}
|
||||
/**
|
||||
* 设置日期
|
||||
* @param {Object} date
|
||||
*/
|
||||
setDate(date) {
|
||||
this.selectDate = this.getDate(date)
|
||||
this._getWeek(this.selectDate.fullDate)
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理多选状态
|
||||
*/
|
||||
cleanMultipleStatus() {
|
||||
this.multipleStatus = {
|
||||
before: '',
|
||||
after: '',
|
||||
data: []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置开始日期
|
||||
*/
|
||||
resetSatrtDate(startDate) {
|
||||
// 范围开始
|
||||
this.startDate = startDate
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置结束日期
|
||||
*/
|
||||
resetEndDate(endDate) {
|
||||
// 范围结束
|
||||
this.endDate = endDate
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任意时间
|
||||
*/
|
||||
getDate(date, AddDayCount = 0, str = 'day') {
|
||||
if (!date) {
|
||||
date = new Date()
|
||||
}
|
||||
if (typeof date !== 'object') {
|
||||
date = date.replace(/-/g, '/')
|
||||
}
|
||||
const dd = new Date(date)
|
||||
switch (str) {
|
||||
case 'day':
|
||||
dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
|
||||
break
|
||||
case 'month':
|
||||
if (dd.getDate() === 31 && AddDayCount > 0) {
|
||||
dd.setDate(dd.getDate() + AddDayCount)
|
||||
} else {
|
||||
const preMonth = dd.getMonth()
|
||||
dd.setMonth(preMonth + AddDayCount) // 获取AddDayCount天后的日期
|
||||
const nextMonth = dd.getMonth()
|
||||
// 处理 pre 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
|
||||
if (AddDayCount < 0 && preMonth !== 0 && nextMonth - preMonth > AddDayCount) {
|
||||
dd.setMonth(nextMonth + (nextMonth - preMonth + AddDayCount))
|
||||
}
|
||||
// 处理 next 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
|
||||
if (AddDayCount > 0 && nextMonth - preMonth > AddDayCount) {
|
||||
dd.setMonth(nextMonth - (nextMonth - preMonth - AddDayCount))
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'year':
|
||||
dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期
|
||||
break
|
||||
}
|
||||
const y = dd.getFullYear()
|
||||
const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0
|
||||
const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0
|
||||
return {
|
||||
fullDate: y + '-' + m + '-' + d,
|
||||
year: y,
|
||||
month: m,
|
||||
date: d,
|
||||
day: dd.getDay()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取上月剩余天数
|
||||
*/
|
||||
_getLastMonthDays(firstDay, full) {
|
||||
let dateArr = []
|
||||
for (let i = firstDay; i > 0; i--) {
|
||||
const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate()
|
||||
dateArr.push({
|
||||
date: beforeDate,
|
||||
month: full.month - 1,
|
||||
lunar: this.getlunar(full.year, full.month - 1, beforeDate),
|
||||
disable: true
|
||||
})
|
||||
}
|
||||
// 获取打点信息
|
||||
for (let i = 0; i < dateArr.length; i++) {
|
||||
let nowDate = full.year + '-' + (dateArr[i].month < 10 ?
|
||||
'0' + dateArr[i].month : dateArr[i].month) + '-' + (dateArr[i].date < 10 ?
|
||||
'0' + dateArr[i].date : dateArr[i].date)
|
||||
let info = this.selected && this.selected.find((item) => {
|
||||
if (this.dateEqual(nowDate, item.date)) {
|
||||
return item
|
||||
}
|
||||
})
|
||||
if (info) dateArr[i].extraInfo = info
|
||||
}
|
||||
return dateArr
|
||||
}
|
||||
/**
|
||||
* 获取本月天数
|
||||
*/
|
||||
_currentMonthDys(dateData, full) {
|
||||
let dateArr = []
|
||||
let fullDate = this.date.fullDate
|
||||
for (let i = 1; i <= dateData; i++) {
|
||||
let nowDate = full.year + '-' + (full.month < 10 ?
|
||||
full.month : full.month) + '-' + (i < 10 ?
|
||||
'0' + i : i)
|
||||
// 是否今天
|
||||
let isDay = fullDate === nowDate
|
||||
// 获取打点信息
|
||||
let info = this.selected && this.selected.find((item) => {
|
||||
if (this.dateEqual(nowDate, item.date)) {
|
||||
return item
|
||||
}
|
||||
})
|
||||
|
||||
// 日期禁用
|
||||
let disableBefore = true
|
||||
let disableAfter = true
|
||||
if (this.startDate) {
|
||||
// let dateCompBefore = this.dateCompare(this.startDate, fullDate)
|
||||
// disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
|
||||
disableBefore = this.dateCompare(this.startDate, nowDate)
|
||||
}
|
||||
|
||||
if (this.endDate) {
|
||||
// let dateCompAfter = this.dateCompare(fullDate, this.endDate)
|
||||
// disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
|
||||
disableAfter = this.dateCompare(nowDate, this.endDate)
|
||||
}
|
||||
let multiples = this.multipleStatus.data
|
||||
let checked = false
|
||||
let multiplesStatus = -1
|
||||
if (this.range) {
|
||||
if (multiples) {
|
||||
multiplesStatus = multiples.findIndex((item) => {
|
||||
return this.dateEqual(item, nowDate)
|
||||
})
|
||||
}
|
||||
if (multiplesStatus !== -1) {
|
||||
checked = true
|
||||
}
|
||||
}
|
||||
let data = {
|
||||
fullDate: nowDate,
|
||||
year: full.year,
|
||||
date: i,
|
||||
multiple: this.range ? checked : false,
|
||||
beforeMultiple: this.dateEqual(this.multipleStatus.before, nowDate),
|
||||
afterMultiple: this.dateEqual(this.multipleStatus.after, nowDate),
|
||||
month: full.month,
|
||||
lunar: this.getlunar(full.year, full.month, i),
|
||||
disable: !(disableBefore && disableAfter),
|
||||
isDay
|
||||
}
|
||||
if (info) {
|
||||
data.extraInfo = info
|
||||
}
|
||||
|
||||
dateArr.push(data)
|
||||
}
|
||||
return dateArr
|
||||
}
|
||||
/**
|
||||
* 获取下月天数
|
||||
*/
|
||||
_getNextMonthDays(surplus, full) {
|
||||
let dateArr = []
|
||||
for (let i = 1; i < surplus + 1; i++) {
|
||||
dateArr.push({
|
||||
date: i,
|
||||
month: Number(full.month) + 1,
|
||||
lunar: this.getlunar(full.year, Number(full.month) + 1, i),
|
||||
disable: true
|
||||
})
|
||||
}
|
||||
// 获取打点信息
|
||||
for (let i = 0; i < dateArr.length; i++) {
|
||||
let nowDate = full.year + '-' + (dateArr[i].month < 10 ?
|
||||
'0' + dateArr[i].month : dateArr[i].month) + '-' + (dateArr[i].date < 10 ?
|
||||
'0' + dateArr[i].date : dateArr[i].date)
|
||||
let info = this.selected && this.selected.find((item) => {
|
||||
if (this.dateEqual(nowDate, item.date)) {
|
||||
return item
|
||||
}
|
||||
})
|
||||
if (info) dateArr[i].extraInfo = info
|
||||
}
|
||||
return dateArr
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前日期详情
|
||||
* @param {Object} date
|
||||
*/
|
||||
getInfo(date) {
|
||||
if (!date) {
|
||||
date = new Date()
|
||||
}
|
||||
const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate)
|
||||
return dateInfo
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较时间大小
|
||||
*/
|
||||
dateCompare(startDate, endDate) {
|
||||
// 计算截止时间
|
||||
startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
|
||||
// 计算详细项的截止时间
|
||||
endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
|
||||
if (startDate <= endDate) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较时间是否相等
|
||||
*/
|
||||
dateEqual(before, after) {
|
||||
// 计算截止时间
|
||||
before = new Date(before.replace('-', '/').replace('-', '/'))
|
||||
// 计算详细项的截止时间
|
||||
after = new Date(after.replace('-', '/').replace('-', '/'))
|
||||
if (before.getTime() - after.getTime() === 0) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取日期范围内所有日期
|
||||
* @param {Object} begin
|
||||
* @param {Object} end
|
||||
*/
|
||||
geDateAll(begin, end) {
|
||||
var arr = []
|
||||
var ab = begin.split('-')
|
||||
var ae = end.split('-')
|
||||
var db = new Date()
|
||||
db.setFullYear(ab[0], ab[1] - 1, ab[2])
|
||||
var de = new Date()
|
||||
de.setFullYear(ae[0], ae[1] - 1, ae[2])
|
||||
var unixDb = db.getTime() - 24 * 60 * 60 * 1000
|
||||
var unixDe = de.getTime() - 24 * 60 * 60 * 1000
|
||||
for (var k = unixDb; k <= unixDe;) {
|
||||
k = k + 24 * 60 * 60 * 1000
|
||||
arr.push(this.getDate(new Date(parseInt(k))).fullDate)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
/**
|
||||
* 计算阴历日期显示
|
||||
*/
|
||||
getlunar(year, month, date) {
|
||||
return CALENDAR.solar2lunar(year, month, date)
|
||||
}
|
||||
/**
|
||||
* 设置打点
|
||||
*/
|
||||
setSelectInfo(data, value) {
|
||||
this.selected = value
|
||||
this._getWeek(data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取多选状态
|
||||
*/
|
||||
setMultiple(fullDate) {
|
||||
let {
|
||||
before,
|
||||
after
|
||||
} = this.multipleStatus
|
||||
|
||||
if (!this.range) return
|
||||
if (before && after) {
|
||||
this.multipleStatus.before = ''
|
||||
this.multipleStatus.after = ''
|
||||
this.multipleStatus.data = []
|
||||
} else {
|
||||
if (!before) {
|
||||
this.multipleStatus.before = fullDate
|
||||
} else {
|
||||
this.multipleStatus.after = fullDate
|
||||
if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
|
||||
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus
|
||||
.after);
|
||||
} else {
|
||||
this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus
|
||||
.before);
|
||||
}
|
||||
}
|
||||
}
|
||||
this._getWeek(fullDate)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取每周数据
|
||||
* @param {Object} dateData
|
||||
*/
|
||||
_getWeek(dateData) {
|
||||
const {
|
||||
year,
|
||||
month
|
||||
} = this.getDate(dateData)
|
||||
let firstDay = new Date(year, month - 1, 1).getDay()
|
||||
let currentDay = new Date(year, month, 0).getDate()
|
||||
let dates = {
|
||||
lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天
|
||||
currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数
|
||||
nextMonthDays: [], // 下个月开始几天
|
||||
weeks: []
|
||||
}
|
||||
let canlender = []
|
||||
const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)
|
||||
dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))
|
||||
canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
|
||||
let weeks = {}
|
||||
// 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天
|
||||
for (let i = 0; i < canlender.length; i++) {
|
||||
if (i % 7 === 0) {
|
||||
weeks[parseInt(i / 7)] = new Array(7)
|
||||
}
|
||||
weeks[parseInt(i / 7)][i % 7] = canlender[i]
|
||||
}
|
||||
this.canlender = canlender
|
||||
this.weeks = weeks
|
||||
}
|
||||
|
||||
//静态方法
|
||||
// static init(date) {
|
||||
// if (!this.instance) {
|
||||
// this.instance = new Calendar(date);
|
||||
// }
|
||||
// return this.instance;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
export default Calendar
|
||||
281
pages/workFlow/schedule/detail.vue
Normal file
@@ -0,0 +1,281 @@
|
||||
<template>
|
||||
<view class="">
|
||||
<u-navbar title="详情" :custom-back="back">
|
||||
<template #right>
|
||||
<view class="navbar-right">
|
||||
<view class="message-box right-item" style="padding-right: 20rpx;">
|
||||
<u-icon name='more-dot-fill' @click="show=true" v-if="!groupId"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</u-navbar>
|
||||
<view class="scheduleForm-v jnpf-wrap">
|
||||
<u-toast ref="uToast" />
|
||||
<u-form :model="dataForm" ref="dataForm" :errorType="['toast']" label-position="left" label-width="150"
|
||||
label-align="left">
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="标题" prop="title">
|
||||
<u-input input-align='right' v-model="dataForm.title" label-align="right" placeholder=""
|
||||
disabled></u-input>
|
||||
</u-form-item>
|
||||
<u-form-item label="内容" prop="content">
|
||||
<u-input input-align='right' v-model="dataForm.content" type="textarea" placeholder=""
|
||||
disabled></u-input>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<!-- #ifndef APP-HARMONY -->
|
||||
<view class="u-p-l-20 u-p-r-20 u-m-t-20 form-item-box">
|
||||
<u-form-item label="附件" prop="content">
|
||||
<JnpfUploadFile v-model="dataForm.files" detailed />
|
||||
</u-form-item>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-HARMONY -->
|
||||
<view class="u-p-l-20 u-p-r-20 u-m-t-20 form-item-box">
|
||||
<u-form-item label="附件" prop="content">
|
||||
<JnpfUploadFileH v-model="dataForm.files" detailed />
|
||||
</u-form-item>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<view class="jnpf-card">
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="紧急程度" prop="urgent">
|
||||
<u-input input-align='right' v-model="dataForm.urgent" label-align="right" placeholder=""
|
||||
disabled></u-input>
|
||||
</u-form-item>
|
||||
<u-form-item label="类型" prop="category">
|
||||
<u-input input-align='right' v-model="dataForm.category" placeholder="" disabled></u-input>
|
||||
</u-form-item>
|
||||
<u-form-item label="创建人" prop="creatorUserId">
|
||||
<u-input input-align='right' v-model="dataForm.creatorUserId" placeholder=""
|
||||
disabled></u-input>
|
||||
</u-form-item>
|
||||
<u-form-item label="参与人" prop="toUserIds">
|
||||
<u-input input-align='right' v-model="dataForm.toUserIds" placeholder="" disabled></u-input>
|
||||
</u-form-item>
|
||||
</view>
|
||||
</view>
|
||||
<view class="jnpf-card">
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="开始时间" prop="startDay">
|
||||
<datetime :delayMin="0" v-model="startDay" :date="startDate" disabled
|
||||
:showtdatetime='showtdatetime' :type="1" :allDay='dataForm.allDay' placeholder="" />
|
||||
</u-form-item>
|
||||
<u-form-item label="结束时间" prop="endDay">
|
||||
<datetime :delayMin="0" v-model="endDay" :date="endDate" disabled
|
||||
:showtdatetime='showtdatetime' :type="2" :allDay='dataForm.allDay' placeholder="" />
|
||||
</u-form-item>
|
||||
</view>
|
||||
</view>
|
||||
</u-form>
|
||||
</view>
|
||||
<u-action-sheet @click="handleAction" :list="actionList" :tips="{ text:'' , color: '#000' , fontSize: 30 }"
|
||||
v-model="show">
|
||||
</u-action-sheet>
|
||||
<u-action-sheet @click="delAction" :list="delList"
|
||||
:tips="{ text:toUserType===true?dataForm.repetition != '1'?'此为重复日程,将删除(含参与人)应用于':'确认删除(含参与人)当前日程':dataForm.repetition != '1'?'此为重复日程,将删除应用于':'确认删除当前日程' , color: '#000' , fontSize: 30 }"
|
||||
v-model="showBtn">
|
||||
</u-action-sheet>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import datetime from './t-datetime.vue'
|
||||
import {
|
||||
ScheduleDetail,
|
||||
ScheduleDelete
|
||||
} from '@/api/workFlow/schedule.js'
|
||||
import {
|
||||
useBaseStore
|
||||
} from '@/store/modules/base'
|
||||
|
||||
const baseStore = useBaseStore()
|
||||
|
||||
export default {
|
||||
components: {
|
||||
datetime
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showAction: '',
|
||||
userInfo: {},
|
||||
show: false,
|
||||
showtdatetime: false,
|
||||
dataForm: {
|
||||
id: 0,
|
||||
category: '',
|
||||
creatorUserId: 0,
|
||||
userName: '',
|
||||
allDay: 0,
|
||||
urgent: '1',
|
||||
startDay: '',
|
||||
startTime: '',
|
||||
endDay: '',
|
||||
endTime: '',
|
||||
duration: '',
|
||||
content: '',
|
||||
title: '',
|
||||
toUserIds: '',
|
||||
reminderTime: -2,
|
||||
reminderType: 1,
|
||||
send: '',
|
||||
sendName: '',
|
||||
repetition: 1,
|
||||
repeatTime: '',
|
||||
color: '#188ae2'
|
||||
},
|
||||
showBtn: false,
|
||||
startDate: {},
|
||||
endDate: {},
|
||||
repeatDate: {},
|
||||
repeat: '',
|
||||
endDay: '',
|
||||
startDay: '',
|
||||
toUserType: false,
|
||||
actionList: [],
|
||||
delList: [],
|
||||
groupId: ''
|
||||
}
|
||||
},
|
||||
onReady() {
|
||||
this.$refs.dataForm.setRules(this.rules);
|
||||
},
|
||||
onLoad(option) {
|
||||
this.dataForm.id = option.id
|
||||
this.toUserType = option.type
|
||||
this.actionList = []
|
||||
this.delList = []
|
||||
this.groupId = option.groupId
|
||||
if (this.toUserType == 'true') {
|
||||
this.actionList.push({
|
||||
text: '编辑',
|
||||
id: 'update'
|
||||
})
|
||||
this.actionList.push({
|
||||
text: '删除',
|
||||
id: 'deldete',
|
||||
color: '#ff3a3a',
|
||||
})
|
||||
} else {
|
||||
this.actionList.push({
|
||||
text: '删除',
|
||||
id: 'deldete',
|
||||
color: '#ff3a3a',
|
||||
})
|
||||
}
|
||||
ScheduleDetail(this.groupId, option.id).then(res => {
|
||||
let data = res.data || {};
|
||||
data.files = data.files ? JSON.parse(data.files) : [];
|
||||
this.dataForm = data
|
||||
if (this.dataForm.repetition != '1') {
|
||||
this.delList.push({
|
||||
text: '仅删除此日程',
|
||||
id: '1'
|
||||
})
|
||||
this.delList.push({
|
||||
text: '删除此日程及后续日程',
|
||||
id: '2',
|
||||
})
|
||||
this.delList.push({
|
||||
text: '删除所有日程',
|
||||
id: '3',
|
||||
})
|
||||
} else {
|
||||
this.delList.push({
|
||||
text: '删除',
|
||||
id: '3',
|
||||
color: '#ff3a3a',
|
||||
})
|
||||
}
|
||||
this.startDate = this.timestampToTime(this.dataForm.startDay)
|
||||
this.endDate = this.timestampToTime(this.dataForm.endDay)
|
||||
}).catch((err) => {
|
||||
uni.showToast({
|
||||
title: err,
|
||||
complete: () => {
|
||||
setTimeout(() => {
|
||||
uni.navigateBack()
|
||||
}, 300)
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
delAction(index) {
|
||||
if (this.dataForm.repetition != '1') {
|
||||
ScheduleDelete(this.dataForm.id, index + 1).then(res => {
|
||||
uni.showToast({
|
||||
title: res.msg,
|
||||
complete: () => {
|
||||
uni.$emit('refresh')
|
||||
uni.navigateBack()
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
ScheduleDelete(this.dataForm.id, 3).then(res => {
|
||||
uni.showToast({
|
||||
title: res.msg,
|
||||
complete: () => {
|
||||
uni.$emit('refresh')
|
||||
uni.navigateBack()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
handleAction(index) {
|
||||
if (this.actionList[index].id == 'update') {
|
||||
uni.navigateTo({
|
||||
url: './form?id=' + this.dataForm.id
|
||||
})
|
||||
} else {
|
||||
this.showBtn = true
|
||||
}
|
||||
},
|
||||
back() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
getResult() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
changeSend(id, name) {
|
||||
this.dataForm.send = id
|
||||
this.dataForm.sendName = name
|
||||
},
|
||||
getDictionaryData() {
|
||||
baseStore.getDictionaryData({
|
||||
sort: 'scheduleType'
|
||||
}).then((res) => {
|
||||
this.typeOptions = res
|
||||
})
|
||||
},
|
||||
timestampToTime(timestamp) {
|
||||
let list = {}
|
||||
var date = new Date(timestamp);
|
||||
let Y = date.getFullYear();
|
||||
let M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1);
|
||||
let D = date.getDate();
|
||||
let h = date.getHours();
|
||||
let m = date.getMinutes();
|
||||
let s = date.getSeconds();
|
||||
list.year = Y
|
||||
list.month = M
|
||||
list.date = D
|
||||
list.hours = h < 10 ? 0 + h : h
|
||||
list.minutes = m < 10 ? 0 + m : m
|
||||
list.seconds = s
|
||||
return list
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f0f2f6;
|
||||
}
|
||||
|
||||
.scheduleForm-v {
|
||||
padding-bottom: 110rpx;
|
||||
}
|
||||
</style>
|
||||
610
pages/workFlow/schedule/form.vue
Normal file
@@ -0,0 +1,610 @@
|
||||
<template>
|
||||
<view class="scheduleForm-v jnpf-wrap">
|
||||
<u-toast ref="uToast" />
|
||||
<u-form :model="dataForm" :rules="rules" ref="dataForm" :errorType="['toast']" label-position="left"
|
||||
label-width="150" label-align="left">
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="标题" prop="title" required>
|
||||
<u-input input-align='right' v-model="dataForm.title" placeholder="请输入"></u-input>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="内容" prop="content">
|
||||
<u-input input-align='right' v-model="dataForm.content" placeholder="请输入" type="textarea"></u-input>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<!-- #ifndef APP-HARMONY -->
|
||||
<view class="jnpf-card u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="附件" prop="files">
|
||||
<JnpfUploadFile v-model="dataForm.files" />
|
||||
</u-form-item>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-HARMONY -->
|
||||
<view class="jnpf-card u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="附件" prop="files">
|
||||
<JnpfUploadFileH v-model="dataForm.files" />
|
||||
</u-form-item>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<view class="jnpf-card">
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="紧急程度" prop="urgent">
|
||||
<JnpfSelect v-model="dataForm.urgent" :options='urgentList' placeholder="请选择" />
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="类型" prop="category" required>
|
||||
<JnpfSelect v-model="dataForm.category" :options='categoryOptions' placeholder="请选择" />
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="创建人" prop="creatorUserId" required>
|
||||
<JnpfUserSelect v-model="dataForm.creatorUserId" placeholder="请输入" disabled="disabled" />
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="参与人" prop="toUserIds">
|
||||
<JnpfUserSelect v-model="dataForm.toUserIds" placeholder="请选择" multiple />
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="标签颜色" prop="color">
|
||||
<JnpfColorPicker v-model="dataForm.color" />
|
||||
</u-form-item>
|
||||
</view>
|
||||
</view>
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="全天" prop="allDay">
|
||||
<JnpfSwitch v-model="dataForm.allDay" @change="change_providerType" />
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="开始时间" prop="startDay" required>
|
||||
<tdatetime :delayMin="0" v-model="startDay" :date="startDate" placeholder="请选择"
|
||||
:showtdatetime='showtdatetime' :type="1" @confirm='confirm' :allDay='dataForm.allDay' />
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="时长" prop="duration" required v-if="dataForm.duration!=-1&&dataForm.allDay==0">
|
||||
<JnpfSelect v-model="dataForm.duration" :options='durationList' />
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="结束时间" prop="endDay" required v-if='dataForm.duration==-1||dataForm.allDay'>
|
||||
<tdatetime :delayMin="0" v-model="endDay" :date="endDate" placeholder="请选择"
|
||||
:showtdatetime='showtdatetime' :type="2" @confirm='confirm' :allDay='dataForm.allDay' />
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="jnpf-card">
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="提醒时间" prop="reminderTime">
|
||||
<JnpfSelect v-model="dataForm.reminderTime"
|
||||
:options='dataForm.allDay?reminderTimeList_:reminderTimeList' placeholder="请选择" />
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view v-if="dataForm.reminderTime!=-2" class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="提醒方式" prop="reminderType">
|
||||
<jnpf-select v-model="dataForm.reminderType" :options='remindList'
|
||||
placeholder="请选择"></jnpf-select>
|
||||
</u-form-item>
|
||||
<u-form-item label="发送配置" prop="send" v-if="dataForm.reminderType==2">
|
||||
<sendSelect v-model="dataForm.sendName" :send='dataForm.send' @change='changeSend'
|
||||
placeholder="请选择" />
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="重复提醒" prop="repetition">
|
||||
<jnpf-select v-model="dataForm.repetition" :options='repeatReminderList'
|
||||
@change='repeatTimeChange' placeholder="请选择"></jnpf-select>
|
||||
</u-form-item>
|
||||
</view>
|
||||
<view class="u-p-l-20 u-p-r-20 form-item-box">
|
||||
<u-form-item label="结束重复" prop="repeatTime" required v-if='dataForm.repetition!=1'>
|
||||
<tdatetime :delayMin="0" v-model="repeat" :date="repeatDate" placeholder="请选择"
|
||||
:showtdatetime='showtdatetime' :type="3" @confirm='confirm' :allDay='1' />
|
||||
</u-form-item>
|
||||
</view>
|
||||
</view>
|
||||
</u-form>
|
||||
<view class="flowBefore-actions">
|
||||
<u-button class="buttom-btn" @click="getResult('cancel')">{{$t('common.cancelText')}}</u-button>
|
||||
<u-button class="buttom-btn" type="primary" :loading='btnLoading'
|
||||
@click.stop="save()">{{$t('common.okText')}}</u-button>
|
||||
</view>
|
||||
<u-action-sheet @click="handleAction" :list="actionList"
|
||||
:tips="{ text:'此为重复日程,将修改应用于' , color: '#000' , fontSize: 30 }" v-model="show">
|
||||
</u-action-sheet>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import tdatetime from './t-datetime.vue'
|
||||
import sendSelect from './sendSelect/index.vue'
|
||||
import {
|
||||
ScheduleInfo,
|
||||
ScheduleCreate,
|
||||
ScheduleUpdate
|
||||
} from '@/api/workFlow/schedule.js'
|
||||
import {
|
||||
useBaseStore
|
||||
} from '@/store/modules/base'
|
||||
|
||||
const baseStore = useBaseStore()
|
||||
|
||||
|
||||
export default {
|
||||
components: {
|
||||
tdatetime,
|
||||
sendSelect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
title: '',
|
||||
userInfo: {},
|
||||
show: false,
|
||||
showtdatetime: false,
|
||||
dataForm: {
|
||||
id: 0,
|
||||
category: '',
|
||||
creatorUserId: 0,
|
||||
userName: '',
|
||||
allDay: 0,
|
||||
urgent: '1',
|
||||
startDay: '',
|
||||
startTime: '',
|
||||
endDay: '',
|
||||
endTime: '',
|
||||
duration: 60,
|
||||
content: '',
|
||||
title: '',
|
||||
toUserIds: [],
|
||||
reminderTime: -2,
|
||||
reminderType: 1,
|
||||
send: '',
|
||||
sendName: '',
|
||||
repetition: 1,
|
||||
repeatTime: '',
|
||||
color: '#FFFFFF',
|
||||
files: []
|
||||
},
|
||||
btnLoading: false,
|
||||
showBtn: false,
|
||||
startDate: {},
|
||||
endDate: {},
|
||||
repeatDate: {},
|
||||
repeat: '',
|
||||
endDay: '',
|
||||
startDay: '',
|
||||
urgentList: [{
|
||||
id: "1",
|
||||
fullName: '普通'
|
||||
}, {
|
||||
id: '2',
|
||||
fullName: '重要'
|
||||
}, {
|
||||
id: '3',
|
||||
fullName: '紧急'
|
||||
}],
|
||||
durationList: [{
|
||||
id: 30,
|
||||
fullName: '30分钟'
|
||||
}, {
|
||||
id: 60,
|
||||
fullName: '1小时'
|
||||
}, {
|
||||
id: 90,
|
||||
fullName: '1小时30分钟'
|
||||
}, {
|
||||
id: 120,
|
||||
fullName: '2小时'
|
||||
}, {
|
||||
id: 180,
|
||||
fullName: '3小时'
|
||||
}, {
|
||||
id: -1,
|
||||
fullName: '自定义'
|
||||
}],
|
||||
categoryOptions: [],
|
||||
repetitionType: false,
|
||||
reminderTimeList: [{
|
||||
id: -2,
|
||||
fullName: '不提醒'
|
||||
}, {
|
||||
id: -1,
|
||||
fullName: '开始时'
|
||||
}, {
|
||||
id: 5,
|
||||
fullName: '提前5分钟'
|
||||
}, {
|
||||
id: 10,
|
||||
fullName: '提前10分钟'
|
||||
}, {
|
||||
id: 15,
|
||||
fullName: '提前15分钟'
|
||||
}, {
|
||||
id: 30,
|
||||
fullName: '提前30分钟'
|
||||
}, {
|
||||
id: 60,
|
||||
fullName: '提前1小时'
|
||||
}, {
|
||||
id: 120,
|
||||
fullName: '提前2小时'
|
||||
}, {
|
||||
id: 1440,
|
||||
fullName: '1天前'
|
||||
}, {
|
||||
id: 2880,
|
||||
fullName: '2天前'
|
||||
}, {
|
||||
id: 10080,
|
||||
fullName: '1周前'
|
||||
}],
|
||||
reminderTimeList_: [{
|
||||
id: -2,
|
||||
fullName: '不提醒'
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
fullName: '当天8:00'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
fullName: '当天9:00'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
fullName: '当天10:00'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
fullName: '1天前8:00'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
fullName: '1天前9:00'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
fullName: '1天前10:00'
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
fullName: '2天前8:00'
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
fullName: '2天前9:00'
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
fullName: '2天前10:00'
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
fullName: '1周前8:00'
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
fullName: '1周前9:00'
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
fullName: '1周前10:00'
|
||||
}
|
||||
],
|
||||
remindList: [{
|
||||
id: 1,
|
||||
fullName: '默认'
|
||||
}, {
|
||||
id: 2,
|
||||
fullName: '自定义'
|
||||
}],
|
||||
repeatReminderList: [{
|
||||
id: 1,
|
||||
fullName: '不重复'
|
||||
}, {
|
||||
id: 2,
|
||||
fullName: '每天重复'
|
||||
}, {
|
||||
id: 3,
|
||||
fullName: '每周重复'
|
||||
}, {
|
||||
id: 4,
|
||||
fullName: '每月重复'
|
||||
}, {
|
||||
id: 5,
|
||||
fullName: '每年重复'
|
||||
}],
|
||||
actionList: [],
|
||||
rules: {
|
||||
startTime: [{
|
||||
required: true,
|
||||
message: '开始时间不能为空',
|
||||
trigger: 'change',
|
||||
type: 'number'
|
||||
}],
|
||||
startTime: [{
|
||||
required: true,
|
||||
message: '开始时间不能为空',
|
||||
trigger: 'change',
|
||||
type: 'number'
|
||||
}],
|
||||
endTime: [{
|
||||
required: true,
|
||||
message: '结束时间不能为空',
|
||||
trigger: 'change',
|
||||
type: 'number'
|
||||
}],
|
||||
repeat: [{
|
||||
required: true,
|
||||
message: '记录不能为空',
|
||||
trigger: 'change',
|
||||
}],
|
||||
category: [{
|
||||
required: true,
|
||||
message: '请选择类型',
|
||||
trigger: 'change'
|
||||
}],
|
||||
title: [{
|
||||
required: true,
|
||||
message: '请输入标题',
|
||||
trigger: 'blur'
|
||||
}],
|
||||
duration: [{
|
||||
required: true,
|
||||
message: '请选择时长',
|
||||
trigger: 'change',
|
||||
type: 'number'
|
||||
}],
|
||||
send: [{
|
||||
required: true,
|
||||
message: '发送配置不能为空',
|
||||
trigger: 'change'
|
||||
}],
|
||||
reminderType: [{
|
||||
required: true,
|
||||
message: '提醒方式不能为空',
|
||||
trigger: 'change',
|
||||
type: 'number'
|
||||
}]
|
||||
}
|
||||
}
|
||||
},
|
||||
onReady() {
|
||||
this.$refs.dataForm.setRules(this.rules);
|
||||
},
|
||||
onLoad(option) {
|
||||
this.repetitionType = false
|
||||
this.userInfo = uni.getStorageSync('userInfo') || {}
|
||||
this.dataForm.id = option.id
|
||||
this.btnLoading = false
|
||||
this.title = this.dataForm.id ? '编辑' : '新建'
|
||||
uni.setNavigationBarTitle({
|
||||
title: this.title
|
||||
});
|
||||
if (this.dataForm.id) {
|
||||
ScheduleInfo(option.id).then(res => {
|
||||
let data = res.data
|
||||
data.files = data.files ? JSON.parse(data.files) : [];
|
||||
this.dataForm = data
|
||||
this.startDate = this.timestampToTime(this.dataForm.startDay)
|
||||
this.endDate = this.timestampToTime(this.dataForm.endDay)
|
||||
this.repeatDate = this.dataForm.repeatTime ? this.timestampToTime(this.dataForm.repeatTime) :
|
||||
{}
|
||||
if (this.dataForm.repetition != "1") return this.repetitionType = true
|
||||
})
|
||||
} else {
|
||||
let startDate = this.timestampToTime(+new Date())
|
||||
this.startDate = this.timestampToTime(option.startTime || +new Date())
|
||||
this.startDate.hours = startDate.hours + 1
|
||||
this.startDate.minutes = '00'
|
||||
this.confirm(this.startDate, 1)
|
||||
this.endDate = this.timestampToTime(option.startTime || +new Date())
|
||||
this.endDate.hours = startDate.hours + 2
|
||||
this.endDate.minutes = '00'
|
||||
this.confirm(this.endDate, 2)
|
||||
this.repeatDate = {}
|
||||
this.dataForm.creatorUserId = this.userInfo.userId
|
||||
this.dataForm.duration = Number(option.duration) || 60
|
||||
}
|
||||
this.getDictionaryData()
|
||||
},
|
||||
methods: {
|
||||
back() {
|
||||
if (!this.dataForm.id) return uni.navigateBack()
|
||||
uni.navigateBack({
|
||||
delta: 2
|
||||
})
|
||||
},
|
||||
handleAction(index) {
|
||||
ScheduleUpdate(this.dataForm, index + 1).then(res => {
|
||||
uni.showToast({
|
||||
title: res.msg,
|
||||
complete: () => {
|
||||
uni.$emit('refresh')
|
||||
uni.navigateBack({
|
||||
delta: 2
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
change_providerType(val) {
|
||||
if (!val) {
|
||||
let startDate = this.timestampToTime(+new Date())
|
||||
this.startDate = this.timestampToTime(this.dataForm.startDay)
|
||||
this.startDate.hours = startDate.hours + 1
|
||||
this.startDate.minutes = '00'
|
||||
this.confirm(this.startDate, 1)
|
||||
this.endDate = this.timestampToTime(this.dataForm.endDay)
|
||||
this.endDate.hours = startDate.hours + 2
|
||||
this.endDate.minutes = '00'
|
||||
this.confirm(this.endDate, 2)
|
||||
} else {
|
||||
this.dataForm.endDay = this.dataForm.startDay
|
||||
}
|
||||
this.dataForm.reminderTime = -2
|
||||
},
|
||||
repeatTimeChange(val) {
|
||||
let time = new Date()
|
||||
time.setFullYear(time.getFullYear() + 1)
|
||||
if (val != 1) {
|
||||
let date = time.getTime()
|
||||
this.repeatDate = this.timestampToTime(date)
|
||||
this.repeatDate.minutes = '00'
|
||||
this.confirm(this.repeatDate, 3)
|
||||
}
|
||||
},
|
||||
getResult() {
|
||||
if (!this.dataForm.id) return uni.navigateBack()
|
||||
uni.showModal({
|
||||
title: '退出此次编辑?',
|
||||
content: '日程信息将不会保存',
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
uni.$emit('refresh')
|
||||
uni.navigateBack({
|
||||
delta: 2
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
changeSend(id, name) {
|
||||
this.dataForm.send = id
|
||||
this.dataForm.sendName = name
|
||||
},
|
||||
getDictionaryData() {
|
||||
baseStore.getDictionaryData({
|
||||
sort: 'scheduleType'
|
||||
}).then((res) => {
|
||||
this.categoryOptions = res || []
|
||||
if (this.categoryOptions.length) this.dataForm.category = this.categoryOptions[0].id
|
||||
})
|
||||
},
|
||||
confirm(e, type) {
|
||||
if (type == 1) {
|
||||
this.dataForm.startDay = e.year + '-' + e.month + '-' + e.date
|
||||
this.dataForm.startDay = new Date(this.dataForm.startDay).getTime()
|
||||
this.dataForm.startTime = e.hours + ":" + e.minutes
|
||||
} else if (type == 2) {
|
||||
this.dataForm.endDay = e.year + '-' + e.month + '-' + e.date
|
||||
this.dataForm.endDay = new Date(this.dataForm.endDay).getTime()
|
||||
this.dataForm.endTime = e.hours + ":" + e.minutes
|
||||
} else {
|
||||
this.dataForm.repeatTime = e.year + '-' + e.month + '-' + e.date
|
||||
this.dataForm.repeatTime = new Date(this.dataForm.repeatTime).getTime()
|
||||
}
|
||||
},
|
||||
save() {
|
||||
this.$refs.dataForm.validate((valid) => {
|
||||
if (valid) {
|
||||
if (this.dataForm.duration == -1) {
|
||||
if (this.dataForm.startDay > this.dataForm.endDay) {
|
||||
this.$refs.uToast.show({
|
||||
title: '结束时间必须晚于开始时间',
|
||||
type: 'error'
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
if (this.dataForm.allDay == 1) {
|
||||
let startDay = this.timestampToData(this.dataForm.startDay)
|
||||
let endDay = this.timestampToData(this.dataForm.endDay)
|
||||
if (this.dataForm.startDay > this.dataForm.endDay) {
|
||||
this.$refs.uToast.show({
|
||||
title: '结束时间必须晚于开始时间',
|
||||
type: 'error'
|
||||
})
|
||||
return
|
||||
}
|
||||
this.dataForm.startDay = new Date(startDay).getTime()
|
||||
this.dataForm.endDay = new Date(endDay).getTime()
|
||||
}
|
||||
if (this.dataForm.repetition != 1) {
|
||||
if (this.dataForm.startDay > this.dataForm.repeatTime) {
|
||||
this.$refs.uToast.show({
|
||||
title: '结束重复时间必须晚于开始时间',
|
||||
type: 'error'
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
if (this.dataForm.id && this.repetitionType) {
|
||||
this.show = true
|
||||
this.actionList = []
|
||||
this.actionList.push({
|
||||
text: '仅修改此日程',
|
||||
id: '1'
|
||||
})
|
||||
this.actionList.push({
|
||||
text: '修改此日程及后续日程',
|
||||
id: '2',
|
||||
})
|
||||
} else {
|
||||
this.btnLoading = true
|
||||
const formMethod = this.dataForm.id ? ScheduleUpdate : ScheduleCreate;
|
||||
const query = {
|
||||
...this.dataForm,
|
||||
files: JSON.stringify(this.dataForm.files)
|
||||
}
|
||||
formMethod(query, 3).then(res => {
|
||||
uni.showToast({
|
||||
title: res.msg,
|
||||
complete: () => {
|
||||
this.btnLoading = false
|
||||
uni.$emit('refresh')
|
||||
if (this.dataForm.id) {
|
||||
uni.navigateBack({
|
||||
delta: 2
|
||||
})
|
||||
} else {
|
||||
uni.navigateBack()
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
timestampToTime(timestamp) {
|
||||
let list = {}
|
||||
timestamp = timestamp || 0
|
||||
var date = new Date(Number(timestamp));
|
||||
let Y = date.getFullYear();
|
||||
let M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1);
|
||||
let D = date.getDate();
|
||||
let h = date.getHours();
|
||||
let m = date.getMinutes();
|
||||
let s = date.getSeconds();
|
||||
list.year = Y
|
||||
list.month = M
|
||||
list.date = D
|
||||
list.hours = h < 10 ? 0 + h : h
|
||||
list.minutes = m < 10 ? 0 + m : m
|
||||
list.seconds = s < 10 ? 0 + s : s
|
||||
return list
|
||||
},
|
||||
timestampToData(timestamp) {
|
||||
var date = new Date(timestamp);
|
||||
let Y = date.getFullYear();
|
||||
let M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1);
|
||||
let D = date.getDate();
|
||||
return Y + '-' + M + '-' + D + " 00:00:00"
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f0f2f6;
|
||||
}
|
||||
|
||||
.scheduleForm-v {
|
||||
padding-bottom: 110rpx;
|
||||
}
|
||||
</style>
|
||||
277
pages/workFlow/schedule/index.vue
Normal file
@@ -0,0 +1,277 @@
|
||||
<template>
|
||||
<view class="schedule-v">
|
||||
<view class="calendar-v">
|
||||
<calendar :lunar="true" :selected="selected" :showMonth="true" @change="change" @initdate="initdate"
|
||||
:key='key' />
|
||||
</view>
|
||||
<view class="u-p-20 block">
|
||||
<view class="block-a u-font-24">
|
||||
{{dateDay}}
|
||||
<div>{{changedate}}</div>
|
||||
</view>
|
||||
<view class="u-m-b-20 list-box">
|
||||
<view v-for="(item,index) in scheduleList" :key="index" class="list">
|
||||
<view class="u-m-t-20 u-flex item" @click="goDetail(item.id,item.creatorUserId)">
|
||||
<text class="u-font-28">{{item.allDay?'全天':item.startTime}}</text>
|
||||
<view class="u-flex-col u-m-l-20 u-p-l-20 content u-font-28">
|
||||
<view>{{item.title}}</view>
|
||||
<view class="u-font-24">{{item.content}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view :class="scheduleList.length<3?'lunar1':'addlunar'">
|
||||
<view @click="goDetail()" class="add-title">+添加日程内容</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import calendar from './calendar/uni-calendar.vue'
|
||||
import {
|
||||
List
|
||||
} from '@/api/workFlow/schedule.js'
|
||||
export default {
|
||||
components: {
|
||||
direction: 'col',
|
||||
calendar,
|
||||
},
|
||||
props: {
|
||||
config: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selected: [],
|
||||
showForm: false,
|
||||
horizontal: 'right',
|
||||
vertical: 'bottom',
|
||||
direction: 'horizontal',
|
||||
pattern: {
|
||||
color: '#7A7E83',
|
||||
backgroundColor: '#fff',
|
||||
selectedColor: '#007AFF',
|
||||
buttonColor: "#007AFF"
|
||||
},
|
||||
changedate: '',
|
||||
scheduleList: [],
|
||||
exhibitionList: [],
|
||||
startDate: '',
|
||||
endDate: '',
|
||||
dateDay: '',
|
||||
query: {},
|
||||
options: [{
|
||||
text: '删除',
|
||||
style: {
|
||||
backgroundColor: '#dd524d'
|
||||
}
|
||||
}],
|
||||
startTime: "",
|
||||
formVisible: false,
|
||||
userInfo: {},
|
||||
key: +new Date(),
|
||||
toDay: '',
|
||||
sysConfigInfo: {}
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.userInfo = uni.getStorageSync('userInfo') || {}
|
||||
this.sysConfigInfo = uni.getStorageSync('sysConfigInfo') || {}
|
||||
},
|
||||
onShow() {
|
||||
uni.$on('refresh', () => {
|
||||
this.key = +new Date()
|
||||
});
|
||||
},
|
||||
onUnload() {
|
||||
uni.$off('refresh')
|
||||
},
|
||||
methods: {
|
||||
/* 初始化请求 */
|
||||
initdate(cale, nowDate) {
|
||||
let canlender = cale.canlender;
|
||||
let weeks = cale.weeks;
|
||||
for (let i = 0; i < canlender.length; i++) {
|
||||
if (canlender[i].fullDate === nowDate.fullDate) {
|
||||
let day = this.toChinaDay(nowDate.lunar.nWeek)
|
||||
this.toDay = nowDate.fullDate
|
||||
this.dateTime = nowDate.fullDate
|
||||
this.dateDay = nowDate.month + '月' + nowDate.date + '日' + " 周" + day +
|
||||
" (今天)"
|
||||
this.changedate = ''
|
||||
if (this.sysConfigInfo.showLunarCalendar) this.changedate = '农历 ' + canlender[i].lunar.IMonthCn +
|
||||
canlender[i].lunar.IDayCn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let data = {
|
||||
weeks: weeks,
|
||||
canlender: canlender
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.handleScheduleList(data)
|
||||
})
|
||||
},
|
||||
handleScheduleList(data) {
|
||||
let canlender = data.canlender
|
||||
let startTime = this.startDate = canlender[0].lunar.cYear + '-' + canlender[0].lunar.cMonth + '-' +
|
||||
canlender[0].lunar
|
||||
.cDay;
|
||||
let endTime = this.endDate = canlender[canlender.length - 1].lunar.cYear + '-' + canlender[canlender
|
||||
.length - 1].lunar
|
||||
.cMonth + '-' + canlender[canlender.length - 1].lunar.cDay;
|
||||
let query = {
|
||||
startTime: startTime,
|
||||
endTime: endTime,
|
||||
dateTime: data.fulldate || this.toDay
|
||||
}
|
||||
List(query).then(res => {
|
||||
let signList = res.data.signList;
|
||||
if (res.data.todayList) {
|
||||
this.scheduleList = res.data.todayList.map(o => ({
|
||||
...o,
|
||||
show: false
|
||||
}));
|
||||
}
|
||||
let selected = []
|
||||
for (let [key, value] of Object.entries(signList)) {
|
||||
const cYear = key.slice(0, 4)
|
||||
const cMonth = key.slice(4, 6)
|
||||
const cDay = key.slice(6, 8)
|
||||
let date = cYear + '-' + cMonth + '-' + cDay
|
||||
if (value && value != 0) {
|
||||
selected.push({
|
||||
date,
|
||||
info: ''
|
||||
})
|
||||
}
|
||||
}
|
||||
this.selected = selected
|
||||
})
|
||||
},
|
||||
change(e) {
|
||||
let weeks = e.cale.weeks;
|
||||
let canlender = e.cale.canlender;
|
||||
let lunar = e.lunar;
|
||||
lunar.cMonth = lunar.cMonth < 10 ? '0' + Number(lunar.cMonth) : lunar.cMonth
|
||||
lunar.cDay = lunar.cDay < 10 ? '0' + Number(lunar.cDay) : lunar.cDay
|
||||
let allDay = lunar.lYear + '-' + lunar.cMonth + '-' + lunar.cDay
|
||||
let srt = this.time(e.fulldate)
|
||||
let day = this.toChinaDay(lunar.nWeek)
|
||||
this.startTime = new Date(e.fulldate).getTime()
|
||||
this.dateDay = lunar.cMonth + '月' + lunar.cDay + '日' + " 周" + day +
|
||||
srt
|
||||
this.changedate = ''
|
||||
if (this.sysConfigInfo.showLunarCalendar) this.changedate = '农历 ' + lunar.IMonthCn + lunar.IDayCn;
|
||||
let data = {
|
||||
weeks: weeks,
|
||||
canlender: canlender,
|
||||
lunar: lunar,
|
||||
fulldate: e.fulldate
|
||||
}
|
||||
this.handleScheduleList(data)
|
||||
},
|
||||
goDetail(id = '', creatorUserId) {
|
||||
let type = this.userInfo.userId == creatorUserId ? true : false
|
||||
let url = id ? `/pages/workFlow/schedule/detail?id=${id}&type=${type}` :
|
||||
`/pages/workFlow/schedule/form?id=${id}&startTime=${this.startTime}&duration=${this.sysConfigInfo.duration}`
|
||||
uni.navigateTo({
|
||||
url
|
||||
})
|
||||
},
|
||||
open(index) {
|
||||
this.scheduleList[index].show = true;
|
||||
this.scheduleList.map((val, idx) => {
|
||||
if (index != idx) this.scheduleList[idx].show = false;
|
||||
})
|
||||
},
|
||||
toChinaDay(d) {
|
||||
if (d == 1) return '一'
|
||||
if (d == 2) return '二'
|
||||
if (d == 3) return '三'
|
||||
if (d == 4) return '四'
|
||||
if (d == 5) return '五'
|
||||
if (d == 6) return '六'
|
||||
if (d == 7) return '日'
|
||||
},
|
||||
time(date) {
|
||||
let time = new Date()
|
||||
if (new Date(date).getFullYear() == time.getFullYear() && new Date(date).getMonth() == time.getMonth()) {
|
||||
let time_str = "";
|
||||
if (new Date(date).getDate() === new Date().getDate()) {
|
||||
time_str = " (今天)";
|
||||
} else if (new Date(date).getDate() === (new Date().getDate() - 1)) {
|
||||
time_str = " (昨天)";
|
||||
} else if (new Date(date).getDate() === (new Date().getDate() + 1)) {
|
||||
time_str = " (明天)";
|
||||
} else if (new Date(date).getDate() < new Date().getDate()) {
|
||||
time_str = "";
|
||||
}
|
||||
return time_str;
|
||||
}
|
||||
return ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #f0f2f6;
|
||||
}
|
||||
|
||||
.schedule-v {
|
||||
width: 100%;
|
||||
|
||||
.block {
|
||||
.block-a {
|
||||
background-color: #fff;
|
||||
padding: 20rpx 30rpx;
|
||||
}
|
||||
|
||||
.list-box {
|
||||
.list {
|
||||
.item {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
height: 120rpx;
|
||||
align-items: center;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
border-left: 4rpx solid #2A7DFD;
|
||||
justify-content: center;
|
||||
height: 80rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lunar1 {
|
||||
height: 124rpx;
|
||||
line-height: 124rpx;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.addlunar {
|
||||
height: 124rpx;
|
||||
line-height: 124rpx;
|
||||
border-top: 1rpx solid rgb(228, 231, 237);
|
||||
}
|
||||
|
||||
.add-title {
|
||||
margin-left: 20rpx;
|
||||
font-size: 24rpx;
|
||||
color: #C0C0C0;
|
||||
}
|
||||
}
|
||||
|
||||
.uni-calendar-item__weeks-box-item {
|
||||
height: 3.23rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
218
pages/workFlow/schedule/sendSelect/Select.vue
Normal file
@@ -0,0 +1,218 @@
|
||||
<template>
|
||||
<u-popup class="jnpf-tree-select-popup" :maskCloseAble="maskCloseAble" mode="right" v-model="showPopup"
|
||||
:safeAreaInsetBottom="safeAreaInsetBottom" @close="close" :z-index="uZIndex" width="100%">
|
||||
<view class="jnpf-tree-select-body">
|
||||
<view class="jnpf-tree-select-title">
|
||||
<view class="icon-ym icon-ym-report-icon-preview-pagePre u-font-40 backIcon" @tap="close()"></view>
|
||||
<view class="title">选择提醒</view>
|
||||
</view>
|
||||
<view class="jnpf-tree-select-search">
|
||||
<u-search :placeholder="$t('app.apply.pleaseKeyword')" v-model="keyword" height="72"
|
||||
:show-action="false" @change="search()" bg-color="#f0f2f6" shape="square">
|
||||
</u-search>
|
||||
</view>
|
||||
<view class="jnpf-tree-select-tree">
|
||||
<scroll-view style="height: 100%" :refresher-enabled="false" :refresher-threshold="100"
|
||||
:scroll-with-animation='true' :refresher-triggered="triggered" @scrolltolower="handleScrollToLower"
|
||||
:scroll-y="true">
|
||||
<view class="list-box" v-if="list.length">
|
||||
<radio-group class="list-item" :value="innerValue" v-for="(item,index) in list" :key="index"
|
||||
@change="radioChange(item)">
|
||||
<label class="radio-label">
|
||||
<radio class="u-radio" :value="item.id" :checked="item.id === selectId" />
|
||||
<view class="list-item-content u-line-1">{{item.fullName}}</view>
|
||||
</label>
|
||||
</radio-group>
|
||||
</view>
|
||||
<JnpfEmpty v-else></JnpfEmpty>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- 底部按钮 -->
|
||||
<view class="jnpf-bottom-actions">
|
||||
<u-button class="buttom-btn" @click="close()">取消</u-button>
|
||||
<u-button class="buttom-btn" type="primary" @click.stop="handleConfirm()">确定</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const defaultProps = {
|
||||
label: 'fullName',
|
||||
value: 'id',
|
||||
}
|
||||
import {
|
||||
getMsgTemplate
|
||||
} from '@/api/portal/portal.js'
|
||||
export default {
|
||||
props: {
|
||||
selectType: {
|
||||
type: String,
|
||||
default: 'all'
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
query: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
// 是否显示边框
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 通过双向绑定控制组件的弹出与收起
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// "取消"按钮的颜色
|
||||
cancelColor: {
|
||||
type: String,
|
||||
default: '#606266'
|
||||
},
|
||||
// "确定"按钮的颜色
|
||||
confirmColor: {
|
||||
type: String,
|
||||
default: '#2979ff'
|
||||
},
|
||||
// 弹出的z-index值
|
||||
zIndex: {
|
||||
type: [String, Number],
|
||||
default: 99999
|
||||
},
|
||||
safeAreaInsetBottom: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否允许通过点击遮罩关闭Picker
|
||||
maskCloseAble: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
//多选
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 顶部标题
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 取消按钮的文字
|
||||
cancelText: {
|
||||
type: String,
|
||||
default: '取消'
|
||||
},
|
||||
// 确认按钮的文字
|
||||
confirmText: {
|
||||
type: String,
|
||||
default: '确认'
|
||||
},
|
||||
selectedId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
keyword: '',
|
||||
selectList: [],
|
||||
list: [],
|
||||
pagination: {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
messageSource: 4
|
||||
},
|
||||
total: 0,
|
||||
triggered: false,
|
||||
innerValue: '',
|
||||
selectId: this.selectedId,
|
||||
showPopup: false
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
modelValue: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
this.showPopup = val
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
uZIndex() {
|
||||
// 如果用户有传递z-index值,优先使用
|
||||
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
|
||||
},
|
||||
realProps() {
|
||||
return {
|
||||
...defaultProps,
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
cleanAll() {
|
||||
this.selectList = [];
|
||||
},
|
||||
radioChange(item) {
|
||||
this.selectId = item.id;
|
||||
this.innerValue = item.id;
|
||||
this.selectList = item
|
||||
},
|
||||
search() {
|
||||
this.searchTimer && clearTimeout(this.searchTimer)
|
||||
this.searchTimer = setTimeout(() => {
|
||||
this.resetData()
|
||||
}, 300)
|
||||
},
|
||||
resetData() {
|
||||
this.list = []
|
||||
this.pagination = {
|
||||
currentPage: 1,
|
||||
pageSize: 20,
|
||||
messageSource: 4
|
||||
}
|
||||
this.upCallback()
|
||||
},
|
||||
handleScrollToLower() {
|
||||
if (this.pagination.pageSize * this.pagination.currentPage < this.total) {
|
||||
this.pagination.currentPage = this.pagination.currentPage + 1;
|
||||
this.upCallback()
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '没有更多信息啦!',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
upCallback() {
|
||||
let query = {
|
||||
currentPage: this.pagination.currentPage,
|
||||
pageSize: this.pagination.pageSize,
|
||||
keyword: this.keyword,
|
||||
messageSource: this.pagination.messageSource
|
||||
}
|
||||
this.loading = false
|
||||
getMsgTemplate(query).then(res => {
|
||||
const list = res.data.list;
|
||||
this.list = this.list.concat(list);
|
||||
this.pagination = res.data.pagination
|
||||
this.total = this.pagination.total
|
||||
let item = this.list.filter(o => o.id == this.selectId)[0]
|
||||
if (item) this.selectList = item
|
||||
})
|
||||
},
|
||||
handleConfirm() {
|
||||
this.keyword = '';
|
||||
this.$emit('confirm', this.selectList);
|
||||
this.close();
|
||||
},
|
||||
close() {
|
||||
this.$emit('close', false);
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
86
pages/workFlow/schedule/sendSelect/index.vue
Normal file
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<view class="jnpf-tree-select">
|
||||
<u-input input-align='right' type="select" :select-open="selectShow" v-model="innerValue"
|
||||
:placeholder="placeholder" @click="openSelect" />
|
||||
<Select v-model="selectShow" :selectedId="selectedId" ref="userTree" @close="handleClose()"
|
||||
@confirm="handleConfirm" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Select from './Select.vue';
|
||||
import {
|
||||
getMsgTemplate
|
||||
} from '@/api/portal/portal.js'
|
||||
import {
|
||||
login
|
||||
} from '@/api/common';
|
||||
export default {
|
||||
components: {
|
||||
Select
|
||||
},
|
||||
props: {
|
||||
modelValue: {
|
||||
default: ''
|
||||
},
|
||||
send: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择'
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
sendName: {
|
||||
type: String,
|
||||
default: '请选择'
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectShow: false,
|
||||
innerValue: '',
|
||||
selectedId: '',
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
send: {
|
||||
handler(val) {
|
||||
if (!val) return this.innerValue = ''
|
||||
this.setDefault(val)
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setDefault(id) {
|
||||
this.innerValue = this.modelValue
|
||||
this.selectedId = id
|
||||
},
|
||||
openSelect() {
|
||||
if (this.disabled) return
|
||||
this.selectShow = true
|
||||
this.$refs.userTree.resetData()
|
||||
},
|
||||
handleConfirm(e) {
|
||||
this.selectedId = e.id;
|
||||
this.defaultValue = e.id
|
||||
this.innerValue = e.fullName
|
||||
this.$emit('update:modelValue', e.id)
|
||||
this.$emit('change', e.id, e.fullName)
|
||||
},
|
||||
handleClose() {
|
||||
this.selectShow = false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.jnpf-tree-select {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
375
pages/workFlow/schedule/t-datetime.vue
Normal file
@@ -0,0 +1,375 @@
|
||||
<template>
|
||||
<view class="jnpf-dateTime">
|
||||
<u-input input-align='right' type="select" :select-open="selectShow" v-model="innerValue"
|
||||
:placeholder="placeholder" @click="openSelect" :disabled="disabled">
|
||||
</u-input>
|
||||
<u-popup v-model="selectShow" mode="bottom" @click="colse()">
|
||||
<view class="t-pop" @tap.stop>
|
||||
<view class="pop-main">
|
||||
<view class="top">
|
||||
<view class="top-l">
|
||||
<view @click="changeSwp('1')" :style="{color:sindex==1?'#1E79FF':'#333333'}">
|
||||
<text>{{checkyear}}</text>
|
||||
</view>
|
||||
<view @click="changeSwp('2')" :style="{color:sindex==2?'#1E79FF':'#333333'}"
|
||||
v-if="allDay==0">
|
||||
<text>{{checkhour}}:{{checkminute}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="top-r" @click="onOK()">
|
||||
<text>确定</text>
|
||||
</view>
|
||||
</view>
|
||||
<swiper class="swiper" circular :current-item-id="sindex">
|
||||
<swiper-item :item-id="'1'">
|
||||
<view class="mid">
|
||||
<scroll-view scroll-y="true" style="height: 960rpx" @scrolltolower="tolower">
|
||||
<uni-calendar ref="calendar" :insert="insert" :lunar='lunar'
|
||||
@change='calendarChange' :date='today' />
|
||||
</scroll-view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
<swiper-item :item-id="'2'" v-if="allDay==0">
|
||||
<picker-view :indicator-style="indicatorStyle" :value="swiperTime" @change="bindChange"
|
||||
class="picker-view">
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(v,i) in 24" :key="i">{{i<10?'0'+i:i}}时</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="item" v-for="(v,i) in 12" :key="i">{{i<2?'0'+i*5:i*5}}分
|
||||
</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "t-datetime",
|
||||
props: {
|
||||
type: {
|
||||
type: Number,
|
||||
default: 0 //默认时间后推0分钟
|
||||
},
|
||||
allDay: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
date: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择'
|
||||
},
|
||||
delayMin: {
|
||||
type: Number,
|
||||
default: 0 //默认时间后推0分钟
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
canToday: { //是否可选择当天之前的时间
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
textList: ['日', '一', '二', '三', '四', '五', '六'],
|
||||
mList: [],
|
||||
checkyear: 0,
|
||||
checkmonth: 0,
|
||||
checkdate: 0,
|
||||
checkhour: 0,
|
||||
checkminute: 0,
|
||||
indicatorStyle: `height: 50px;`,
|
||||
sindex: '1',
|
||||
nowYear: 0,
|
||||
nowMonth: 0,
|
||||
nowDate: 0,
|
||||
lunar: false,
|
||||
insert: true,
|
||||
innerValue: '',
|
||||
selectShow: false,
|
||||
swiperTime: [],
|
||||
year: 0,
|
||||
hours: '',
|
||||
minutes: '',
|
||||
today: ''
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
allDay(val) {
|
||||
let allTime = this.date.year + '-' + this.date.month + '-' + this.date.date
|
||||
this.today = allTime
|
||||
let srt = this.time(allTime)
|
||||
this.innerValue = ''
|
||||
if (srt) {
|
||||
this.innerValue = srt + this.date.month + '月' + this.date.date + '日'
|
||||
} else {
|
||||
if (this.date.year == this.year) {
|
||||
this.innerValue = this.date.month + '月' + this.date.date + '日'
|
||||
} else {
|
||||
this.innerValue = this.date.year + '年' + this.date.month + '月' + this.date.date + '日'
|
||||
}
|
||||
}
|
||||
if (this.allDay == 0) {
|
||||
this.innerValue = this.innerValue + ' ' + this.hours + ':' +
|
||||
this.minutes
|
||||
}
|
||||
},
|
||||
date(val) {
|
||||
this.init()
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.timestampToTime(+new Date())
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
tolower() {
|
||||
this.init()
|
||||
},
|
||||
openSelect() {
|
||||
if (this.disabled) return
|
||||
this.selectShow = true
|
||||
this.init()
|
||||
},
|
||||
calendarChange(e) {
|
||||
this.date.year = e.year
|
||||
this.date.month = e.month
|
||||
this.date.date = e.date
|
||||
this.date.date = this.date.date < 10 ? '0' + Number(this.date.date) : this.date.date
|
||||
this.date.month = this.date.month < 10 ? '0' + Number(this.date.month) : this.date.month
|
||||
this.checkyear = this.year == this.date.year ? this.date.month + '月' + this.date.date + '日' : this.date
|
||||
.year +
|
||||
'年' + this.date.month + '月' + this.date.date + '日'
|
||||
this.sindex = '2'
|
||||
},
|
||||
init() {
|
||||
this.innerValue = ''
|
||||
this.today = this.date.year + '-' + this.date.month + '-' + this.date.date
|
||||
this.date.minutes = this.date.minutes < 10 ? '0' + Number(this.date.minutes) : this.date.minutes
|
||||
this.date.hours = this.date.hours < 10 ? '0' + Number(this.date.hours) : this.date.hours
|
||||
this.date.date = this.date.date < 10 ? '0' + Number(this.date.date) : this.date.date
|
||||
this.date.month = this.date.month < 10 ? '0' + Number(this.date.month) : this.date.month
|
||||
this.checkyear = this.year == this.date.year ? this.date.month + '月' + this.date.date + '日' : this.date
|
||||
.year + '年' + this.date.month + '月' + this.date.date + '日'
|
||||
this.checkhour = this.date.hours
|
||||
this.checkminute = this.date.minutes < 10 ? '0' + Number(this.date.minutes) : this.date.minutes
|
||||
let checkminute = this.date.minutes / 5
|
||||
this.swiperTime = [Number(this.checkhour), checkminute]
|
||||
this.hours = this.date.hours
|
||||
this.minutes = this.date.minutes
|
||||
let allTime = this.date.year + '-' + this.date.month + '-' + this.date.date
|
||||
let srt = this.time(allTime)
|
||||
if (srt) {
|
||||
this.innerValue = srt + this.date.month + '月' + this.date.date + '日'
|
||||
} else {
|
||||
if (this.date.year == this.year) {
|
||||
this.innerValue = this.date.month + '月' + this.date.date + '日'
|
||||
} else {
|
||||
this.innerValue = this.date.year + '年' + this.date.month + '月' + this.date.date + '日'
|
||||
}
|
||||
}
|
||||
if (this.allDay == 0) {
|
||||
this.innerValue = this.innerValue + ' ' + this.hours + ':' +
|
||||
this.checkminute
|
||||
}
|
||||
|
||||
},
|
||||
colse() {
|
||||
this.selectShow = false
|
||||
},
|
||||
bindChange(e) {
|
||||
const val = e.detail.value
|
||||
this.swiperTime = [val[0], val[1]]
|
||||
this.checkhour = Number(val[0]) < 10 ? '0' + val[0] : val[0]
|
||||
this.checkminute = val[1] == '天' ? '00' : val[1] < 2 ? '0' + val[1] * 5 : val[1] * 5
|
||||
},
|
||||
changeSwp(i) {
|
||||
this.sindex = i
|
||||
},
|
||||
onOK() {
|
||||
if (this.allDay == 1) {
|
||||
this.date.hours = '00'
|
||||
this.date.minutes = '00'
|
||||
} else {
|
||||
this.date.hours = this.checkhour
|
||||
this.date.minutes = this.checkminute
|
||||
}
|
||||
this.selectShow = false
|
||||
let allTime = this.date.year + '-' + this.date.month + '-' + this.date.date
|
||||
let srt = this.time(allTime)
|
||||
if (srt) {
|
||||
this.innerValue = srt + this.date.month + '月' + this.date.date + '日'
|
||||
if (this.allDay == 0) {
|
||||
this.innerValue = this.innerValue + ' ' + this.date.hours +
|
||||
':' + this.date.minutes
|
||||
}
|
||||
} else {
|
||||
if (this.date.year == this.year) {
|
||||
this.innerValue = this.date.month + '月' + this.date.date + '日'
|
||||
} else {
|
||||
this.innerValue = this.date.year + '年' + this.date.month + '月' + this.date.date + '日'
|
||||
}
|
||||
if (this.allDay == 0) {
|
||||
this.innerValue = this.innerValue + ' ' + this.date.hours +
|
||||
':' + this.date.minutes
|
||||
}
|
||||
|
||||
}
|
||||
this.selectShow = false
|
||||
this.$emit('confirm', this.date, this.type)
|
||||
},
|
||||
timestampToTime(timestamp) {
|
||||
var date = new Date(timestamp);
|
||||
this.year = date.getFullYear();
|
||||
},
|
||||
time(date) {
|
||||
if (this.date.year != this.year) return false
|
||||
let time_str = "";
|
||||
if (new Date(date).getDate() === new Date().getDate()) {
|
||||
time_str = "今天 · ";
|
||||
} else if (new Date(date).getDate() === (new Date().getDate() - 1)) {
|
||||
time_str = "昨天 · ";
|
||||
} else if (new Date(date).getDate() === (new Date().getDate() + 1)) {
|
||||
time_str = "明天 · ";
|
||||
} else if (new Date(date).getDate() < new Date().getDate()) {
|
||||
time_str = "";
|
||||
}
|
||||
return time_str;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.jnpf-dateTime {
|
||||
width: 100%;
|
||||
|
||||
:deep(.u-drawer) {
|
||||
z-index: 999 !important;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.uni-calendar-item__weeks-box-item) {
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
.t-pop {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.pop-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
border-radius: 24px;
|
||||
height: 900rpx;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.swiper {
|
||||
height: 840rpx;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin: 20rpx 0;
|
||||
|
||||
.top-l {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-left: 30rpx;
|
||||
}
|
||||
|
||||
.top-r {
|
||||
margin-right: 30rpx;
|
||||
color: #1E79FF;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.calendar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
width: 100vw;
|
||||
position: relative;
|
||||
|
||||
}
|
||||
|
||||
.ca-top {
|
||||
width: 14.2vw;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 66rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.cell {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
border-radius: 30rpx;
|
||||
}
|
||||
|
||||
.cell-active {
|
||||
background-color: #1E79FF;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.cabg {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100vw;
|
||||
font-size: 180rpx;
|
||||
color: beige;
|
||||
position: absolute;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.picker-view {
|
||||
width: 750rpx;
|
||||
height: 600rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.item {
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
BIN
pages/workFlow/static/emoji/100.gif
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
pages/workFlow/static/emoji/101.gif
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
pages/workFlow/static/emoji/102.gif
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
pages/workFlow/static/emoji/103.gif
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
pages/workFlow/static/emoji/104.gif
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
pages/workFlow/static/emoji/105.gif
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
pages/workFlow/static/emoji/106.gif
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
pages/workFlow/static/emoji/107.gif
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
pages/workFlow/static/emoji/108.gif
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
pages/workFlow/static/emoji/109.gif
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
pages/workFlow/static/emoji/110.gif
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
pages/workFlow/static/emoji/111.gif
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
pages/workFlow/static/emoji/112.gif
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
pages/workFlow/static/emoji/113.gif
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
pages/workFlow/static/emoji/114.gif
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
pages/workFlow/static/emoji/115.gif
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
pages/workFlow/static/emoji/116.gif
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
pages/workFlow/static/emoji/117.gif
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
pages/workFlow/static/emoji/118.gif
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
pages/workFlow/static/emoji/119.gif
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
pages/workFlow/static/emoji/120.gif
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
pages/workFlow/static/emoji/121.gif
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
pages/workFlow/static/emoji/122.gif
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
pages/workFlow/static/emoji/123.gif
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
pages/workFlow/static/emoji/124.gif
Normal file
|
After Width: | Height: | Size: 2.2 KiB |