sunlupeng 1 rok pred
rodič
commit
a7c177b0a9

+ 95 - 0
api/oa/universal.js

@@ -0,0 +1,95 @@
+import request from '@/utils/request'
+
+// 创建流程
+export function create(data) {
+  return request({
+    url: '/bpm/oa-universal/commit',
+    method: 'post',
+    data: data
+  })
+}
+//驳回或撤回后再次提交通用用事项审批流程信息
+export function reCommit(data) {
+  return request({
+    url: '/bpm/oa-universal/reCommit',
+    method: 'post',
+    data: data
+  })
+}
+// 暂存数据保存
+export function save(data) {
+  return request({
+    url: '/bpm/oa-universal/staging',
+    method: 'post',
+    data: data
+  })
+}
+// 暂存数据删除
+export function deleteById(id) {
+  return request({
+    url: '/bpm/oa-universal/delete?id=' + id,
+    method: 'delete'
+  })
+}
+
+// 关闭审批流程信息
+export function closeById(id) {
+  return request({
+    url: '/bpm/oa-universal/close?id=' + id,
+    method: 'delete'
+  })
+}
+
+// 获得详情
+export function getDetail(id) {
+  return request({
+    url: '/bpm/oa-universal/get?id=' + id,
+    method: 'get'
+  })
+}
+
+// 获得列表
+export function getListData(query) {
+  return request({
+    url: '/bpm/oa-universal/page',
+    method: 'get',
+    params: query
+  })
+}
+// 导出列表
+export function exportList(query) {
+  return request({
+    url: '/bpm/oa-universal/export-excel',
+    method: 'get',
+    params: query,
+    responseType: 'blob'
+  })
+}
+
+//审批同意通用事项审批流程信息
+export function agree(data) {
+  return request({
+    url: '/bpm/oa-universal/agree',
+    method: 'post',
+    data: data
+  })
+}
+
+//驳回通用事项审批流程信息
+export function disagree(data) {
+  return request({
+    url: '/bpm/oa-universal/disagree',
+    method: 'post',
+    data: data
+  })
+}
+
+//撤回通用事项审批流程信息
+export function revocation(data) {
+  return request({
+    url: '/bpm/oa-universal/revocation',
+    method: 'post',
+    data: data
+  })
+}
+

+ 19 - 0
api/peopleSelect/index.js

@@ -0,0 +1,19 @@
+import request from '@/utils/request'
+
+// 获取部门精简信息列表
+export function listSimpleDepts() {
+  return request({
+    url: '/system/dept/list-all-simple',
+    method: 'get'
+  })
+}
+
+// 获得可选择的员工信息列表,用于选择业务人或审批人等   auth是否有权限,0无 1有
+export function listForSelectEmployee(query) {
+  return request({
+    url: '/personnel/employee/listForSelectEmployee',
+    method: 'get',
+    params: query
+  })
+}
+  

+ 45 - 0
components/my-popup/keypress.js

@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+  name: 'Keypress',
+  props: {
+    disable: {
+      type: Boolean,
+      default: false
+    }
+  },
+  mounted () {
+    const keyNames = {
+      esc: ['Esc', 'Escape'],
+      tab: 'Tab',
+      enter: 'Enter',
+      space: [' ', 'Spacebar'],
+      up: ['Up', 'ArrowUp'],
+      left: ['Left', 'ArrowLeft'],
+      right: ['Right', 'ArrowRight'],
+      down: ['Down', 'ArrowDown'],
+      delete: ['Backspace', 'Delete', 'Del']
+    }
+    const listener = ($event) => {
+      if (this.disable) {
+        return
+      }
+      const keyName = Object.keys(keyNames).find(key => {
+        const keyName = $event.key
+        const value = keyNames[key]
+        return value === keyName || (Array.isArray(value) && value.includes(keyName))
+      })
+      if (keyName) {
+        // 避免和其他按键事件冲突
+        setTimeout(() => {
+          this.$emit(keyName, {})
+        }, 0)
+      }
+    }
+    document.addEventListener('keyup', listener)
+    this.$once('hook:beforeDestroy', () => {
+      document.removeEventListener('keyup', listener)
+    })
+  },
+	render: () => {}
+}
+// #endif

+ 22 - 0
components/my-popup/message.js

@@ -0,0 +1,22 @@
+export default {
+	created() {
+		if (this.type === 'message') {
+			// 不显示遮罩
+			this.maskShow = false 
+			// 获取子组件对象
+			this.childrenMsg = null
+		}
+	},
+	methods: {
+		customOpen() {
+			if (this.childrenMsg) {
+				this.childrenMsg.open()
+			}
+		},
+		customClose() {
+			if (this.childrenMsg) {
+				this.childrenMsg.close()
+			}
+		}
+	}
+}

+ 321 - 0
components/my-popup/my-popup.vue

@@ -0,0 +1,321 @@
+<template>
+	<view v-if="showPopup" class="uni-popup" :class="[popupstyle, isDesktop ? 'fixforpc-z-index' : '']"
+	 @touchmove.stop.prevent="clear">
+		<uni-transition v-if="maskShow" class="uni-mask--hook" :mode-class="['fade']" :styles="maskClass" :duration="duration"
+		 :show="showTrans" @click="onTap" />
+		<uni-transition :mode-class="ani" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
+			<view class="uni-popup__wrapper-box" @click.stop="clear">
+				<slot />
+			</view>
+		</uni-transition>
+		<!-- #ifdef H5 -->
+		<keypress v-if="maskShow" @esc="onTap" />
+		<!-- #endif -->
+	</view>
+</template>
+
+<script>
+	import popup from './popup.js'
+	// #ifdef H5
+	import keypress from './keypress.js'
+	// #endif
+	/**
+	 * PopUp 弹出层
+	 * @description 弹出层组件,为了解决遮罩弹层的问题
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+	 * @property {String} type = [top|center|bottom] 弹出方式
+	 * 	@value top 顶部弹出
+	 * 	@value center 中间弹出
+	 * 	@value bottom 底部弹出
+	 * 	@value message 消息提示
+	 * 	@value dialog 对话框
+	 * 	@value share 底部分享示例
+	 * @property {Boolean} animation = [ture|false] 是否开启动画
+	 * @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
+	 * @event {Function} change 打开关闭弹窗触发,e={show: false}
+	 */
+
+	export default {
+		name: 'uniPopup',
+		components: {
+			// #ifdef H5
+			keypress
+			// #endif
+		},
+		props: {
+			// 开启动画
+			animation: {
+				type: Boolean,
+				default: true
+			},
+			// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
+			// message: 消息提示 ; dialog : 对话框
+			type: {
+				type: String,
+				default: 'center'
+			},
+			// maskClick
+			maskClick: {
+				type: Boolean,
+				default: true
+			}
+		},
+		provide() {
+			return {
+				popup: this
+			}
+		},
+		mixins: [popup],
+		watch: {
+			/**
+			 * 监听type类型
+			 */
+			type: {
+				handler: function(newVal) {
+					this[this.config[newVal]]()
+				},
+				immediate: true
+			},
+			isDesktop: {
+				handler: function(newVal) {
+					this[this.config[this.type]]()
+				},
+				immediate: true
+			},
+			/**
+			 * 监听遮罩是否可点击
+			 * @param {Object} val
+			 */
+			maskClick: {
+				handler: function(val) {
+					this.mkclick = val
+				},
+				immediate: true
+			}
+		},
+		data() {
+			return {
+				duration: 300,
+				ani: [],
+				showPopup: false,
+				showTrans: false,
+				maskClass: {
+					'position': 'fixed',
+					'bottom': 0,
+					'top': 0,
+					'left': 0,
+					'right': 0,
+					'backgroundColor': 'rgba(0, 0, 0, 0.4)'
+				},
+				transClass: {
+					'position': 'fixed',
+					'left': 0,
+					'right': 0,
+				},
+				maskShow: true,
+				mkclick: true,
+				popupstyle: this.isDesktop ? 'fixforpc-top' : 'top'
+			}
+		},
+		created() {
+			this.mkclick = this.maskClick
+			if (this.animation) {
+				this.duration = 300
+			} else {
+				this.duration = 0
+			}
+		},
+		methods: {
+			clear(e) {
+				// TODO nvue 取消冒泡
+				e.stopPropagation()
+			},
+			open() {
+				this.showPopup = true
+				this.$nextTick(() => {
+					new Promise(resolve => {
+						clearTimeout(this.timer)
+						this.timer = setTimeout(() => {
+							this.showTrans = true
+							// fixed by mehaotian 兼容 app 端
+							this.$nextTick(() => {
+								resolve();
+							})
+						}, 50);
+					}).then(res => {
+						// 自定义打开事件
+						clearTimeout(this.msgtimer)
+						this.msgtimer = setTimeout(() => {
+							this.customOpen && this.customOpen()
+						}, 100)
+						this.$emit('change', {
+							show: true,
+							type: this.type
+						})
+					})
+				})
+			},
+			close(type) {
+				this.showTrans = false
+				this.$nextTick(() => {
+					this.$emit('change', {
+						show: false,
+						type: this.type
+					})
+					clearTimeout(this.timer)
+					// 自定义关闭事件
+					this.customOpen && this.customClose()
+					this.timer = setTimeout(() => {
+						this.showPopup = false
+					}, 300)
+				})
+			},
+			onTap() {
+				if (!this.mkclick) return
+				this.close()
+			},
+			/**
+			 * 顶部弹出样式处理
+			 */
+			top() {
+				this.popupstyle = this.isDesktop ? 'fixforpc-top' : 'top'
+				this.ani = ['slide-top']
+				this.transClass = {
+					'position': 'fixed',
+					'left': 0,
+					'right': 0,
+				}
+			},
+			/**
+			 * 底部弹出样式处理
+			 */
+			bottom() {
+				this.popupstyle = 'bottom'
+				this.ani = ['slide-bottom']
+				this.transClass = {
+					'position': 'fixed',
+					'left': 0,
+					'right': 0,
+					'bottom': 0
+				}
+			},
+			/**
+			 * 中间弹出样式处理
+			 */
+			center() {
+				this.popupstyle = 'center'
+				this.ani = ['zoom-out', 'fade']
+				this.transClass = {
+					'position': 'fixed',
+					/* #ifndef APP-NVUE */
+					'display': 'flex',
+					'flexDirection': 'column',
+					/* #endif */
+					'bottom': 0,
+					'left': 0,
+					'right': 0,
+					'top': 0,
+					'justifyContent': 'center',
+					'alignItems': 'center'
+				}
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	.uni-popup {
+		position: fixed;
+		/* #ifndef APP-NVUE */
+		z-index: 99;
+		/* #endif */
+	}
+
+	.fixforpc-z-index {
+		/* #ifndef APP-NVUE */
+		z-index: 999;
+		/* #endif */
+	}
+
+	.uni-popup__mask {
+		position: absolute;
+		top: 0;
+		bottom: 0;
+		left: 0;
+		right: 0;
+		background-color: $uni-bg-color-mask;
+		opacity: 0;
+	}
+
+	.mask-ani {
+		transition-property: opacity;
+		transition-duration: 0.2s;
+	}
+
+	.uni-top-mask {
+		opacity: 1;
+	}
+
+	.uni-bottom-mask {
+		opacity: 1;
+	}
+
+	.uni-center-mask {
+		opacity: 1;
+	}
+
+	.uni-popup__wrapper {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		position: absolute;
+	}
+
+	.top {
+		/* #ifdef H5 */
+		top: var(--window-top);
+		/* #endif */
+		/* #ifndef H5 */
+		top: 0;
+		/* #endif */
+	}
+
+	.fixforpc-top {
+		top: 0;
+	}
+
+	.bottom {
+		bottom: 0;
+	}
+
+	.uni-popup__wrapper-box {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		position: relative;
+		/* iphonex 等安全区设置,底部安全区适配 */
+		/* #ifndef APP-NVUE */
+		padding-bottom: constant(safe-area-inset-bottom);
+		padding-bottom: env(safe-area-inset-bottom);
+		/* #endif */
+	}
+
+	.content-ani {
+		// transition: transform 0.3s;
+		transition-property: transform, opacity;
+		transition-duration: 0.2s;
+	}
+
+
+	.uni-top-content {
+		transform: translateY(0);
+	}
+
+	.uni-bottom-content {
+		transform: translateY(0);
+	}
+
+	.uni-center-content {
+		transform: scale(1);
+		opacity: 1;
+	}
+</style>

+ 50 - 0
components/my-popup/popup.js

@@ -0,0 +1,50 @@
+import message from './message.js';
+// 定义 type 类型:弹出类型:top/bottom/center
+const config = {
+	// 顶部弹出
+	top: 'top',
+	// 底部弹出
+	bottom: 'bottom',
+	// 居中弹出
+	center: 'center',
+	// 消息提示
+	message: 'top',
+	// 对话框
+	dialog: 'center',
+	// 分享
+	share: 'bottom',
+}
+
+export default {
+	data() {
+		return {
+			config: config,
+			popupWidth: 0,
+			popupHeight: 0
+		}
+	},
+	mixins: [message],
+	computed: {
+		isDesktop() {
+			return this.popupWidth >= 500 && this.popupHeight >= 500
+		}
+	},
+	mounted() {
+		const fixSize = () => {
+			const {
+				windowWidth,
+				windowHeight,
+				windowTop
+			} = uni.getSystemInfoSync()
+			this.popupWidth = windowWidth
+			this.popupHeight = windowHeight + windowTop
+		}
+		fixSize()
+		// #ifdef H5
+		window.addEventListener('resize', fixSize)
+		this.$once('hook:beforeDestroy', () => {
+			window.removeEventListener('resize', fixSize)
+		})
+		// #endif
+	},
+}

+ 16 - 0
components/my-popup/share.js

@@ -0,0 +1,16 @@
+export default {
+	created() {
+		if (this.type === 'share') {
+			// 关闭点击
+			this.mkclick = false
+		}
+	},
+	methods: {
+		customOpen() {
+			console.log('share 打开了');
+		},
+		customClose() {
+			console.log('share 关闭了');
+		}
+	}
+}

+ 4 - 1
components/myUnits/purchaseUnit/unit.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class='my-unit'>
+	<view class='my-unit' @click="childClick">
 			<view class="unit-head">
 				<text style="font-weight: bold;font-size: 26upx;">{{info.title}}</text>
 			</view>
@@ -45,6 +45,9 @@
         methods:{
 			doDel(){
 				this.$store.commit("switch_loading")
+			},
+			childClick(){
+				this.$emit('faClick', this.info)
 			}
         },
 		computed:{

+ 76 - 0
components/wm-watermark.vue

@@ -0,0 +1,76 @@
+<template>
+	<!-- 水印 -->
+	<view class="watermark_big" :style='{height:height?height+"px":"100%"}'>
+		<view v-for="(item,index) in num" :key="index">
+			<view class="watermark-text" v-if="text != ''" :style="{opacity:opacity}"><text style='color: #efefef;font-size: 26rpx;'>{{text}}</text></view>
+			<image class="watermark-img" :src="imgUrl" mode="aspectFill" v-if="imgUrl !='' && text ==''" :style="{opacity:opacity}"></image>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name:'wm-watermark',
+		props:{
+			height:{
+				type:Number,//动态设置屏幕高度
+				default:0
+			},
+			text:{			//设置水印文字
+				type:String,
+				default:''
+			},
+			imgUrl:{		//设置水印图片
+				type:String,
+				default:''
+			},
+			opacity:{		//设置透明度
+				type:[Number,String],		
+				default:0.8
+			},
+			num:{			//设置水印数量
+				type:Number,
+				default:6
+			}
+		},
+		data() {
+			return {
+				
+			};
+		},
+	}
+</script>
+
+<style scoped>
+	
+.watermark_big{
+	position: fixed;
+	width: 750rpx;
+	top:0;
+	left: 0;
+	bottom: 0;
+	right: 0;
+	 /* pointer-events: none; */
+	z-index: 9999;
+	 /* display: flex; */
+	flex-wrap: wrap;
+	overflow: hidden;
+	flex-direction: column;
+}
+.watermark-text{
+		width: 250rpx;
+		height: 250rpx;
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		transform: rotate(-36deg);
+		z-index: 9999;
+		
+		 /* white-space: nowrap; */
+	}
+	.watermark-img{
+		width: 375rpx;
+		height: 375rpx;
+		z-index: 1;
+	}
+</style>

+ 645 - 0
js/data.js

@@ -0,0 +1,645 @@
+let resource = {
+	'choose': [{
+			"uid": "111111111111",
+			"uname": "王五",
+			"mobile": "18999999999",
+		}, {
+			"uid": "111111111112",
+			"uname": "王四",
+			"mobile": "18999999999",
+		},
+		{
+			"uid": "111111111113",
+			"uname": "王三",
+			"mobile": "18999999999",
+		},
+		{
+			"uid": "111111111114",
+			"uname": "王一",
+			"mobile": "18999999999",
+		},
+		{
+			"uid": "111111111115",
+			"uname": "王石",
+			"mobile": "18999999999",
+		},
+		{
+			"uid": "111111111116",
+			"uname": "王石头",
+			"mobile": "18999999999",
+		},
+		{
+			"uid": "111111111117",
+			"uname": "王石散",
+			"mobile": "18999999999",
+		}
+	],
+	"chooseUserNew": [{
+		"oid": "1",
+		"userList": [],
+		"children": [{
+			"oid": "1240606295896199168",
+			"userList": [{
+				"uid": "1281267314632708096",
+				"ddUserid": null,
+				"wxUnionid": null,
+				"userLoginName": "18990000008",
+				"mobile": "18990000008",
+				"oid": "1240606295896199168",
+				"userAddr": "",
+				"uname": "管理员01",
+				"oname": "塔格智汇"
+			}, {
+				"uid": "1281267512314449920",
+				"ddUserid": null,
+				"wxUnionid": null,
+				"userLoginName": "18990000007",
+				"mobile": "18990000007",
+				"oid": "1240606295896199168",
+				"userAddr": "",
+				"uname": "管理员02",
+				"oname": "塔格智汇"
+			}, {
+				"uid": "1281267808939823104",
+				"ddUserid": null,
+				"wxUnionid": null,
+				"userLoginName": "18990000006",
+				"mobile": "18990000006",
+				"oid": "1240606295896199168",
+				"userAddr": "",
+				"uname": "管理员03",
+				"oname": "塔格智汇"
+			}, {
+				"uid": "1281270063898316800",
+				"ddUserid": null,
+				"wxUnionid": null,
+				"userLoginName": "18990000005",
+				"mobile": "18990000005",
+				"oid": "1240606295896199168",
+				"userAddr": "",
+				"uname": "管理员04",
+				"oname": "塔格智汇"
+			}, {
+				"uid": "1281270472947814400",
+				"ddUserid": null,
+				"wxUnionid": null,
+				"userLoginName": "18990000006",
+				"mobile": "18990000006",
+				"oid": "1240606295896199168",
+				"userAddr": "11",
+				"uname": "管理员05",
+				"oname": "塔格智汇"
+			}, {
+				"uid": "1280425262332366848",
+				"ddUserid": null,
+				"wxUnionid": null,
+				"userLoginName": "18990000005",
+				"mobile": "18990000005",
+				"oid": "1240606295896199168",
+				"userAddr": "",
+				"uname": "管理员06",
+				"oname": "塔格智汇"
+			}, {
+				"uid": "1283508839768969216",
+				"ddUserid": null,
+				"wxUnionid": null,
+				"userLoginName": "18990000006",
+				"mobile": "18990000006",
+				"oid": "1240606295896199168",
+				"userAddr": "",
+				"uname": "管理员07",
+				"oname": "塔格智汇"
+			}],
+			"children": [{
+				"oid": "1240606357378238464",
+				"userList": [{
+					"uid": "1277884006771286016",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000007",
+					"mobile": "18990000007",
+					"oid": "1240606357378238464",
+					"userAddr": "",
+					"uname": "李三",
+					"oname": "办公室"
+				}, {
+					"uid": "1277884317862813696",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000008",
+					"mobile": "18990000008",
+					"oid": "1240606357378238464",
+					"userAddr": "",
+					"uname": "王三",
+					"oname": "办公室"
+				}, {
+					"uid": "1277884450641895424",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000009",
+					"mobile": "18990000009",
+					"oid": "1240606357378238464",
+					"userAddr": "",
+					"uname": "王四",
+					"oname": "办公室"
+				}, {
+					"uid": "1277884567717502976",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000010",
+					"mobile": "18990000010",
+					"oid": "1240606357378238464",
+					"userAddr": "",
+					"uname": "王五",
+					"oname": "办公室"
+				}, {
+					"uid": "1277884677415329792",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000011",
+					"mobile": "18990000011",
+					"oid": "1240606357378238464",
+					"userAddr": "",
+					"uname": "王瑞清",
+					"oname": "办公室"
+				}, {
+					"uid": "1277884790623789056",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000012",
+					"mobile": "18990000012",
+					"oid": "1240606357378238464",
+					"userAddr": "",
+					"uname": "蔡海成",
+					"oname": "办公室"
+				}, {
+					"uid": "1277884904411062272",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000013",
+					"mobile": "18990000013",
+					"oid": "1240606357378238464",
+					"userAddr": "",
+					"uname": "马利军",
+					"oname": "办公室"
+				}, {
+					"uid": "1277885013135810560",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000014",
+					"mobile": "18990000014",
+					"oid": "1240606357378238464",
+					"userAddr": "",
+					"uname": "李灵杰",
+					"oname": "办公室"
+				}, {
+					"uid": "1277885133420060672",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000015",
+					"mobile": "18990000015",
+					"oid": "1240606357378238464",
+					"userAddr": "",
+					"uname": "黎子源",
+					"oname": "办公室"
+				}, {
+					"uid": "1277896941161766912",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000016",
+					"mobile": "18990000016",
+					"oid": "1240606357378238464",
+					"userAddr": "",
+					"uname": "郭天乐",
+					"oname": "办公室"
+				}, {
+					"uid": "1280437881676091392",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000017",
+					"mobile": "18990000017",
+					"oid": "1240606357378238464",
+					"userAddr": "",
+					"uname": "马迪娜",
+					"oname": "办公室"
+				}, {
+					"uid": "1366319674584821760",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000018",
+					"mobile": "18990000018",
+					"oid": "1240606357378238464",
+					"userAddr": "",
+					"uname": "宋词",
+					"oname": "办公室"
+				}, {
+					"uid": "1385539598209355776",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000019",
+					"mobile": "18990000019",
+					"oid": "1240606357378238464",
+					"userAddr": "",
+					"uname": "出差",
+					"oname": "办公室"
+				}],
+				"children": [],
+				"opname": "塔格智汇",
+				"opid": "1240606295896199168",
+				"oname": "办公室"
+			}, {
+				"oid": "1240606368345721856",
+				"userList": [{
+					"uid": "1257324946863239168",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000020",
+					"mobile": "18990000020",
+					"oid": "1240606368345721856",
+					"userAddr": "",
+					"uname": "刘恩萁",
+					"oname": "售前事业部"
+				}, {
+					"uid": "1257883527970856960",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000021",
+					"mobile": "18990000021",
+					"oid": "1240606368345721856",
+					"userAddr": "",
+					"uname": "张杰",
+					"oname": "售前事业部"
+				}, {
+					"uid": "1277896593785315328",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000022",
+					"mobile": "18990000022",
+					"oid": "1240606368345721856",
+					"userAddr": "",
+					"uname": "李成龙",
+					"oname": "售前事业部"
+				}, {
+					"uid": "1277896830088208384",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000023",
+					"mobile": "18990000023",
+					"oid": "1240606368345721856",
+					"userAddr": "塔格智汇",
+					"uname": "蒲揆",
+					"oname": "售前事业部"
+				}, {
+					"uid": "1277896915438100480",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000024",
+					"mobile": "18990000024",
+					"oid": "1240606368345721856",
+					"userAddr": "",
+					"uname": "张思远",
+					"oname": "售前事业部"
+				}, {
+					"uid": "1277897406951809024",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000025",
+					"mobile": "18990000025",
+					"oid": "1240606368345721856",
+					"userAddr": "",
+					"uname": "张鹏冲",
+					"oname": "售前事业部"
+				}, {
+					"uid": "1277897491429285888",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000026",
+					"mobile": "18990000026",
+					"oid": "1240606368345721856",
+					"userAddr": "",
+					"uname": "杨帆",
+					"oname": "售前事业部"
+				}, {
+					"uid": "1277897579597750272",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000027",
+					"mobile": "18990000027",
+					"oid": "1240606368345721856",
+					"userAddr": "",
+					"uname": "王千",
+					"oname": "售前事业部"
+				}, {
+					"uid": "1277899506708471808",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000028",
+					"mobile": "18990000028",
+					"oid": "1240606368345721856",
+					"userAddr": "",
+					"uname": "林祥",
+					"oname": "售前事业部"
+				}, {
+					"uid": "1280438506853879808",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000029",
+					"mobile": "18990000029",
+					"oid": "1240606368345721856",
+					"userAddr": "",
+					"uname": "刘玥",
+					"oname": "售前事业部"
+				}, {
+					"uid": "1280438681609555968",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000030",
+					"mobile": "18990000030",
+					"oid": "1240606368345721856",
+					"userAddr": "",
+					"uname": "于克生",
+					"oname": "售前事业部"
+				}, {
+					"uid": "1280438919686639616",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000031",
+					"mobile": "18990000031",
+					"oid": "1240606368345721856",
+					"userAddr": "",
+					"uname": "王春莉",
+					"oname": "售前事业部"
+				}, {
+					"uid": "1280439434101248000",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000032",
+					"mobile": "18990000032",
+					"oid": "1240606368345721856",
+					"userAddr": "",
+					"uname": "唐紫煜",
+					"oname": "售前事业部"
+				}, {
+					"uid": "1377284674484707328",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000033",
+					"mobile": "18990000033",
+					"oid": "1240606368345721856",
+					"userAddr": null,
+					"uname": "辛雨洁",
+					"oname": "售前事业部"
+				}],
+				"children": [{
+					"oid": "1284037878438998016",
+					"userList": [{
+						"uid": "1277898208336502784",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000034",
+						"mobile": "18990000034",
+						"oid": "1284037878438998016",
+						"userAddr": "",
+						"uname": "李荣山",
+						"oname": "售前事业部"
+					}, {
+						"uid": "1277898734105092096",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000035",
+						"mobile": "18990000035",
+						"oid": "1284037878438998016",
+						"userAddr": "",
+						"uname": "王蒙",
+						"oname": "售前事业部"
+					}, {
+						"uid": "1277898953823707136",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000036",
+						"mobile": "18990000036",
+						"oid": "1284037878438998016",
+						"userAddr": "",
+						"uname": "赵菁舒",
+						"oname": "售前事业部"
+					}, {
+						"uid": "1277899614980235264",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000037",
+						"mobile": "18990000037",
+						"oid": "1284037878438998016",
+						"userAddr": "",
+						"uname": "潘  峰",
+						"oname": "售前事业部"
+					}],
+					"children": [],
+					"opname": "售前事业部",
+					"opid": "1240606368345721856",
+					"oname": "内勤组"
+				}],
+				"opname": "塔格智汇",
+				"opid": "1240606295896199168",
+				"oname": "售前事业部"
+			}, {
+				"oid": "1240606369176105984",
+				"userList": [],
+				"children": [{
+					"oid": "1284037942104338432",
+					"userList": [{
+						"uid": "1277898102623264768",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000038",
+						"mobile": "18990000038",
+						"oid": "1284037942104338432",
+						"userAddr": "",
+						"uname": "张一建",
+						"oname": "售后运维部"
+					}, {
+						"uid": "1280443693114970112",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000039",
+						"mobile": "18990000039",
+						"oid": "1284037942104338432",
+						"userAddr": "",
+						"uname": "徐恒磊",
+						"oname": "售后运维部"
+					}],
+					"children": [],
+					"opname": "售前事业部",
+					"opid": "1240606369176105984",
+					"oname": "售后运维部"
+				}, {
+					"oid": "1284038014472859648",
+					"userList": [{
+						"uid": "1277897961543655424",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000040",
+						"mobile": "18990000040",
+						"oid": "1284038014472859648",
+						"userAddr": "",
+						"uname": "王化金",
+						"oname": "安保部"
+					}, {
+						"uid": "1283975471687622656",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000041",
+						"mobile": "18990000041",
+						"oid": "1284038014472859648",
+						"userAddr": "",
+						"uname": "朱建斌",
+						"oname": "安保部"
+					}, {
+						"uid": "1369105483440381952",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000042",
+						"mobile": "18990000042",
+						"oid": "1284038014472859648",
+						"userAddr": "",
+						"uname": "王刚",
+						"oname": "安保部"
+					}],
+					"children": [],
+					"opname": "售前事业部",
+					"opid": "1240606369176105984",
+					"oname": "安保部"
+				}, {
+					"oid": "1284038078972866560",
+					"userList": [{
+						"uid": "1277897441529651200",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000043",
+						"mobile": "18990000043",
+						"oid": "1284038078972866560",
+						"userAddr": "",
+						"uname": "李雪英",
+						"oname": "政务学习办公室"
+					}, {
+						"uid": "1277899782219718656",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000044",
+						"mobile": "18990000044",
+						"oid": "1284038078972866560",
+						"userAddr": "",
+						"uname": "司永瑞",
+						"oname": "政务学习办公室"
+					}],
+					"children": [],
+					"opname": "售前事业部",
+					"opid": "1240606369176105984",
+					"oname": "政务学习办公室"
+				}, {
+					"oid": "1284038138737504256",
+					"userList": [{
+						"uid": "1277899429063516160",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000045",
+						"mobile": "18990000045",
+						"oid": "1284038138737504256",
+						"userAddr": "",
+						"uname": "吴磊",
+						"oname": "科技研发部"
+					}, {
+						"uid": "1289069610955509760",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000046",
+						"mobile": "18990000046",
+						"oid": "1284038138737504256",
+						"userAddr": "",
+						"uname": "池星璇",
+						"oname": "科技研发部"
+					}, {
+						"uid": "1289069897309032448",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000047",
+						"mobile": "18990000047",
+						"oid": "1284038138737504256",
+						"userAddr": "",
+						"uname": "李鑫威",
+						"oname": "科技研发部"
+					}, {
+						"uid": "1372727449900642304",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000048",
+						"mobile": "18990000048",
+						"oid": "1284038138737504256",
+						"userAddr": "",
+						"uname": "段钟琪",
+						"oname": "科技研发部"
+					}],
+					"children": [],
+					"opname": "外部事物管理办公室",
+					"opid": "1240606369176105984",
+					"oname": "科技研发部"
+				}, {
+					"oid": "1284046618542256128",
+					"userList": [{
+						"uid": "1277897109391106048",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000049",
+						"mobile": "18990000049",
+						"oid": "1284046618542256128",
+						"userAddr": "",
+						"uname": "沈建帅",
+						"oname": "采购部"
+					}, {
+						"uid": "1277897336588165120",
+						"ddUserid": null,
+						"wxUnionid": null,
+						"userLoginName": "18990000050",
+						"mobile": "18990000050",
+						"oid": "1284046618542256128",
+						"userAddr": "",
+						"uname": "张 力",
+						"oname": "采购部"
+					}],
+					"children": [],
+					"opname": "售前事业部",
+					"opid": "1240606369176105984",
+					"oname": "采购部"
+				}],
+				"opname": "塔格智汇",
+				"opid": "1240606295896199168",
+				"oname": "售前事业部"
+			}, {
+				"oid": "1240606369181587072",
+				"userList": [{
+					"uid": "1277904817062240256",
+					"ddUserid": null,
+					"wxUnionid": null,
+					"userLoginName": "18990000051",
+					"mobile": "18990000051",
+					"oid": "1240606369181587072",
+					"userAddr": "",
+					"uname": "薛定成",
+					"oname": "一楼办公室"
+				}],
+				"children": [],
+				"opname": "塔格智汇",
+				"opid": "1240606295896199168",
+				"oname": "一楼办公室"
+			}],
+			"opname": "部门管理",
+			"opid": "1",
+			"oname": "塔格智汇"
+		}],
+		"opname": null,
+		"opid": "0",
+		"oname": "部门管理"
+	}]
+
+
+}
+export default resource

+ 3 - 1
main.js

@@ -3,12 +3,14 @@ import App from './App'
 import store from './store' // store
 import plugins from './plugins' // plugins
 import './permission' // permission
-import { parseTime } from "@/utils/ruoyi";
+import { parseTime,handleTree,getFileType } from "@/utils/ruoyi";
 Vue.use(plugins)
 
 Vue.config.productionTip = false
 Vue.prototype.$store = store
 Vue.prototype.parseTime = parseTime
+Vue.prototype.handleTree = handleTree
+Vue.prototype.getFileType = getFileType
 
 App.mpType = 'app'
 

+ 6 - 1
pages.json

@@ -76,7 +76,12 @@
     "style": {
       "navigationBarTitleText": "通用审批"
     }
-  }],
+  },{
+			"path": "pages/popleSelect/choose",
+			"style": {
+				"navigationBarTitleText": "通讯录"
+			}
+		}],
   "tabBar": {
     "color": "#000000",
     "selectedColor": "#000000",

+ 3 - 1
pages/message/index.vue

@@ -19,7 +19,7 @@
 			</uni-list>
 		</scroll-view>
 		<view>
-			<!-- 普通弹窗 -->
+			<!-- 底部弹窗 -->
 			<uni-popup ref="popup" background-color="#fff" border-radius="10px 10px 0 0">
 				<view class="popup-body">
 					<view class="popup-close">
@@ -93,12 +93,14 @@
 			handleUpdate(ids) {
 				updateNotifyMessageRead(ids).then(response => {
 					// this.$modal.msgSuccess("消息已读!")
+					this.page = 1;
 					this.getList(this.page, this.__pulldone)
 				});
 			},
 			handleUpdateAll() {
 				updateAllNotifyMessageRead().then(response => {
 					this.$modal.msgSuccess("全部已读!")
+					this.page = 1;
 					this.getList(this.page, this.__pulldone)
 				});
 			},

+ 8 - 18
pages/oa/dataList.vue

@@ -1,15 +1,15 @@
 <template>
-	<view class='my-unit'>
+	<view class='my-unit' @click="childClick">
 		<view class="unit-head">
-			<text style="font-weight: bold;font-size: 26upx;">{{ info.title }}</text>
+			<text style="font-weight: bold;font-size: 26upx;">{{ info.oaType }}</text>
 			<text style="color: gray;font-size: 20upx;">{{ parseTime(info.time) }}</text>
 		</view>
 		<view class="unit-body">
-			<text class="uni-ellipsis-1">事项标题:{{ info.status }}</text>
-			<text class="uni-ellipsis-1">详细描述:{{ info.status }}</text>
+			<text class="uni-ellipsis-1">事项标题:{{ info.title }}</text>
+			<text class="uni-ellipsis-1">详细描述:{{ info.remarks }}</text>
 		</view>
 		<view class="unit-foot">
-			<text>{{ initIndex == 2 ? '当前处理人' : '发起人' }}</text>
+			<text>{{ info.status }}</text>
 			<text style="color: orange;">{{ info.nickname }}</text>
 		</view>
 	</view>
@@ -27,21 +27,11 @@ export default {
 		}
 	},
 	data() {
-		return {
-			unitModel1: [
-				{ prop: "", label: "匹配商铺数" },
-				{ prop: "", label: "已报价商铺数" },
-				{ prop: "", label: "最新报价", class: "color-red", isMoney: true },
-				{ prop: "", label: "商品报价", class: "color-999", isMoney: true },
-				{ prop: "", label: "税点", class: "color-999" },
-				{ prop: "", label: "税费", class: "color-999", isMoney: true },
-				{ prop: "", label: "运费", class: "color-999", isMoney: true },
-			]
-		}
+		return {}
 	},
 	methods: {
-		doDel() {
-			this.$store.commit("switch_loading")
+		childClick(){
+			this.$emit('faClick', this.info)
 		}
 	},
 	computed: {

+ 344 - 0
pages/oa/universal/detail.vue

@@ -0,0 +1,344 @@
+<template>
+	<view class="container">
+		<uni-forms ref="form" :model="form" labelWidth="80px" :label-position="alignment">
+			<uni-forms-item label="申请人">
+				<uni-easyinput v-model="userInfo.nickname" disabled />
+			</uni-forms-item>
+			<uni-forms-item label="部门">
+				<uni-easyinput v-model="userInfo.deptName" disabled />
+			</uni-forms-item>
+			<uni-forms-item label="职位">
+				<uni-easyinput v-model="userInfo.position" disabled />
+			</uni-forms-item>
+			<uni-forms-item label="手机号">
+				<uni-easyinput v-model="userInfo.mobile" disabled />
+			</uni-forms-item>
+			<uni-forms-item label="事项标题" required name="title">
+				<uni-easyinput maxlength="20" v-model="form.title" disabled />
+			</uni-forms-item>
+			<uni-forms-item label="详细描述" required name="description">
+				<uni-easyinput autoHeight maxlength="200" type="textarea" v-model="form.description" disabled />
+			</uni-forms-item>
+			<uni-forms-item label="附件">
+				<view class="upload-wrap">
+					<view class="mgb-16 file-wrap" v-for="(item, index) in form.fileList" :key="index">
+					  <view class="btn-click file-line" @click="handlePreview(item)">
+					    <view class="file-info">
+					      <image :src="icons.file" mode="aspectFill" class="file-icon" />
+					      <text class="file-name">{{ item.name || title[type] }}</text>
+					    </view>
+					  </view>
+					</view>
+				</view>
+			</uni-forms-item>
+			<uni-forms-item label="备注">
+				<uni-easyinput autoHeight maxlength="200" type="textarea" v-model="form.remarks" disabled />
+			</uni-forms-item>
+			<uni-forms-item label="审批意见" required v-if="(form.auditStatus==2 || form.auditStatus==1) && name=='0'">
+				<uni-easyinput autoHeight maxlength="200" type="textarea" v-model="reason" placeholder="请输入审批建议" />
+			</uni-forms-item>
+			<uni-forms-item label="流程动态">
+				<uni-steps active-icon="medal" :options="tasks" active-color="#007AFF" :active="tasks.length" direction="column" />
+			</uni-forms-item>
+		</uni-forms>
+		<view class="button-group" v-if="name=='0'">
+			<button type="primary" size="mini" @click="handleAudit(true)">同意</button>
+			<button size="mini" @click="handleAudit(false)">驳回</button>
+		</view>
+		<view class="button-group" v-if="name=='2'">
+			<button type="warning" size="mini" @click="handleRevocation('form')">撤回</button>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { getDetail,revocation,agree,disagree } from "@/api/oa/universal.js"
+	export default {
+		props: {
+		    id: {
+		      type: [String, Number],
+		      default: undefined
+		    },
+		    name: {
+		      type: String,
+		      default: undefined
+		    },
+		  },
+		data() {
+			return {
+				reason:'',
+				active: -1,
+				tasks: [],
+				userInfo:uni.getStorageSync('userInfo'),
+				alignment:'top',
+				fileList: [],
+				icons: {
+				  file: '/static/icon_file.png',
+				},
+				// 表单数据
+				form: {},
+			}
+		},
+		watch: {
+		    id: {
+		      immediate: true,
+		      handler(val) {
+		        this.getDetail(val);
+		      }
+		    }
+		  },
+		methods: {
+			  /** 获得详情信息 */
+			    getDetail(val) {
+			      getDetail(val).then(response => {
+			        this.form = response.data;
+			        let auditRecordList = response.data.auditRecordList;
+					let tasks = [];
+					auditRecordList.forEach(v => {
+						tasks.push({
+							title:'任务:' + v.assigneeUser.nickname + v.name,
+							desc:this.parseTime(v.endTime),
+						})
+					})
+					this.tasks = tasks;
+			      });
+			    },
+			// 预览
+			handlePreview(val) {
+			  console.log('PreviewFile', val);
+			  const fileType = this.getFileType(val.name);
+			  if (fileType === 'image') {
+			   uni.previewImage({
+			     current: 0,
+			     urls: [val.url],
+			   });
+			  }
+			  else if (fileType === 'office') {
+				  return uni.downloadFile({
+				    url: val.url, 
+				    success: function (res) {
+				      let filePath = res.filePath || res.tempFilePath;
+				      uni.openDocument({
+				        filePath: filePath,
+				        showMenu: true,
+				        success: function (res) {
+				          console.log('打开文档成功');
+				        }
+				      });
+				    }
+				  });
+			  }
+			  else{
+				  uni.showModal({
+				    title: '该类型文件无法预览',
+				    content: val.name,
+				    showCancel: false,
+				  });
+			  }
+			  
+			},
+			handleRevocation(){
+			      console.log(this.form.taskId);
+				  let that = this
+				  uni.showModal({
+				          title: '提示',
+				          content: '是否确认撤回?',
+				          success: function (res) {
+				            if (res.confirm) {
+				              console.log('用户点击确定');
+				              revocation({id:that.form.taskId}).then(response => {
+				               uni.showToast({
+				               	title: "撤回成功!"
+				               })
+				              })
+				            } else if (res.cancel) {
+				              console.log('用户点击取消');
+				            }
+				          }
+				        });
+			    },
+			    handleAudit(pass) {
+			      if (!this.reason) {
+					uni.showModal({
+						title: "提示",
+						content: "请填写审批意见",
+						showCancel: false,
+						confirmText: "确定"
+					})
+			        return;
+			      } else {
+			        const data = {
+			          id: this.form.taskId,
+			          reason: this.reason,
+			        }
+			        if (pass) {
+			          agree(data).then(response => {
+						  uni.showToast({
+						  	title: "审批通过成功!"
+						  })
+						  this.$emit('popupClose');
+			          });
+			        } else {
+			          disagree(data).then(response => {
+						  uni.showToast({
+						  	title: "驳回成功!"
+						  })
+						  this.$emit('popupClose');
+			          });
+			        }
+			      }
+			    },
+			
+			
+		}
+	}
+</script>
+
+<style lang="scss">
+	.container {
+		padding: 15px;
+		background-color: #fff;
+	}
+
+	.segmented-control {
+		margin-bottom: 15px;
+	}
+
+	.button-group {
+		margin-top: 15px;
+		display: flex;
+	}
+
+	.form-item {
+		display: flex;
+		align-items: center;
+		flex: 1;
+	}
+
+	.button {
+		display: flex;
+		align-items: center;
+		height: 35px;
+		line-height: 35px;
+		margin-left: 10px;
+	}
+</style>
+<style lang="scss" scoped>
+	.user-avatar {
+	  width: 22px;
+	  height: 22px;
+	  line-height: 19px;
+	  font-size: 12px;
+	  background: #46c26f;
+	  border: 1px solid transparent;
+	  border-radius: 5px;
+	  color: #fff;
+	  display: inline-block;
+	  overflow: hidden;
+	  text-align: center;
+	  line-height: 22px;
+	  margin-bottom: 2px;
+	}
+	.popup-body{
+		z-index: 99;
+		height: 450px;
+		overflow-x: auto;
+		// margin-bottom: 60px;
+	}
+	.popup-close{
+		cursor: pointer;
+		height: 40px;
+		line-height: 40px;
+		padding-left: 10px;
+		border-bottom: 1px solid #eaecef;
+	}
+	.popup-content{
+		margin: 20px;
+	}
+.btn-click {
+  transition: all 0.3s;
+  opacity: 1;
+}
+
+.btn-click:active {
+  opacity: 0.5;
+}
+
+.mgb-16 {
+  margin-bottom: 16rpx;
+
+  &:last-child {
+    margin-bottom: 0;
+  }
+}
+
+.upload-wrap {
+  width: 100%;
+  border-radius: 16rpx;
+  background: white;
+  // padding: 32rpx;
+
+  .upload-btn {
+    width: 100%;
+    height: 176rpx;
+    border: 2rpx dashed #AAAAAA;
+    background: #FAFAFA;
+    border-radius: 16rpx;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+
+    .upload-icon {
+      width: 48rpx;
+      height: 48rpx;
+      margin-bottom: 8rpx;
+    }
+
+    .upload-text {
+      font-size: 26rpx;
+      color: #9E9E9E;
+      line-height: 40rpx;
+    }
+  }
+
+  .file-wrap {
+    .file-line {
+      width: 100%;
+      background: #F5F5F5;
+      border-radius: 8rpx;
+      padding: 16rpx;
+      font-size: 26rpx;
+      color: #1A1A1A;
+      line-height: 40rpx;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+
+      .file-info {
+        width: 90%;
+        display: flex;
+        align-items: center;
+
+        .file-name {
+          max-width: 80%;
+          padding-left: 16rpx;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+        }
+      }
+
+      .file-icon {
+        width: 40rpx;
+        height: 40rpx;
+        flex-shrink: 0;
+      }
+
+      .file-empty {
+        color: #999999;
+      }
+    }
+  }
+}
+</style>

+ 548 - 0
pages/oa/universal/edit.vue

@@ -0,0 +1,548 @@
+<template>
+	<view class="container">
+		<uni-forms ref="form" :rules="rules" :model="form" labelWidth="80px" :label-position="alignment">
+			<uni-forms-item label="申请人">
+				<uni-easyinput v-model="userInfo.nickname" disabled />
+			</uni-forms-item>
+			<uni-forms-item label="部门">
+				<uni-easyinput v-model="userInfo.deptName" disabled />
+			</uni-forms-item>
+			<uni-forms-item label="职位">
+				<uni-easyinput v-model="userInfo.position" disabled />
+			</uni-forms-item>
+			<uni-forms-item label="手机号">
+				<uni-easyinput v-model="userInfo.mobile" disabled />
+			</uni-forms-item>
+			<uni-forms-item label="事项标题" required name="title">
+				<uni-easyinput maxlength="20" v-model="form.title" placeholder="请输入申请的简要标题" />
+			</uni-forms-item>
+			<uni-forms-item label="详细描述" required name="description">
+				<uni-easyinput maxlength="200" type="textarea" v-model="form.description" placeholder="请输入详细描述" />
+			</uni-forms-item>
+			<uni-forms-item label="附件">
+				<view class="upload-wrap">
+					<button type="primary" size="mini" @click="handleUploadClick">点击上传</button>
+					<xe-upload ref="XeUpload" :options="uploadOptions" @callback="handleUploadCallback"></xe-upload>
+					<view class="mgb-16 file-wrap" v-for="(item, index) in fileList" :key="index">
+						<view class="btn-click file-line" @click="handlePreview(item)">
+							<view class="file-info">
+								<image :src="icons.file" mode="aspectFill" class="file-icon" />
+								<text class="file-name">{{ item.name || title[type] }}</text>
+							</view>
+							<image :src="icons.close" mode="aspectFill" class="file-icon"
+								@click.stop="handleDeleteFile(index)" />
+						</view>
+					</view>
+				</view>
+
+			</uni-forms-item>
+			<uni-forms-item label="备注">
+				<uni-easyinput maxlength="200" type="textarea" v-model="form.remarks" placeholder="请输入备注" />
+			</uni-forms-item>
+			<uni-forms-item label="审批人" required name="peopleList">
+				<uni-easyinput v-model="form.peopleList" style="display: none;" />
+				<view style="display: flex;justify-content: flex-start;align-items: center;">
+					<uni-icons type="folder-add" size="40" @click="gotochooseUser"></uni-icons>
+					<view style="display: flex;justify-content: flex-start;align-items: center;"
+						v-for="(tag, index) in nikeNamelist" :key="index">
+						<uni-icons type="right" size="20"></uni-icons>
+						<view style="display: flex;flex-direction: column;justify-content: center;align-items: center;"
+							@click="handleClose(index)">
+							<span class="user-avatar">{{ tag.substring(0, 1) || 'U' }}</span>
+							<text style="font-size: 12px;">{{tag}}</text>
+						</view>
+
+					</view>
+				</view>
+			</uni-forms-item>
+			<uni-forms-item label="流程动态" v-if="tasks.length > 0">
+				<uni-steps active-icon="medal" :options="tasks" active-color="#007AFF" :active="tasks.length"
+					direction="column" />
+			</uni-forms-item>
+		</uni-forms>
+		<view class="button-group" v-if="name == '0'">
+			<button type="default" size="mini" @click="onReCommit('form')">提交</button>
+			<button type="primary" size="mini" @click="onClose()">关闭</button>
+		</view>
+		<view class="button-group" v-else>
+			<button type="primary" size="mini" @click="submit('form')">提交</button>
+			<button type="default" size="mini" @click="onSave()">暂存</button>
+			<button type="danger" size="mini" @click="onDelete()" v-if="form.auditStatus == 0">删除</button>
+		</view>
+
+		<view>
+			<!-- 普通弹窗 -->
+			<uni-popup ref="popup" background-color="#fff" border-radius="10px 10px 0 0">
+				<view class="popup-body">
+					<!-- <view class="popup-close">
+						<uni-icons type="closeempty" size="20" @click="popupClose"></uni-icons>
+					</view> -->
+					<view class="popup-content">
+						<pople-Select @submit="submitPeople"></pople-Select>
+					</view>
+				</view>
+
+			</uni-popup>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		getDetail,
+		create,
+		save,
+		deleteById,
+		closeById,
+		reCommit
+	} from "@/api/oa/universal.js"
+	import {
+		uploadFile
+	} from "@/api/system/user"
+	import popleSelect from '../../popleSelect/choose.vue'
+	export default {
+		components: {
+			popleSelect
+		},
+		props: {
+			id: {
+				type: [String, Number],
+				default: undefined
+			},
+			name: {
+				type: String,
+				default: undefined
+			},
+		},
+		data() {
+			return {
+				tasks: [],
+				userInfo: uni.getStorageSync('userInfo'),
+				alignment: 'top',
+				uploadOptions: {},
+				fileList: [],
+				icons: {
+					close: '/static/icon_close.png',
+					file: '/static/icon_file.png',
+				},
+				nikeNamelist: [],
+				// 表单数据
+				form: {
+					employeeName: undefined,
+					deptName: undefined,
+					position: undefined,
+					employeePhone: undefined,
+					title: undefined,
+					fileIdList: undefined,
+					remarks: undefined,
+					peopleList: '',
+				},
+				// 校验规则
+				rules: {
+					title: {
+						rules: [{
+							required: true,
+							errorMessage: '请输入申请的简要标题'
+						}, ]
+					},
+					description: {
+						rules: [{
+							required: true,
+							errorMessage: '请输入详细描述'
+						}, ]
+					},
+					peopleList: {
+						rules: [{
+							required: true,
+							errorMessage: '请选择审批人'
+						}, ]
+					},
+				},
+			}
+		},
+		  watch: {
+		    id: {
+		      immediate: true,
+		      handler(val) {
+		        if (val) {
+		          this.getDetail(val);
+		        }
+		      }
+		    }
+		  },
+		methods: {
+			/** 获得详情信息 */
+			getDetail(val) {
+				getDetail(val).then(response => {
+					this.form = response.data;
+					console.log(this.form);
+					this.fileList = response.data.fileList ? response.data.fileList : [];
+					let auditUserList = response.data.auditUserList;
+					if (auditUserList) {
+						let peopleList = [];
+						let nikeNamelist = [];
+						auditUserList.map(item => {
+							peopleList.push(item.id);
+							nikeNamelist.push(item.nickname)
+						});
+						this.$set(this.form, 'peopleList', peopleList.join(','));
+						this.nikeNamelist = nikeNamelist;
+					} else {
+						this.$set(this.form, 'peopleList', '');
+						this.nikeNamelist = [];
+					}
+					let auditRecordList = response.data.auditRecordList;
+					if (auditRecordList) {
+						let tasks = [];
+						auditRecordList.forEach(v => {
+							tasks.push({
+								title: '任务:' + v.assigneeUser.nickname + v.name,
+								desc: this.parseTime(v.endTime),
+							})
+						})
+						this.tasks = tasks;
+					}
+				});
+			},
+			// 关闭标签
+			handleClose(index) {
+				this.nikeNamelist.splice(index, 1);
+				let peopleList = this.form.peopleList.split(',');
+				peopleList.splice(index, 1);
+				this.form.peopleList = peopleList.join(',');
+			},
+			submitPeople(userList, nikeNamelist, userIdList) {
+				console.log(userList);
+				console.log(userIdList);
+				this.nikeNamelist = nikeNamelist;
+				this.form.peopleList = userIdList.join(',');
+				this.$refs.popup.close();
+			},
+			popupClose() {
+				this.$refs.popup.close();
+			},
+			gotochooseUser() {
+				this.$refs.popup.open('bottom');
+				// uni.navigateTo({
+				// 	url:'/pages/popleSelect/choose'
+				// })
+			},
+			handleUploadClick() {
+				this.$refs.XeUpload.upload('file');
+			},
+			handleUploadCallback(e) {
+				console.log('UploadCallback', e);
+				let data = {
+					filePath: e.data[0].tempFilePath
+				}
+				uploadFile(data).then(response => {
+					const tmpFiles = ([response.data] || []).map(({
+						id,
+						url,
+						name,
+						type
+					}) => {
+						return {
+							id,
+							url,
+							name,
+							type,
+						};
+					});
+					this.fileList.push(...tmpFiles);
+				})
+			},
+			// 预览
+			handlePreview(val) {
+				console.log('PreviewFile', val);
+				const fileType = this.getFileType(val.name);
+				if (fileType === 'image') {
+					uni.previewImage({
+						current: 0,
+						urls: [val.url],
+					});
+				} else if (fileType === 'office') {
+					return uni.downloadFile({
+						url: val.url,
+						success: function(res) {
+							let filePath = res.filePath || res.tempFilePath;
+							uni.openDocument({
+								filePath: filePath,
+								showMenu: true,
+								success: function(res) {
+									console.log('打开文档成功');
+								}
+							});
+						}
+					});
+				} else {
+					uni.showModal({
+						title: '该类型文件无法预览',
+						content: val.name,
+						showCancel: false,
+					});
+				}
+
+			},
+			handleDeleteFile(index) {
+				this.fileList.splice(index, 1);
+			},
+			submit(ref) {
+				this.$refs[ref].validate().then(res => {
+					this.form.startUserSelectAssignees = this.form.peopleList.split(',');
+					this.form.auditPass = true;
+					create(this.form).then(response => {
+						uni.showToast({
+							title: `提交成功`
+						})
+						if(this.id){
+							this.$emit('popupClose');
+						}else{
+							setTimeout(() => {
+								this.$router.go(0)
+							}, 500)
+						}
+						
+					}).catch(() => {
+						
+					});
+				}).catch(err => {
+					console.log('err', err);
+				})
+			},
+			//暂存
+			onSave() {
+				if (this.form.peopleList) {
+					this.form.startUserSelectAssignees = this.form.peopleList.split(',');
+				}
+				this.form.auditPass = false;
+				save(this.form).then(response => {
+					uni.showToast({
+						title: `暂存成功`
+					})
+					if(this.id){
+						this.$emit('popupClose');
+					}else{
+							setTimeout(() => {
+								this.$router.go(0)
+							}, 500)
+						}
+				}).catch(() => {
+					
+				});
+			},
+			//驳回或撤回后再次提交
+			    onReCommit(ref) {
+			      this.$refs[ref].validate().then(res => {
+			      	this.form.startUserSelectAssignees = this.form.peopleList.split(',');
+			      	this.form.auditPass = true;
+			      	reCommit(this.form).then(response => {
+						uni.showToast({
+							title: `提交成功`
+						})
+					  this.$emit('popupClose');
+			      	}).catch(() => {
+						
+					});
+			      }).catch(err => {
+			      	console.log('err', err);
+			      })
+			    },
+			//暂存删除
+			async onDelete() {
+				let that = this;
+				uni.showModal({
+					title: '提示',
+					content: '是否确认删除?',
+					success: function(res) {
+						if (res.confirm) {
+							console.log('用户点击确定');
+							deleteById(that.id).then(response => {
+								uni.showToast({
+									title: "删除成功!"
+								})
+								that.$emit('popupClose');
+							})
+						} else if (res.cancel) {
+							console.log('用户点击取消');
+						}
+					}
+				});
+			},
+			//暂存关闭
+			async onClose() {
+				let that = this;
+				uni.showModal({
+					title: '提示',
+					content: '是否确认关闭?',
+					success: function(res) {
+						if (res.confirm) {
+							console.log('用户点击确定');
+							closeById(that.id).then(response => {
+								uni.showToast({
+									title: "流程已关闭!"
+								})
+								that.$emit('popupClose');
+							})
+						} else if (res.cancel) {
+							console.log('用户点击取消');
+						}
+					}
+				});
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	.container {
+		padding: 15px;
+		background-color: #fff;
+	}
+
+	.segmented-control {
+		margin-bottom: 15px;
+	}
+
+	.button-group {
+		margin-top: 15px;
+		display: flex;
+	}
+
+	.form-item {
+		display: flex;
+		align-items: center;
+		flex: 1;
+	}
+
+	.button {
+		display: flex;
+		align-items: center;
+		height: 35px;
+		line-height: 35px;
+		margin-left: 10px;
+	}
+</style>
+<style lang="scss" scoped>
+	.user-avatar {
+		width: 22px;
+		height: 22px;
+		line-height: 19px;
+		font-size: 12px;
+		background: #46c26f;
+		border: 1px solid transparent;
+		border-radius: 5px;
+		color: #fff;
+		display: inline-block;
+		overflow: hidden;
+		text-align: center;
+		line-height: 22px;
+		margin-bottom: 2px;
+	}
+
+	.popup-body {
+		z-index: 99;
+		height: 450px;
+		overflow-x: auto;
+		// margin-bottom: 60px;
+	}
+
+	.popup-close {
+		cursor: pointer;
+		height: 40px;
+		line-height: 40px;
+		padding-left: 10px;
+		border-bottom: 1px solid #eaecef;
+	}
+
+	.popup-content {
+		margin: 20px;
+	}
+
+	.btn-click {
+		transition: all 0.3s;
+		opacity: 1;
+	}
+
+	.btn-click:active {
+		opacity: 0.5;
+	}
+
+	.mgb-16 {
+		margin-bottom: 16rpx;
+
+		&:last-child {
+			margin-bottom: 0;
+		}
+	}
+
+	.upload-wrap {
+		width: 100%;
+		border-radius: 16rpx;
+		background: white;
+		// padding: 32rpx;
+
+		.upload-btn {
+			width: 100%;
+			height: 176rpx;
+			border: 2rpx dashed #AAAAAA;
+			background: #FAFAFA;
+			border-radius: 16rpx;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			flex-direction: column;
+
+			.upload-icon {
+				width: 48rpx;
+				height: 48rpx;
+				margin-bottom: 8rpx;
+			}
+
+			.upload-text {
+				font-size: 26rpx;
+				color: #9E9E9E;
+				line-height: 40rpx;
+			}
+		}
+
+		.file-wrap {
+			.file-line {
+				width: 100%;
+				background: #F5F5F5;
+				border-radius: 8rpx;
+				padding: 16rpx;
+				font-size: 26rpx;
+				color: #1A1A1A;
+				line-height: 40rpx;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+
+				.file-info {
+					width: 90%;
+					display: flex;
+					align-items: center;
+
+					.file-name {
+						max-width: 80%;
+						padding-left: 16rpx;
+						overflow: hidden;
+						text-overflow: ellipsis;
+						white-space: nowrap;
+					}
+				}
+
+				.file-icon {
+					width: 40rpx;
+					height: 40rpx;
+					flex-shrink: 0;
+				}
+
+				.file-empty {
+					color: #999999;
+				}
+			}
+		}
+	}
+</style>

+ 0 - 331
pages/oa/universal/formCreate - 副本.vue

@@ -1,331 +0,0 @@
-<template>
-	<view class="container">
-		<uni-section title="">
-			<view class="example">
-				<!-- 基础用法,不包含校验规则 -->
-				<uni-forms ref="baseForm" :rules="rules" :model="baseFormData" labelWidth="80px" :label-position="alignment">
-					<uni-forms-item label="姓名" required>
-						<uni-easyinput v-model="baseFormData.name" placeholder="请输入姓名" disabled />
-					</uni-forms-item>
-					<uni-forms-item label="年龄" required>
-						<uni-easyinput v-model="baseFormData.age" placeholder="请输入年龄" />
-					</uni-forms-item>
-					<uni-forms-item label="性别" required>
-						<uni-data-checkbox v-model="baseFormData.sex" :localdata="sexs" />
-					</uni-forms-item>
-					<uni-forms-item label="兴趣爱好" required>
-						<uni-data-checkbox v-model="baseFormData.hobby" multiple :localdata="hobbys" />
-					</uni-forms-item>
-					<uni-forms-item label="自我介绍">
-						<uni-easyinput type="textarea" v-model="baseFormData.introduction" placeholder="请输入自我介绍" />
-					</uni-forms-item>
-					<uni-forms-item label="日期时间">
-						<uni-datetime-picker type="datetime" return-type="timestamp"
-							v-model="baseFormData.datetimesingle" />
-					</uni-forms-item>
-					<uni-forms-item label="选择城市">
-						<uni-data-picker v-model="baseFormData.city" :localdata="cityData" popup-title="选择城市">
-						</uni-data-picker>
-					</uni-forms-item>
-
-					<uni-forms-item label="选择技能">
-						<uni-data-select v-model="baseFormData.skills" :localdata="skillsRange" >
-						</uni-data-select>
-					</uni-forms-item>
-				</uni-forms>
-			</view>
-		</uni-section>
-
-		<uni-section title="表单校验" type="line">
-			<view class="example">
-				<!-- 基础表单校验 -->
-				<uni-forms ref="valiForm" :rules="rules" :model="valiFormData" labelWidth="80px" :label-position="alignment">
-					<uni-forms-item label="姓名" required name="name">
-						<uni-easyinput v-model="valiFormData.name" placeholder="请输入姓名" />
-					</uni-forms-item>
-					<uni-forms-item label="年龄" required name="age">
-						<uni-easyinput v-model="valiFormData.age" placeholder="请输入年龄" />
-					</uni-forms-item>
-					<uni-forms-item label="自我介绍">
-						<uni-easyinput type="textarea" v-model="valiFormData.introduction" placeholder="请输入自我介绍" />
-					</uni-forms-item>
-				</uni-forms>
-				<button type="primary" @click="submit('valiForm')">提交</button>
-			</view>
-		</uni-section>
-
-		<uni-section title="自定义校验规则" type="line">
-			<view class="example">
-				<!-- 自定义表单校验 -->
-				<uni-forms ref="customForm" :rules="customRules" labelWidth="80px" :modelValue="customFormData" :label-position="alignment">
-					<uni-forms-item label="姓名" required name="name">
-						<uni-easyinput v-model="customFormData.name" placeholder="请输入姓名" />
-					</uni-forms-item>
-					<uni-forms-item label="年龄" required name="age">
-						<uni-easyinput v-model="customFormData.age" placeholder="请输入年龄" />
-					</uni-forms-item>
-					<uni-forms-item label="兴趣爱好" required name="hobby">
-						<uni-data-checkbox v-model="customFormData.hobby" multiple :localdata="hobbys" />
-					</uni-forms-item>
-				</uni-forms>
-				<button type="primary" @click="submit('customForm')">提交</button>
-			</view>
-		</uni-section>
-
-
-		<uni-section title="动态表单" type="line">
-			<view class="example">
-				<!-- 动态表单校验 -->
-				<uni-forms ref="dynamicForm" :rules="dynamicRules" :model="dynamicFormData" labelWidth="80px" :label-position="alignment">
-					<uni-forms-item label="邮箱" required name="email">
-						<uni-easyinput v-model="dynamicFormData.email" placeholder="请输入姓名" />
-					</uni-forms-item>
-					<uni-forms-item v-for="(item,index) in dynamicFormData.domains" :key="item.id"
-						:label="item.label+' '+index" required :rules="item.rules" :name="['domains',index,'value']">
-						<view class="form-item">
-							<uni-easyinput v-model="dynamicFormData.domains[index].value" placeholder="请输入域名" />
-							<button class="button" size="mini" type="default" @click="del(item.id)">删除</button>
-						</view>
-					</uni-forms-item>
-				</uni-forms>
-				<view class="button-group">
-					<button type="primary" size="mini" @click="add">新增域名</button>
-					<button type="primary" size="mini" @click="submit('dynamicForm')">提交</button>
-				</view>
-			</view>
-		</uni-section>
-	</view>
-</template>
-
-<script>
-	export default {
-		data() {
-			return {
-				// 基础表单数据
-				baseFormData: {
-					name: '',
-					age: '',
-					introduction: '',
-					sex: 2,
-					hobby: [5],
-					datetimesingle: 1627529992399,
-					city: '',
-					skills: 0
-				},
-				// 城市数据
-				cityData: [{
-					text: "北京",
-					value: "10001",
-				}, {
-					text: "上海",
-					value: "10002",
-				}, {
-					text: "深圳",
-					value: "10004",
-				}],
-				skillsRange: [{
-						value: 0,
-						text: "编程"
-					},
-					{
-						value: 1,
-						text: "绘画"
-					},
-					{
-						value: 2,
-						text: "运动"
-					},
-				],
-				// 表单数据
-				alignmentFormData: {
-					name: '',
-					age: '',
-				},
-				// 单选数据源
-				sexs: [{
-					text: '男',
-					value: 0
-				}, {
-					text: '女',
-					value: 1
-				}, {
-					text: '保密',
-					value: 2
-				}],
-				// 多选数据源
-				hobbys: [{
-					text: '跑步',
-					value: 0
-				}, {
-					text: '游泳',
-					value: 1
-				}, {
-					text: '绘画',
-					value: 2
-				}, {
-					text: '足球',
-					value: 3
-				}, {
-					text: '篮球',
-					value: 4
-				}, {
-					text: '其他',
-					value: 5
-				}],
-				// 分段器数据
-				current: 0,
-				items: ['左对齐', '顶部对齐'],
-				// 校验表单数据
-				valiFormData: {
-					name: '',
-					age: '',
-					introduction: '',
-				},
-				// 校验规则
-				rules: {
-					name: {
-						rules: [{
-							required: true,
-							errorMessage: '姓名不能为空'
-						}]
-					},
-					age: {
-						rules: [{
-							required: true,
-							errorMessage: '年龄不能为空'
-						}, {
-							format: 'number',
-							errorMessage: '年龄只能输入数字'
-						}]
-					}
-				},
-				// 自定义表单数据
-				customFormData: {
-					name: '',
-					age: '',
-					hobby: []
-				},
-				// 自定义表单校验规则
-				customRules: {
-					name: {
-						rules: [{
-							required: true,
-							errorMessage: '姓名不能为空'
-						}]
-					},
-					age: {
-						rules: [{
-							required: true,
-							errorMessage: '年龄不能为空'
-						}]
-					},
-					hobby: {
-						rules: [{
-								format: 'array'
-							},
-							{
-								validateFunction: function(rule, value, data, callback) {
-									if (value.length < 2) {
-										callback('请至少勾选两个兴趣爱好')
-									}
-									return true
-								}
-							}
-						]
-					}
-
-				},
-				dynamicFormData: {
-					email: '',
-					domains: []
-				},
-				dynamicLists: [],
-				dynamicRules: {
-					email: {
-						rules: [{
-							required: true,
-							errorMessage: '域名不能为空'
-						}, {
-							format: 'email',
-							errorMessage: '域名格式错误'
-						}]
-					}
-				}
-			}
-		},
-		computed: {
-			// 处理表单排列切换
-			alignment() {
-				return 'top'
-			}
-		},
-		onLoad() {},
-		onReady() {
-			// 设置自定义表单校验规则,必须在节点渲染完毕后执行
-			this.$refs.customForm.setRules(this.customRules)
-		},
-		methods: {
-			onClickItem(e) {
-				console.log(e);
-				this.current = e.currentIndex
-			},
-			add() {
-				this.dynamicFormData.domains.push({
-					label: '域名',
-					value: '',
-					rules: [{
-						'required': true,
-						errorMessage: '域名项必填'
-					}],
-					id: Date.now()
-				})
-			},
-			del(id) {
-				let index = this.dynamicLists.findIndex(v => v.id === id)
-				this.dynamicLists.splice(index, 1)
-			},
-			submit(ref) {
-				console.log(this.baseFormData);
-				this.$refs[ref].validate().then(res => {
-					console.log('success', res);
-					uni.showToast({
-						title: `校验通过`
-					})
-				}).catch(err => {
-					console.log('err', err);
-				})
-			},
-		}
-	}
-</script>
-
-<style lang="scss">
-	.example {
-		padding: 15px;
-		background-color: #fff;
-	}
-
-	.segmented-control {
-		margin-bottom: 15px;
-	}
-
-	.button-group {
-		margin-top: 15px;
-		display: flex;
-		justify-content: space-around;
-	}
-
-	.form-item {
-		display: flex;
-		align-items: center;
-		flex: 1;
-	}
-
-	.button {
-		display: flex;
-		align-items: center;
-		height: 35px;
-		line-height: 35px;
-		margin-left: 10px;
-	}
-</style>

+ 0 - 256
pages/oa/universal/formCreate.vue

@@ -1,256 +0,0 @@
-<template>
-	<view class="container">
-		<uni-forms ref="form" :rules="rules" :model="form" labelWidth="80px" :label-position="alignment">
-			<uni-forms-item label="申请人">
-				<uni-easyinput v-model="form.employeeName" disabled />
-			</uni-forms-item>
-			<uni-forms-item label="部门">
-				<uni-easyinput v-model="form.deptName" disabled />
-			</uni-forms-item>
-			<uni-forms-item label="职位">
-				<uni-easyinput v-model="form.position" disabled />
-			</uni-forms-item>
-			<uni-forms-item label="手机号">
-				<uni-easyinput v-model="form.employeePhone" disabled />
-			</uni-forms-item>
-			<uni-forms-item label="事项标题" required name="title">
-				<uni-easyinput maxlength="20" v-model="form.title" placeholder="请输入申请的简要标题" />
-			</uni-forms-item>
-			<uni-forms-item label="详细描述" required name="description">
-				<uni-easyinput maxlength="200" type="textarea" v-model="form.description" placeholder="请输入详细描述" />
-			</uni-forms-item>
-			<uni-forms-item label="附件">
-				<view class="upload-wrap">
-					<button type="primary" size="mini" @click="handleUploadClick">点击上传</button>
-					<xe-upload ref="XeUpload" :options="uploadOptions" @callback="handleUploadCallback"></xe-upload>
-					<view class="mgb-16 file-wrap" v-for="(item, index) in fileList" :key="index">
-					  <view class="btn-click file-line" @click="handlePreview(item)">
-					    <view class="file-info">
-					      <image :src="icons.file" mode="aspectFill" class="file-icon" />
-					      <text class="file-name">{{ item.name || title[type] }}</text>
-					    </view>
-					    <image :src="icons.close" mode="aspectFill" class="file-icon"
-					      @click.stop="handleDeleteFile(index)" />
-					  </view>
-					</view>
-				</view>
-				
-			</uni-forms-item>
-			<uni-forms-item label="备注">
-				<uni-easyinput maxlength="200" type="textarea" v-model="form.remarks" placeholder="请输入备注" />
-			</uni-forms-item>
-		</uni-forms>
-		<view class="button-group">
-			<button type="primary" size="mini" @click="submit('form')">提交</button>
-		</view>
-	</view>
-</template>
-
-<script>
-  	import { uploadFile } from "@/api/system/user"
-	export default {
-		data() {
-			return {
-				alignment:'top',
-				uploadOptions: {},
-				fileList: [],
-				icons: {
-				  close: '/static/icon_close.png',
-				  file: '/static/icon_file.png',
-				},
-				// 表单数据
-				form: {
-					employeeName: undefined,
-					deptName: undefined,
-					position: undefined,
-					employeePhone: undefined,
-					title: undefined,
-					fileIdList: undefined,
-					remarks: undefined,
-					peopleList: '',
-				},
-				// 校验规则
-				rules: {
-					title: {
-						rules: [{
-							required: true,
-							errorMessage: '请输入申请的简要标题'
-						}, ]
-					},
-					description: {
-						rules: [{
-							required: true,
-							errorMessage: '请输入详细描述'
-						}, ]
-					}
-				},
-			}
-		},
-		onLoad() {},
-		methods: {
-			handleUploadClick() {
-			  this.$refs.XeUpload.upload('file');
-			},
-			handleUploadCallback(e) {
-			  console.log('UploadCallback', e);
-			  let data = { filePath: e.data[0].tempFilePath}
-			  uploadFile(data).then(response => {
-				const tmpFiles = ([response.data] || []).map(({ id, url, name, type }) => {
-				  return {
-					id,
-				    url,
-				    name,
-				    type,
-				  };
-				});
-				this.fileList.push(...tmpFiles);
-			  })
-			},
-			// 预览
-			handlePreview(val) {
-			  console.log('PreviewFile', val);
-			  if (val.type == 'image/png' || val.type == 'image/jpg') {
-			    return uni.previewImage({
-			      current: 0,
-			      urls: [val.url],
-			    });
-			  }else{
-				  
-			  }
-			},
-			handleDeleteFile(index) {
-			  this.fileList.splice(index, 1);
-			},
-			submit(ref) {
-				console.log(this.form);
-				this.$refs[ref].validate().then(res => {
-					console.log('success', res);
-					uni.showToast({
-						title: `校验通过`
-					})
-				}).catch(err => {
-					console.log('err', err);
-				})
-			},
-		}
-	}
-</script>
-
-<style lang="scss">
-	.container {
-		padding: 15px;
-		background-color: #fff;
-	}
-
-	.segmented-control {
-		margin-bottom: 15px;
-	}
-
-	.button-group {
-		margin-top: 15px;
-		display: flex;
-		justify-content: space-around;
-	}
-
-	.form-item {
-		display: flex;
-		align-items: center;
-		flex: 1;
-	}
-
-	.button {
-		display: flex;
-		align-items: center;
-		height: 35px;
-		line-height: 35px;
-		margin-left: 10px;
-	}
-</style>
-<style lang="scss" scoped>
-.btn-click {
-  transition: all 0.3s;
-  opacity: 1;
-}
-
-.btn-click:active {
-  opacity: 0.5;
-}
-
-.mgb-16 {
-  margin-bottom: 16rpx;
-
-  &:last-child {
-    margin-bottom: 0;
-  }
-}
-
-.upload-wrap {
-  width: 100%;
-  border-radius: 16rpx;
-  background: white;
-  // padding: 32rpx;
-
-  .upload-btn {
-    width: 100%;
-    height: 176rpx;
-    border: 2rpx dashed #AAAAAA;
-    background: #FAFAFA;
-    border-radius: 16rpx;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    flex-direction: column;
-
-    .upload-icon {
-      width: 48rpx;
-      height: 48rpx;
-      margin-bottom: 8rpx;
-    }
-
-    .upload-text {
-      font-size: 26rpx;
-      color: #9E9E9E;
-      line-height: 40rpx;
-    }
-  }
-
-  .file-wrap {
-    .file-line {
-      width: 100%;
-      background: #F5F5F5;
-      border-radius: 8rpx;
-      padding: 16rpx;
-      font-size: 26rpx;
-      color: #1A1A1A;
-      line-height: 40rpx;
-      display: flex;
-      align-items: center;
-      justify-content: space-between;
-
-      .file-info {
-        width: 90%;
-        display: flex;
-        align-items: center;
-
-        .file-name {
-          max-width: 80%;
-          padding-left: 16rpx;
-          overflow: hidden;
-          text-overflow: ellipsis;
-          white-space: nowrap;
-        }
-      }
-
-      .file-icon {
-        width: 40rpx;
-        height: 40rpx;
-        flex-shrink: 0;
-      }
-
-      .file-empty {
-        color: #999999;
-      }
-    }
-  }
-}
-</style>

+ 53 - 16
pages/oa/universal/index.vue

@@ -3,26 +3,41 @@
 		<my-tabs @change="tapChange" :initIndex="initIndex"></my-tabs>
 		<scroll-view class="purchase-body" scroll-y="true" @scrolltolower="scrolltolower" @scroll="scroll">
 			<view v-if="initIndex === 0">
-				<form-Create></form-Create>
+				<!-- <form-Create></form-Create> -->
+				<form-Edit @popupClose="popupClose"></form-Edit>
 			</view>
 			<view v-if="initIndex === 1">
-				<data-List v-for="(item,index) in listData" :key="index" :info="item"></data-List>
-				<uni-fab :pattern="pattern" :horizontal="horizontal" :vertical="vertical"
-					:direction="direction" @fabClick="fabClick" />
+				<data-List v-for="(item,index) in listData" :key="index" :info="item" @faClick="handdle"></data-List>
+				<!-- 普通弹窗 -->
+				<uni-popup ref="popup" background-color="#fff" border-radius="10px 10px 0 0">
+					<view class="popup-body">
+						<view class="popup-close">
+							<uni-icons type="closeempty" size="20" @click="popupClose"></uni-icons>
+						</view>
+						<view class="popup-content">
+							<form-Edit :id="id" v-if="status=='暂存'" @popupClose="popupClose"></form-Edit>
+							<form-Detail :id="id" v-else @popupClose="popupClose"></form-Detail>
+						</view>
+					</view>
+					
+				</uni-popup>
 			</view>
 		</scroll-view>
 	</view>
 </template>
 <script>
-	import { getTodoTaskPage, getDoneTaskPage,getMyProcessInstancePage } from "@/api/work/index"
+	import { getListData } from "@/api/oa/universal"
 	import myTabs from '../myTabs.vue'
 	import dataList from '../dataList.vue'
-	import formCreate from './formCreate.vue'
+	import formDetail from './detail.vue'
+	import formEdit from './edit.vue'
 	import myPull from '@/static/js/myPull.js'
 	export default {
-		components:{myTabs,dataList,formCreate},
+		components:{myTabs,dataList,formEdit,formDetail},
 		data() {
 			return {
+				id:'',
+				status:'',
 				initIndex: 0,
 				pageNo: 1,
 				pageSize: 10,
@@ -42,28 +57,36 @@
 			this.refresh();
 		},
 		methods: {
+			popupClose(){
+				this.$refs.popup.close();
+				this.page = 1;
+				this.getList(this.page,this.__pulldone)
+			},
+			handdle(row) {
+				this.$refs.popup.open('bottom');
+			    this.id = row.id;
+				this.status = row.status;
+			},
 			fabClick() {
 				this.initIndex = 0;
-				// uni.showToast({
-				// 	title: '点击了悬浮按钮',
-				// 	icon: 'none'
-				// })
 			},
 			/**
 			 * @name 获取列表
 			 */
 			getList(page,done){
-				console.log(`获取第${page}页数据`);
 				if(this.initIndex==1){
-					getDoneTaskPage({pageNo:page,pageSize: this.pageSize}).then(response => {
+					getListData({pageNo:page,pageSize: this.pageSize}).then(response => {
 						let dataList = response.data.list;
 						let list = []
 						dataList.forEach(v => {
 							list.push({
-								title:v.processInstance.name,
-								status: v.name,
+								id:v.id,
+								oaType:v.employeeName+'提交的通用审批',
 								time:v.createTime,
-								nickname:v.processInstance.startUser.nickname
+								title:v.title,
+								remarks:v.remarks,
+								status: v.auditStatusDesc,
+								nickname:v.currentAuditEmployeeName
 							})
 						})
 						done(list);
@@ -97,6 +120,20 @@
 	}
 </script>
 <style lang='scss' scoped>
+	.popup-body{
+		z-index: 99;
+	}
+	.popup-close{
+		cursor: pointer;
+		height: 40px;
+		line-height: 40px;
+		padding-left: 10px;
+		border-bottom: 1px solid #eaecef;
+	}
+	.popup-content{
+		height: 450px;
+		overflow-x: auto;
+	}
 	.purchase-list {
 		background-color: #f5f5f5;
 		height: 100%;

+ 371 - 0
pages/popleSelect/choose.vue

@@ -0,0 +1,371 @@
+<template>
+	<view class="pur-list">
+		<view class="pur-hadder">
+			<uni-search-bar style="width: 100%;" placeholder="请输入姓名" @confirm="search" @clear="clear"@blur="blur" clearButton="auto"cancelButton="none" />
+		</view>
+		<view class="pur-body">
+			<!-- 面包屑 -->
+			<view class="bread" v-if='isShow'
+				style='display: flex;align-items:center; margin-left: 5px;height: 100rpx;width: 750rpx;'>
+				<view style='margin-right:5rpx;' @click='goBigBread()'>
+					神州通誉
+				</view>
+				<view v-for='(it,i) in breadList' @click='goBread(it,i)' :key='i'>
+					<text style='margin-left: 5px;margin-right: 5px;'>></text>
+					<text style='margin-left: 5px;margin-right: 5px;'>{{it.name}}</text>
+				</view>
+			</view>
+			<view v-if='isShow' class="" style='width: 750rpx;height: 15rpx;background-color:#f1f0f5;'>
+
+			</view>
+			<view class="" style='padding-bottom: 160rpx;width: 750rpx;' :style='{marginTop:isShow?"0px":"80rpx"}'>
+				<view class="list" v-if='deptIdTree.length'>
+					<view
+						style="display: flex;flex-direction: row;justify-content: space-between;margin-left: 40rpx;margin-right: 40rpx;height: 110rpx;border-bottom: 1px solid #f0f0f0;"
+						v-for="(it,i) in deptIdTree" :key='i' @click='godept(it)'>
+						<view v-if='it.name' style='display: flex;height: 110rpx;flex-direction: row;'>
+							<text style='font-size: 36rpx;line-height: 110rpx;'>{{it.name}} </text>
+							<!-- <text style='color:#ccc;line-height: 110rpx;'>({{it.children.length}})</text> -->
+						</view>
+						<view class="" v-if='it.children' style='padding-top: 40rpx;'>
+							<text style='color: #ccc;'>></text>
+						</view>
+
+					</view>
+				</view>
+				<view v-if='userList.length'>
+					<view class="" v-for='(it,i) in userList' :key='it.id' style='display: flex;flex-direction: row;height: 110rpx;margin-left: 5px;padding-top: 20px;padding-left: 10px;position: relative;border-bottom: 1px solid #f0f0f0;'>
+							<label class="radio" v-if='selectType' @click="isChecked($event,i,it)">
+								<radio :value='it.id.toString()' :checked="it.checked" />
+							</label>
+							<text class="avatar" style='position: absolute;top:12px;left:40px' :style='{left:selectType?"40px":"10px"}'>{{it.name.length>2?it.name.substr(it.name.length-2):it.name}}</text>
+							<view style='margin-left: 90rpx;'>
+								<text style='font-size: 36rpx;'>{{it.name}}</text>
+							</view>
+					</view>
+				</view>
+				<view v-if="!userList.length" style='width: 750rpx;text-align: center;padding-top: 100rpx;'>
+					暂无数据
+				</view>
+			</view>
+		</view>
+
+
+		<view class="list-bottom">
+			<view class="list-bottom-lianxi" @click='open'>
+				<text>已选择</text>
+				<text class="list-bottom-queding" v-if='checkList.length'>{{checkList.length}}个</text>
+				<text>联系人</text>
+			</view>
+			<view @click="determine" v-if='checkList.length'>
+				<text class="list-bottom-queding">确定</text>
+			</view>
+			<view v-else>
+				<text class="list-bottom-queding" style="color: #8F8F94;">确定</text>
+			</view>
+		</view>
+
+		<!-- 底部弹框 -->
+		<my-popup id="popup" ref="popup" type="bottom" :animation="false" @change="change">
+			<view class="popup-content" :style='{height:checkList.length>3?"auto":"500rpx"}'
+				style='padding-bottom: 100rpx;'>
+				<view class="" style='display: flex;flex-direction: row;justify-content: space-between;height: 100rpx;'>
+					<view class="" style='display: flex;flex-direction: row;margin-top: 20rpx;margin-left: 40rpx;'>
+						<text style='color: #333;'>已选择</text>
+						<text style='color:#007AFF;font-size: 36rpx;'>{{checkList.length}}</text>人
+					</view>
+					<view class="" style='margin-right: 20rpx;margin-top: 20rpx;' @click='submit'>
+						<text style='margin-right:10px;color:#007AFF;font-size: 36rpx;line-height: 50rpx;'>关闭</text>
+					</view>
+				</view>
+				<view class="" v-for='(it,i) in checkList' :key='i'
+					style='display: flex;flex-direction: row;border-bottom: 1px solid #f0f0f0;width: 750rpx;justify-content: space-between;height: 100rpx;'>
+					<view class="" style='position: relative;'>
+						<text class="avatar" v-if='it.name'
+							style='position: absolute;top:8px;left:20px'>{{it.name.length>2?it.name.substr(it.name.length-2):it.name}}</text>
+						<view style='margin-left: 130rpx;margin-top: 15px;color: #333;font-size: 36rpx;'>{{it.name}}
+						</view>
+					</view>
+					<view class="" style='margin-right: 20px;padding-top: 35rpx;'>
+						<text
+							style='color:#C9C9C9;font-size: 30rpx;text-align: center;border-radius: 10rpx;width: 100rpx;height: 50rpx;line-height: 50rpx;border-width: 1px;border-color: #C9C9C9;'
+							@click='deleteUser(it)'>删除</text>
+					</view>
+				</view>
+			</view>
+		</my-popup>
+	</view>
+</template>
+
+<script>
+	import {
+		listSimpleDepts,
+		listForSelectEmployee
+	} from "@/api/peopleSelect/index"
+	import resource from '../../js/data.js';
+	import myPopup from '../../components/my-popup/my-popup.vue';
+	export default {
+		data() {
+			return {
+				// 查询参数
+				queryParams: {
+					name: undefined,
+					deptId: undefined,
+					auth: undefined
+				},
+				deptIdTree: [],
+				userList: [],
+				breadList: [],
+				selectType: true,
+				active: null,
+				checkList: [],
+				breadId: null,
+				isShow: true, //是否显示面包屑
+			}
+		},
+		components: {
+			myPopup
+		},
+		onLoad() {
+			this.getDeptTree()
+			this.getList()
+		},
+		onShow() {
+			this.getDeptTree()
+			this.getList()
+		},
+		methods: {
+			/** 查询部门下拉树结构 */
+			getDeptTree() {
+				listSimpleDepts().then(response => {
+					// 处理 deptIdTree 参数
+					this.deptIdTree = [];
+					this.deptIdTree.push(...this.handleTree(response.data, "id"));
+					console.log(this.deptIdTree);
+				});
+			},
+			/** 查询用户列表 */
+			getList() {
+				listForSelectEmployee(this.queryParams).then(response => {
+					this.userList = response.data
+					console.log(this.userList);
+				})
+			},
+			search(res) {
+				console.log('----search:', res)
+				this.queryParams.name = res.value;
+				this.getList();
+			},
+			clear(res) {
+				console.log('----clear:', res)
+				this.queryParams.name = '';
+				this.getList();
+			},
+			blur(res) {
+				console.log('----blur:', res)
+				this.queryParams.name = res.value;
+				this.getList();
+			},
+			
+			// 弹窗确认
+			submit() {
+				this.$refs.popup.close()
+			},
+			deleteUser(it) {
+				this.userList.forEach(its => {
+					if (its.id == it.id) {
+						its.checked = false
+					}
+				})
+				this.checkList = this.checkList.filter(item => {
+					let itId = it.id.toString();
+					let itemId = item.id.toString();
+					return !itId.includes(itemId);
+				})
+			},
+			change() {},
+			open() {
+				let that = this;
+				that.$refs.popup.open();
+			},
+			goBread(it, i) {
+				if (it.it.children) {
+					this.deptIdTree = it.it.children
+				} else {
+					this.deptIdTree = []
+				}
+				this.breadId = it
+				this.breadList = this.breadList.slice(0, i + 1)
+				this.queryParams.deptId = it.id;
+				this.getList();
+			},
+			goBigBread() {
+				this.queryParams.deptId = undefined;
+				this.getDeptTree();
+				this.getList();
+				this.breadList = []
+			},
+			isChecked(e, i, it) {
+				this.active = i;
+				console.log("12")
+				// #ifdef APP-NVUE
+				console.log("123")
+				e.stopPropagation()
+				// #endif
+				this.userList[i].checked = !this.userList[i].checked
+				if (this.selectType) {
+					if (this.userList[i].checked) {
+						console.log('push进去', this.checkList)
+						this.checkList.push(it)
+					} else {
+						this.checkList.splice(this.checkList.indexOf(it), 1);
+					}
+				} else {
+
+				}
+			},
+			godept(it) {
+				console.log('人员', it)
+				if (it.name) {
+					this.breadId = it.id
+					this.breadList.push({
+						name: it.name,
+						id: it.id,
+						it: it,
+						color: '#0066CC'
+					})
+				}
+				if (!it.children) {
+					this.deptIdTree = []
+				}else{
+					this.deptIdTree = it.children
+				}
+				this.queryParams.deptId = it.id;
+				this.getList();
+			},
+			//获取选中的人员昵称列表
+			        getNickNameList(uns) {
+			          let result = []
+			  
+			          uns.forEach(item => {
+						   result.push(item.name)
+			          })
+			  
+			          return result
+			        },
+					//获取选中的人员ID列表
+					        getUserIdList(uns) {
+					          let result = []
+					          uns.forEach(item => {
+								  result.push(item.id)
+					          })
+					  
+					          return result
+					        },
+			// 确认
+			determine() {
+				console.log(this.checkList)
+				this.$emit('submit', this.checkList,this.getNickNameList(this.checkList), this.getUserIdList(this.checkList))
+				
+				// uni.navigateTo({
+				// 	url: '/pages/oa/universal/index?list=' + JSON.stringify(this.checkList)
+				// })
+			},
+		}
+	}
+</script>
+<style>
+</style>
+<style lang="scss">
+	.pur-list {
+		background-color: #fff;
+		height: 100%;
+		overflow: hidden;
+
+		.pur-hadder {
+			background-color: #ffffff;
+			height: 55px;
+			font-size: 14px;
+			display: flex;
+			position: -webkit-sticky;
+			position: sticky;
+			box-sizing: border-box;
+			min-width: 100%;
+			overflow-x: auto;
+		}
+
+		.pur-body {
+			height: calc(100% - 88upx);
+			overflow: auto
+		}
+	}
+
+	.avatar {
+		width: 70rpx;
+		height: 70rpx;
+		background: #3489ff;
+		text-align: center;
+		line-height: 70rpx;
+		border-radius: 15rpx;
+		font-size: 26rpx;
+		color: #fff;
+	}
+
+	.popup-content {
+		width: 750rpx;
+		height: 500rpx;
+		z-index: 99999;
+		background-color: #fff
+	}
+
+	.list-bottom {
+		position: fixed;
+		height: 150rpx;
+		background-color: #FFFFFF;
+		width: 760rpx;
+		bottom: 0;
+		left: 0;
+		display: flex;
+		flex-direction: row;
+		flex-wrap: nowrap;
+		font-size: 20rpx;
+		justify-content: space-between;
+		padding: 50rpx 30rpx;
+	}
+
+	.list-bottom-queding {
+		color: #007AFF;
+
+	}
+
+	.list-bottom-lianxi {
+		display: flex;
+		flex-direction: row;
+	}
+
+	.search {
+		position: relative;
+		width: 700rpx;
+		height: 80rpx;
+		box-sizing: border-box;
+		line-height: 80rpx;
+		background: #f1f0f5;
+		border-radius: 26rpx;
+		margin-left: 15%;
+
+
+	}
+
+	.fdj {
+		position: absolute;
+		top: 35rpx;
+		transform: translateY(-50%);
+		right: 70rpx;
+		color: #999;
+		font-size: 40rpx;
+	}
+
+	.list {
+		width: 750rpx;
+	}
+</style>

+ 51 - 1
pages/work/index.vue

@@ -2,11 +2,24 @@
 	<view class='purchase-list'>
 		<my-tabs @change="tapChange" :modelData="modelData" :initIndex="initIndex"></my-tabs>
 		<scroll-view class="purchase-body" scroll-y="true" @scrolltolower="scrolltolower" @scrolltoupper="scrolltoupper" @scroll="scroll" @touchstart="touchstart" @touchend="touchend">
-			<my-unit v-for="(item,index) in listData" :key="index" :info="item" :initIndex="initIndex"></my-unit>
+			<my-unit v-for="(item,index) in listData" :key="index" :info="item" :initIndex="initIndex" @faClick="handdle"></my-unit>
 		</scroll-view>
+		<!-- 底部弹窗 -->
+		<uni-popup ref="popup" background-color="#fff" border-radius="10px 10px 0 0">
+				<view class="popup-body">
+					<view class="popup-close">
+						<uni-icons type="closeempty" size="20" @click="popupClose"></uni-icons>
+					</view>
+					<view class="popup-content">
+						<async-form-component :id="businessKey" :name="initIndex.toString()" @popupClose="popupClose"></async-form-component>
+					</view>
+				</view>
+				
+			</uni-popup>
 	</view>
 </template>
 <script>
+	import Vue from 'vue'
 	import { getTodoTaskPage, getDoneTaskPage,getMyProcessInstancePage } from "@/api/work/index"
 	import myTabs from '@/components/myTabs/myTabs.vue'
 	import myUnit from '@/components/myUnits/purchaseUnit/unit.vue'
@@ -15,6 +28,7 @@
 		components:{myTabs,myUnit},
 		data() {
 			return {
+				businessKey:'',
 				initIndex:0,
 				pageNo: 1,
 				pageSize: 10
@@ -26,6 +40,21 @@
 		  this.refresh();
 		},
 		methods: {
+			handdle(row) {
+			    this.businessKey = row.businessKey;
+				//将业务表单,注册为动态组件
+				const path = row.path;
+				console.log("path:" + path)
+				Vue.component("async-form-component", function (resolve) {
+					require([`@/pages${path}`], resolve);
+				});
+				this.$refs.popup.open('bottom');
+			},
+			popupClose(){
+				this.$refs.popup.close();
+				this.page = 1;
+				this.getList(this.page,this.__pulldone)
+			},
 			/**
 			 * @name 获取列表
 			 */
@@ -37,6 +66,8 @@
 						let list = []
 						dataList.forEach(v => {
 							list.push({
+								businessKey:v.processInstance.businessKey,
+								path:v.taskDefinitionKey == 'modifyApply' ? v.processDefinition.formCustomCreatePath : v.processDefinition.formCustomViewPath,
 								title:v.processInstance.name,
 								status: v.name,
 								time:v.createTime,
@@ -52,6 +83,8 @@
 						let list = []
 						dataList.forEach(v => {
 							list.push({
+								businessKey:v.processInstance.businessKey,
+								path:v.processDefinition.formCustomViewPath,
 								title:v.processInstance.name,
 								status: v.name,
 								time:v.createTime,
@@ -67,6 +100,8 @@
 						let list = []
 						dataList.forEach(v => {
 							list.push({
+								businessKey:v.businessKey,
+								path:v.processDefinition.formCustomViewPath,
 								title:v.name,
 								status: v.status,
 								time:v.startTime,
@@ -113,6 +148,21 @@
 	}
 </script>
 <style lang='scss' scoped>
+.popup-body{
+		z-index: 99;
+	}
+	.popup-close{
+		cursor: pointer;
+		height: 40px;
+		line-height: 40px;
+		padding-left: 10px;
+		border-bottom: 1px solid #eaecef;
+	}
+	.popup-content{
+		height: 450px;
+		overflow-x: auto;
+		padding-bottom: 50px;
+	}
 	.purchase-list {
 		background-color: #f5f5f5;
 		height: 100%;

+ 12 - 3
static/scss/colorui.css

@@ -131,7 +131,6 @@ switch.checked::before {
 }
 
 /* #ifndef MP-ALIPAY */
-radio::before,
 checkbox::before {
 	font-family: "cuIcon";
 	content: "\e645";
@@ -228,8 +227,18 @@ switch .uni-switch-input::before,
 radio.radio::before,
 checkbox .uni-checkbox-input::before,
 radio .uni-radio-input::before {
-	display: none;
-}
+	/* display: none; */
+}
+/* uni-radio .uni-radio-input.uni-radio-input-checked:before {
+    font: normal normal normal 14px/1 uni;
+    content: "\EA08";
+    font-size: 18px;
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%,-48%) scale(.73);
+    -webkit-transform: translate(-50%,-48%) scale(.73)
+} */
 
 radio.radio[checked]::after,
 radio.radio .uni-radio-input-checked::after {

+ 2 - 1
store/getters.js

@@ -3,6 +3,7 @@ const getters = {
   avatar: state => state.user.avatar,
   name: state => state.user.name,
   roles: state => state.user.roles,
-  permissions: state => state.user.permissions
+  permissions: state => state.user.permissions,
+  userInfo:state => state.user.userInfo,
 }
 export default getters

+ 7 - 2
store/modules/user.js

@@ -12,7 +12,7 @@ const user = {
     name: storage.get(constant.name),
     avatar: storage.get(constant.avatar),
     roles: storage.get(constant.roles),
-    permissions: storage.get(constant.permissions)
+    permissions: storage.get(constant.permissions),
   },
 
   mutations: {
@@ -34,7 +34,11 @@ const user = {
     SET_PERMISSIONS: (state, permissions) => {
       state.permissions = permissions
       storage.set(constant.permissions, permissions)
-    }
+    },
+	SET_USERINFO: (state, userInfo) => {
+	  state.userInfo = userInfo
+	  storage.set(constant.userInfo, userInfo)
+	}
   },
 
   actions: {
@@ -71,6 +75,7 @@ const user = {
           }
           commit('SET_NAME', nickname)
           commit('SET_AVATAR', avatar)
+		  uni.setStorage({key: 'userInfo',data: user,})
           resolve(res)
         }).catch(error => {
           reject(error)

+ 90 - 39
utils/ruoyi.js

@@ -5,43 +5,94 @@
 
 // 日期格式化
 export function parseTime(time, pattern) {
-  if (arguments.length === 0 || !time) {
-    return null
-  }
-  const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
-  let date
-  if (typeof time === 'object') {
-    date = time
-  } else {
-    if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
-      time = parseInt(time)
-    } else if (typeof time === 'string') {
-      time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm),'');
-    }
-    if ((typeof time === 'number') && (time.toString().length === 10)) {
-      time = time * 1000
-    }
-    date = new Date(time)
-  }
-  const formatObj = {
-    y: date.getFullYear(),
-    m: date.getMonth() + 1,
-    d: date.getDate(),
-    h: date.getHours(),
-    i: date.getMinutes(),
-    s: date.getSeconds(),
-    a: date.getDay()
-  }
-  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
-    let value = formatObj[key]
-    // Note: getDay() returns 0 on Sunday
-    if (key === 'a') {
-      return ['日', '一', '二', '三', '四', '五', '六'][value]
-    }
-    if (result.length > 0 && value < 10) {
-      value = '0' + value
-    }
-    return value || 0
-  })
-  return time_str
+	if (arguments.length === 0 || !time) {
+		return null
+	}
+	const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
+	let date
+	if (typeof time === 'object') {
+		date = time
+	} else {
+		if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
+			time = parseInt(time)
+		} else if (typeof time === 'string') {
+			time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '');
+		}
+		if ((typeof time === 'number') && (time.toString().length === 10)) {
+			time = time * 1000
+		}
+		date = new Date(time)
+	}
+	const formatObj = {
+		y: date.getFullYear(),
+		m: date.getMonth() + 1,
+		d: date.getDate(),
+		h: date.getHours(),
+		i: date.getMinutes(),
+		s: date.getSeconds(),
+		a: date.getDay()
+	}
+	const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
+		let value = formatObj[key]
+		// Note: getDay() returns 0 on Sunday
+		if (key === 'a') {
+			return ['日', '一', '二', '三', '四', '五', '六'][value]
+		}
+		if (result.length > 0 && value < 10) {
+			value = '0' + value
+		}
+		return value || 0
+	})
+	return time_str
 }
+
+/**
+ * 构造树型结构数据
+ * @param {*} data 数据源
+ * @param {*} id id字段 默认 'id'
+ * @param {*} parentId 父节点字段 默认 'parentId'
+ * @param {*} children 孩子节点字段 默认 'children'
+ * @param {*} rootId 根Id 默认 0
+ */
+export function handleTree(data, id, parentId, children, rootId) {
+	id = id || 'id'
+	parentId = parentId || 'parentId'
+	children = children || 'children'
+	rootId = rootId || Math.min.apply(Math, data.map(item => {
+		return item[parentId]
+	})) || 0
+	//对源数据深度克隆
+	const cloneData = JSON.parse(JSON.stringify(data))
+	//循环所有项
+	const treeData = cloneData.filter(father => {
+		let branchArr = cloneData.filter(child => {
+			//返回每一项的子级数组
+			return father[id] === child[parentId]
+		});
+		branchArr.length > 0 ? father.children = branchArr : '';
+		//返回第一层
+		return father[parentId] === rootId;
+	});
+	return treeData !== '' ? treeData : data;
+}
+
+/**
+ * 获取文件类型
+ * @param {String} fileName 文件名称
+ * @returns {String} fileType => '', image, video, audio, office, unknown
+ */
+export function getFileType(fileName = '') {
+	const flieArr = fileName.split('.');
+	let suffix = flieArr[flieArr.length - 1];
+	if (!suffix) return '';
+	suffix = suffix.toLocaleLowerCase();
+	const image = ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp'];
+	if (image.includes(suffix)) return 'image';
+	const video = ['mp4', 'm4v'];
+	if (video.includes(suffix)) return 'video';
+	const audio = ['mp3', 'm4a', 'wav', 'aac'];
+	if (audio.includes(suffix)) return 'audio';
+	const office = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'plain'];
+	if (office.includes(suffix)) return 'office';
+	return 'unknown';
+}