personnel_management_mobile/components/rider-crud/index.vue

476 lines
11 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view>
<!-- head -->
<view class="head-area" :style="{ height: `${headHeight}rpx` }">
<u-navbar
:is-fixed="false"
:border-bottom="false"
:is-back="true"
:custom-back="navBack"
:title="isWeixin ? '' : option.navTitle"
:back-icon-name="option.navBackIcon || 'arrow-leftward'"
back-icon-color="#fff"
back-icon-size="35"
:background="{ background: 'transparent' }"
title-color="#fff"
>
<view class="nav-title" v-if="isWeixin">{{ option.navTitle }}</view>
<view class="nav-right" slot="right" v-if="option.manageBtn" @click="manageSwitch = !manageSwitch">
{{ manageSwitch ? '完成' : '管理' }}
</view>
</u-navbar>
<view class="search-item" v-if="option.searchShow">
<u-search
placeholder="搜索内容"
v-model="searchValue"
@search="onSearch(searchValue)"
@clear="onSearch(searchValue)"
shape="square"
bg-color="#8EAAFF"
placeholder-color="#5470C4"
color="#fff"
search-icon-color="#ffffffE5"
:clearabled="true"
:show-action="false"
></u-search>
</view>
</view>
<!-- head seat -->
<view :style="{ height: `${headHeight}rpx` }"></view>
<!-- list -->
<block v-if="data && data.length > 0">
<view class="" v-for="(item, index) in data" :key="index">
<crud-item
:ref="`crud-item${index}`"
:list="data"
:node="item"
:option="option"
:nodeIndex="index"
:checkList="checkList"
:checkShow="manageSwitch"
:random-num="randomNum"
></crud-item>
</view>
<view style="padding: 20rpx 0;"><slot name="loadmore"></slot></view>
</block>
<!-- foot -->
<block v-if="manageSwitch">
<view :style="[{ height: isFullSucreen ? '168rpx' : '100rpx' }]"></view>
<view class="foot flex" v-if="manageSwitch" :class="[isFullSucreen ? 'foot-ipx' : '']">
<checkbox-group @change="onCheckedAll">
<label class="well-check flex flex-c">
<checkbox
color="#fff"
style="transform: scale(0.7)"
value="allSelect"
:checked="checkedAll"
class="curdCheck"
></checkbox>
<text class="checkAll">全选 ({{ checkList.length }})</text>
</label>
</checkbox-group>
<view class=""><view class="foot-del-btn" @click="onRemove">删除</view></view>
</view>
</block>
<!-- form -->
<u-popup
v-model="createShow"
safe-area-inset-bottom
border-radius="14"
mode="bottom"
closeable
@close="onCreateClose"
:mask-close-able="false"
>
<view class="popup-head"><u-section :title="action" :right="false" line-color="#5f88ff"></u-section></view>
<scroll-view scroll-y="true" style="height: 68vh;">
<view class="form">
<block v-if="formType == 'uviewForm'">
<u-form :model="value" ref="uForm" :label-width="option.labelWidth || 160"><slot name="form"></slot></u-form>
</block>
<block v-else><slot name="form"></slot></block>
</view>
</scroll-view>
<view class="form-btn">
<u-button
v-if="action != '查看'"
@click="onSubmit"
:loading="disabled"
shape="circle"
ripple
:custom-style="{ width: '100%', background: 'linear-gradient(90deg, #69b0ff, #5f88ff)', color: '#fff' }"
>
保存
</u-button>
</view>
</u-popup>
<!-- addBtn -->
<movable-area class="movable-area">
<movable-view class="movable-view" :x="moveX" :y="moveY" direction="all">
<image src="@/static/images/crud/create.png" @click="onCreateOpen"></image>
</movable-view>
</movable-area>
<!-- empty -->
<slot name="empty">
<block v-if="data.length == 0">
<u-empty text="工作再忙,也要记得喝水~" margin-top="200" :src="require('@/static/images/crud/empty.png')"></u-empty>
</block>
</slot>
</view>
</template>
<script>
import crudItem from './components/crud-item/index'
import { checkModel } from './util/tool.js'
import validate from './util/validate.js'
export default {
name: 'rider-crud',
components: { crudItem },
props: {
value: {}, // 表单
data: Array, // 列表
// 配置
option: {
type: Object,
default: {
column: []
}
},
// 表单类型
formType: {
type: String,
default: 'uviewForm'
},
// 返回事件
navBack: {
type: Function,
default: null
},
rules: {}, // 校验规则
readonly: {
type: Boolean,
default: false
}
},
data() {
return {
isFullSucreen: checkModel(),
moveX: 320, //添加按钮坐标
moveY: 580,
checkedAll: false, //全选
checkList: [], //选中值
createShow: false, //form弹窗
disabled: false, // 操作按钮
action: '新增',
searchValue: '',
isWeixin: false,
manageSwitch: false,
headHeight: 0,
randomNum: Math.round(Math.random() * 99999) // 随机数防止uni.on重复调用
}
},
watch: {
manageSwitch: {
handler(newVal, oldVal) {
this.checkList = []
this.checkedAll = false
},
deep: true,
immediate: true
},
'option.searchShow': {
handler(newVal, oldVal) {
const that = this
this.headHeight = newVal ? 192 : 98
// #ifndef H5
uni.getSystemInfo({
success: function(res) {
const statusBarHeight = Number(res.statusBarHeight) + Number(res.platform == 'ios' ? 44 : 48)
that.headHeight = newVal ? statusBarHeight + 192 : statusBarHeight + 98
}
})
// #endif
},
deep: true,
immediate: true
}
},
// 通信事件
created() {
let that = this
uni.$on(`action${this.randomNum}`, ({ index }, i, list) => {
that.onActionClick({ index }, i, list)
})
uni.$on(`checked${this.randomNum}`, (e, id) => {
that.onChecked(e, id)
})
// #ifdef MP-WEIXIN
this.isWeixin = true
// #endif
// #ifndef MP-WEIXIN
this.isWeixin = false
// #endif
},
methods: {
setLazyLoad(func) {
this.option.lazyLoad = func
setTimeout(() => {
this.data.forEach((d, i) => {
this.$refs[`crud-item${i}`][0].setLazyLoad(func)
})
}, 100)
},
// 选择
onChecked(e, id) {
const i = e.detail.value[0]
if (i) this.checkList.push(i)
else this.checkList.splice(this.checkList.findIndex(e => e === id), 1)
this.checkedAll = this.checkList.length === this.data.length
},
// 全选
onCheckedAll() {
if (!this.checkedAll) {
this.checkedAll = true
this.checkList = []
this.data.map(e => {
this.checkList.push(e.id)
})
} else {
this.checkedAll = false
this.checkList = []
}
},
// 元素点击
onClick(item, index) {
const action = { name: '查看' }
const data = JSON.parse(JSON.stringify(item))
this.$emit('input', data)
this.$emit('action-click', { index, data, actionIndex: -1, action, done: this.show })
this.action = action.name
},
// 底部删除
onRemove() {
if (this.checkList.length === 0) {
uni.showToast({
title: '请选择至少一条数据',
icon: 'none',
duration: 2000
})
return
}
this.$emit('del', this.checkList.join(','))
},
// 打开弹窗
onCreateOpen() {
this.action = '新增'
this.$emit('action-click', { action: { name: this.action }, done: this.show })
},
// 关闭弹窗
onCreateClose() {
this.hide()
},
// 添加保存
onSubmit() {
this.disabled = true
const data = JSON.parse(JSON.stringify(this.value))
if (this.formType == 'uviewForm') {
// #ifdef MP
validate(this.value, this.rules)
.then(() => {
this.$emit('submit', data, this.action, this.unloading, this.hide)
})
.catch(() => {
this.unloading()
})
// #endif
// #ifndef MP
this.$refs.uForm.validate(valid => {
if (valid) {
this.$emit('submit', data, this.action, this.unloading, this.hide)
} else {
this.unloading()
}
})
// #endif
} else {
validate(this.value, this.rules)
.then(() => {
debugger
this.$emit('submit', data, this.action, this.unloading, this.hide)
})
.catch(() => {
this.unloading()
})
}
},
// 左滑按钮点击
onActionClick({ index }, i, list) {
let action
if (index == -1) action = { name: '查看' }
else action = this.option.actions[index]
const data = JSON.parse(JSON.stringify(list[i]))
if (['新增', '编辑', '查看'].includes(action.name)) this.$emit('input', data)
this.$emit('action-click', { index: i, data, actionIndex: index, action, done: this.show })
// this.action = action.name
this.$set(this, 'action', action.name)
},
//全选删除后回调
allCheckHide(val) {
if (this.checkedAll) this.manageSwitch = val
this.checkList = []
},
// 搜索
onSearch(val) {
this.$emit('search', val)
},
show() {
this.createShow = true
setTimeout(() => {
if (this.rules && this.$refs['uForm'] && typeof this.$refs['uForm'].setRules == 'function') {
this.$refs['uForm'].setRules(this.rules)
}
}, 100)
},
hide() {
this.createShow = false
this.disabled = false
this.$emit('input', {})
this.$emit('update:readonly', false)
},
unloading() {
this.disabled = false
},
hideChildren() {
this.data.forEach((d, i) => {
this.$refs[`crud-item${i}`][0].hide()
})
}
}
}
</script>
<style lang="scss" scoped>
.flex {
display: flex;
align-items: center;
justify-content: space-between;
}
.flex-one {
flex: 1;
}
.head-area {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
width: 100%;
background: url('/static/images/head_bg.png') no-repeat center bottom;
background-size: 100% 100%;
.nav-right {
color: #fff;
font-size: 30rpx;
font-weight: normal;
padding-right: 30rpx;
}
.nav-title {
color: #fff;
font-size: 32rpx;
font-weight: normal;
}
.search-item {
padding: 0 30rpx;
}
}
.head-h {
height: 200rpx;
}
/* 底部 */
/* 适配 */
.foot-ipx {
bottom: 68rpx !important;
}
.foot-ipx::after {
content: ' ';
position: fixed;
bottom: 0 !important;
left: 0;
right: 0;
height: 68rpx !important;
width: 100%;
background: #fff;
}
.foot {
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 99;
width: 100%;
padding: 0 26rpx;
height: 100rpx;
background: #fff;
border-top: 2px solid #eee;
&-del-btn {
width: 160rpx;
height: 64rpx;
line-height: 64rpx;
font-size: 26rpx;
// color: #fff;
text-align: center;
border-radius: 34px;
// background: linear-gradient(180deg, #5f88ff, #69b0ff);
color: #f56c6c;
background: #fef0f0;
}
}
.form {
padding: 0 30rpx 20rpx;
}
.popup-head {
padding: 36rpx 30rpx;
border-bottom: 2rpx dashed #efefef;
}
.form-btn {
margin: 30rpx;
min-height: 80rpx;
}
.movable-area {
height: 100vh;
width: 100%;
top: 0;
position: fixed;
pointer-events: none;
.movable-view {
width: 96rpx;
height: 96rpx;
pointer-events: auto;
image {
width: 96rpx;
height: 96rpx;
}
}
}
</style>