中航光电PDA端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

476 lines
11 KiB

3 weeks ago
<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>