有限空间作业

八项作业
LiuJiaNan 2024-07-04 17:57:31 +08:00
parent 898297dd1d
commit b2d15258cb
34 changed files with 3586 additions and 230 deletions

View File

@ -33,10 +33,17 @@ export const setCertificateInformationEditPost = (params) => post("/app/specialU
export const getDeptTree = (params) => post("/api/department/listzTree", params) //用户信息
export const getEMPLOYMENTAPPLYMANAGEMENTID = (params) => post("/app/user/getEMPLOYMENTAPPLYMANAGEMENTID",
params) //获取EMPLOYMENTAPPLYMANAGEMENTID
export const getCorpInfoList = (params) => post("/department/getPreventCrop", params) //获取公司列表
export const getConfinedSpaceSelectList = (params) => post("/app/gfLimitSpace/listAllSpace", {
// 以下接口八项作业流程使用
export const getCorpInfoList = (params) => post("/app/util/getCorp", params) //获取公司列表
export const getConfinedSpaceSelectList = (params) => post("/app/Task/getAllToDoList", {
loading: false,
...params
}) //获取受限空间名称选择列表
export const getOtherAssignmentsSelectList = (params) => post("/app/eightwork/list", params) //关联的其他特殊作业及安全作业票编号选择列表
export const getRiskIdentificationResultsSelectList = (params) => post("/app/eightwork/getInfo", params) //风险辨识结果选择列表
export const getOtherAssignmentsSelectList = (params) => post("/app/Task/getAllUnEndList", params) //关联的其他特殊作业及安全作业票编号选择列表
export const getRiskIdentificationResultsSelectList = (params) => post("/app/eightWork/getInfo", params) //风险辨识结果选择列表
export const setTaskSave = (params) => post("/app/Task/init", params) //八项作业、隐患整改、安全环保检查任务保存更新接口
export const getCurrentNextOperation = (params) => post("/app/Task/getSupplementInfo", params) //获取当前任务的下一步操作
export const getDepartmentTree = (params) => post("/app/util/getDepartmentTree", params) //获取部门树
export const getUserList = (params) => post("/app/util/getUserList", params) //获取人员
// 结束

View File

@ -5,7 +5,7 @@
<u-checkbox-group v-model="selectValue" placement="column">
<u-checkbox :customStyle="{marginBottom: '8px'}" v-for="(item, index) in list" :key="index"
:label="type === 'assignments' ? item.CHECK_NO : item.NAME"
:value="type === 'assignments' ? item.CHECK_NO : item.NAME">
:name="type === 'assignments' ? item.CHECK_NO : item.NAME">
</u-checkbox>
</u-checkbox-group>
<view class="button_group_placeholder"></view>
@ -29,17 +29,14 @@
visible: {
type: Boolean,
required: true,
default: false
},
value: {
type: String,
required: true,
default: ''
},
type: {
type: String,
required: true,
default: ''
}
},
data() {
@ -51,7 +48,10 @@
watch: {
visible: {
handler(newValue) {
if (newValue) this.getData()
if (newValue) {
this.selectValue = this.value.split(',')
this.getData()
}
},
immediate: true
}
@ -60,7 +60,7 @@
async getData() {
if (this.type === 'assignments') {
const resData = await getOtherAssignmentsSelectList()
this.list = resData.varList
this.list = resData.list
} else if (this.type === 'identification') {
const resData = await getRiskIdentificationResultsSelectList({
vectors: JSON.stringify(['accidentType'])
@ -69,17 +69,19 @@
}
},
close() {
this.selectValue = []
this.$emit('update:visible', false)
},
determine() {
const value = []
for (let i = 0; i < this.selectValue.length; i++) {
if (this.value.indexOf(this.selectValue[i]) === -1) {
value.push(this.selectValue[i])
}
}
this.value && value.unshift(this.value)
const emitValue = value.join(',')
// const value = []
// for (let i = 0; i < this.selectValue.length; i++) {
// if (this.value.indexOf(this.selectValue[i]) === -1) {
// value.push(this.selectValue[i])
// }
// }
// this.value && value.unshift(this.value)
// const emitValue = value.join(',')
const emitValue = this.selectValue.join(',')
this.$emit('input', emitValue)
this.close()
}
@ -107,4 +109,4 @@
right: 0;
}
}
</style>
</style>

View File

@ -175,7 +175,7 @@
}
},
{
"path": "pages/selete_corp_info/index",
"path": "pages/eight_assignments/select_corp_info",
"style": {
"navigationBarTitleText": "选择分公司"
}
@ -197,6 +197,18 @@
"style": {
"navigationBarTitleText": "位置定位"
}
},
{
"path": "pages/eight_assignments/select_review_personnel",
"style": {
"navigationBarTitleText": "选择审核人员"
}
},
{
"path": "pages/eight_assignments/select_department",
"style": {
"navigationBarTitleText": "选择部门"
}
}
],
"globalStyle": {

View File

@ -1,173 +1,234 @@
<template>
<view class="content">
<view class="card">
<u--form labelPosition="left" :model="form" :rules="rules" ref="formRef" labelWidth="140px">
<u-form-item label="申请单位" prop="APPLY_DEPARTMENT_NAME" borderBottom required>
<u--input v-model="form.APPLY_DEPARTMENT_NAME" border="none" readonly />
</u-form-item>
<u-form-item label="申请人" prop="APPLY_USER_NAME" borderBottom required>
<u--input v-model="form.APPLY_USER_NAME" border="none" readonly />
</u-form-item>
<u-form-item label="作业分公司" prop="CORP_NAME" borderBottom required>
<u--input v-model="form.CORP_NAME" border="none" readonly />
</u-form-item>
<u-form-item label="受限空间所属单位" prop="BELONG_CORP" borderBottom required>
<u--input v-model="form.BELONG_CORP" border="none" />
</u-form-item>
<u-form-item label="受限空间名称" prop="LIMITSPACE_NAME" borderBottom required
@click="fnSingleChoiceClick('LIMITSPACE_NAME')">
<u--input v-model="form.LIMITSPACE_NAME" border="none" readonly />
</u-form-item>
<u-form-item label="受限空间内原有介质名称" prop="MEDIUM_NAME" borderBottom required>
<u--input v-model="form.MEDIUM_NAME" border="none" />
</u-form-item>
<u-form-item label="作业内容" prop="WORK_CONTENT" borderBottom required labelPosition="top">
<u--textarea v-model="form.WORK_CONTENT" border="none" autoHeight />
</u-form-item>
<u-form-item label="作业开始时间" prop="WORK_START_DATE" borderBottom required
@click="fnDateTimePickerClick('WORK_START_DATE')">
<u--input v-model="form.WORK_START_DATE" border="none" readonly />
</u-form-item>
<u-form-item label="作业结束时间" prop="WORK_END_DATE" borderBottom required
@click="fnDateTimePickerClick('WORK_END_DATE')">
<u--input v-model="form.WORK_END_DATE" border="none" readonly />
</u-form-item>
<u-form-item label="地点坐标" borderBottom required>
<u-button type="primary" size="small" text="定位" :customStyle="{width:'100upx',margin:0}"
@click="fnLocation" />
</u-form-item>
<u-form-item label="经度" prop="WORK_LONGITUDE" borderBottom required>
<u--input v-model="form.WORK_LONGITUDE" border="none" readonly />
</u-form-item>
<u-form-item label="纬度" prop="WORK_LATITUDE" borderBottom required>
<u--input v-model="form.WORK_LATITUDE" border="none" readonly />
</u-form-item>
<u-form-item label="作业人" prop="WORK_USER" borderBottom required>
<u--input v-model="form.WORK_USER" border="none" />
</u-form-item>
<u-form-item label="关联的其他特殊作业及安全作业票编号" prop="SPECIAL_WORK" borderBottom required labelPosition="top"
labelWidth="auto">
<u-button type="primary" size="mini" text="选择其它"
:customStyle="{position: 'absolute',top: '-46upx',right: '20upx',width: '150upx'}"
@click="otherAssignmentsShow = true" />
<u--textarea v-model="form.SPECIAL_WORK" border="none" autoHeight maxlength="-1" />
</u-form-item>
<u-form-item label="风险辨识结果" prop="RISK_IDENTIFICATION" borderBottom required labelPosition="top"
labelWidth="auto">
<u-button type="primary" size="mini" text="选择其它"
:customStyle="{position: 'absolute',top: '-46upx',right: '20upx',width: '150upx'}"
@click="otherIdentificationShow = true" />
<u--textarea v-model="form.RISK_IDENTIFICATION" border="none" autoHeight maxlength="-1" />
</u-form-item>
</u--form>
</view>
<u-picker :show="picker.show" :columns="picker.columns" :keyName="picker.key" :key="picker.type"
@confirm="fnSingleChoiceConfirm" @cancel="fnSingleChoiceCancel" />
<u-datetime-picker :show="datetimePicker.show" v-model="datetimePicker.value" :mode="datetimePicker.mode"
:minDate="datetimePicker.min" :key="datetimePicker.type" @confirm="fnDateTimePickerConfirm"
@cancel="fnDateTimePickerCancel" />
<other-select :visible.sync="otherAssignmentsShow" v-model="form.SPECIAL_WORK" type="assignments" />
<other-select :visible.sync="otherIdentificationShow" v-model="form.RISK_IDENTIFICATION" type="identification" />
</view>
<view class="content">
<view class="card">
<u-form labelPosition="left" :model="form" :rules="rules" ref="formRef" labelWidth="140px">
<u-form-item label="申请单位" prop="APPLY_DEPARTMENT_NAME" borderBottom required>
<u-input v-model="form.APPLY_DEPARTMENT_NAME" border="none" readonly/>
</u-form-item>
<u-form-item label="申请人" prop="APPLY_USER_NAME" borderBottom required>
<u-input v-model="form.APPLY_USER_NAME" border="none" readonly/>
</u-form-item>
<u-form-item label="作业分公司" prop="CORP_NAME" borderBottom required>
<u-input v-model="form.CORP_NAME" border="none" readonly/>
</u-form-item>
<u-form-item label="受限空间所属单位" prop="BELONG_CORP" borderBottom required>
<u-input v-model="form.BELONG_CORP" border="none"/>
</u-form-item>
<u-form-item label="受限空间名称" prop="LIMITSPACE_NAME" borderBottom required
@click="fnSingleChoiceClick('LIMITSPACE_NAME')">
<u-input v-model="form.LIMITSPACE_NAME" border="none" readonly/>
<u-icon name="arrow-right"></u-icon>
</u-form-item>
<u-form-item label="受限空间内原有介质名称" prop="MEDIUM_NAME" borderBottom required>
<u-input v-model="form.MEDIUM_NAME" border="none"/>
</u-form-item>
<u-form-item label="作业内容" prop="WORK_CONTENT" borderBottom required labelPosition="top">
<u-textarea v-model="form.WORK_CONTENT" border="none" autoHeight/>
</u-form-item>
<u-form-item label="作业开始时间" prop="WORK_START_DATE" borderBottom required
@click="fnDateTimePickerClick('WORK_START_DATE')">
<u-input v-model="form.WORK_START_DATE" border="none" readonly/>
<u-icon name="arrow-right"></u-icon>
</u-form-item>
<u-form-item label="作业结束时间" prop="WORK_END_DATE" borderBottom required
@click="fnDateTimePickerClick('WORK_END_DATE')">
<u-input v-model="form.WORK_END_DATE" border="none" readonly/>
<u-icon name="arrow-right"></u-icon>
</u-form-item>
<u-form-item label="地点坐标" borderBottom required>
<u-button type="primary" size="small" text="定位" :customStyle="{width:'100upx',margin:0}"
@click="fnLocation"/>
</u-form-item>
<u-form-item label="经度" prop="WORK_LONGITUDE" borderBottom required>
<u-input v-model="form.WORK_LONGITUDE" border="none" readonly/>
</u-form-item>
<u-form-item label="纬度" prop="WORK_LATITUDE" borderBottom required>
<u-input v-model="form.WORK_LATITUDE" border="none" readonly/>
</u-form-item>
<u-form-item label="作业人" prop="WORK_USER" borderBottom required>
<u-input v-model="form.WORK_USER" border="none"/>
</u-form-item>
<u-form-item label="关联的其他特殊作业及安全作业票编号" prop="SPECIAL_WORK" borderBottom required
labelPosition="top" labelWidth="auto">
<u-button type="primary" size="mini" text="选择其它"
:customStyle="{position: 'absolute',top: '-46upx',right: '20upx',width: '150upx'}"
@click="otherAssignmentsShow = true"/>
<u-textarea v-model="form.SPECIAL_WORK" border="none" autoHeight maxlength="-1"/>
</u-form-item>
<u-form-item label="风险辨识结果" prop="RISK_IDENTIFICATION" borderBottom required labelPosition="top"
labelWidth="auto">
<u-button type="primary" size="mini" text="选择其它"
:customStyle="{position: 'absolute',top: '-46upx',right: '20upx',width: '150upx'}"
@click="otherIdentificationShow = true"/>
<u-textarea v-model="form.RISK_IDENTIFICATION" border="none" autoHeight maxlength="-1"/>
</u-form-item>
</u-form>
<view class="mt-10">
<u-button type="primary" text="下一步" @click="$u.debounce(fnSubmit, 1000,true)"/>
</view>
</view>
<u-picker :show="picker.show" :columns="picker.columns" :keyName="picker.key" :key="picker.type"
@confirm="fnSingleChoiceConfirm" @cancel="fnSingleChoiceCancel"/>
<u-datetime-picker :show="dateTimePicker.show" v-model="dateTimePicker.value" :mode="dateTimePicker.mode"
:minDate="dateTimePicker.min" :key="dateTimePicker.type" @confirm="fnDateTimePickerConfirm"
@cancel="fnDateTimePickerCancel"/>
<other-select :visible.sync="otherAssignmentsShow" v-model="form.SPECIAL_WORK" type="assignments"/>
<other-select :visible.sync="otherIdentificationShow" v-model="form.RISK_IDENTIFICATION" type="identification"/>
</view>
</template>
<script>
import {
getConfinedSpaceSelectList
} from '../../../api/index'
import OtherSelect from '@/components/other-select/index.vue';
import {getConfinedSpaceSelectList} from '../../../api/index'
import OtherSelect from '@/components/other-select/index.vue';
import {setSubmitForm} from "@/utils/submitHomeworkProcess";
export default {
components: {
OtherSelect
},
data() {
return {
form: {
APPLY_DEPARTMENT_ID: this.$store.getters.getUserInfo.DEPARTMENT_ID,
APPLY_DEPARTMENT_NAME: this.$store.getters.getUserInfo.DEPARTMENT_NAME,
APPLY_USER_ID: this.$store.getters.getUserInfo.USER_ID,
APPLY_USER_NAME: this.$store.getters.getUserInfo.NAME,
BELONG_CORP: '',
LIMITSPACE_NAME: '',
LIMITSPACE_ID: '',
MEDIUM_NAME: '',
WORK_CONTENT: '',
WORK_START_DATE: '',
WORK_END_DATE: '',
WORK_LONGITUDE: '',
WORK_LATITUDE: '',
WORK_USER: '',
SPECIAL_WORK: '',
},
rules: {},
picker: {
show: false,
columns: [],
key: 'NAME',
type: ''
},
datetimePicker: {
show: false,
value: Number(new Date()),
min: new Date().getTime(),
mode: 'datetime',
type: ''
},
otherAssignmentsShow: false,
otherIdentificationShow: false,
}
},
onLoad(options) {
this.form.CORP_ID = options.CORPINFO_ID
this.form.CORP_NAME = options.CORP_NAME
},
methods: {
async fnGetConfinedSpaceSelectList() {
const resData = await getConfinedSpaceSelectList()
this.picker.columns = [resData.varList]
},
fnSingleChoiceClick(event) {
this.picker.type = event
if (event === 'LIMITSPACE_NAME') this.fnGetConfinedSpaceSelectList()
this.picker.show = true
},
fnSingleChoiceConfirm(event) {
if (this.picker.type === 'LIMITSPACE_NAME') {
this.form.LIMITSPACE_ID = event.value[0].LIMITSPACE_ID
this.form.LIMITSPACE_NAME = event.value[0].NAME
}
this.fnSingleChoiceCancel()
},
fnSingleChoiceCancel() {
this.picker.show = false
},
fnDateTimePickerClick(event) {
this.datetimePicker.type = event
this.datetimePicker.value = Number(new Date(this.form[event])) || Number(new Date())
this.datetimePicker.show = true
},
fnDateTimePickerConfirm(event) {
this.form[this.datetimePicker.type] = uni.$u.timeFormat(event.value, 'yyyy-mm-dd hh:MM')
this.fnDateTimePickerCancel()
},
fnDateTimePickerCancel() {
this.datetimePicker.show = false
},
fnLocation() {
uni.navigateTo({
url: '/pages/map/index',
events: {
acceptLocationData: (event) => {
this.form.WORK_LONGITUDE = event.data.longitue;
this.form.WORK_LATITUDE = event.data.latitude;
}
},
})
}
}
}
export default {
components: {
OtherSelect
},
data() {
return {
formItems: [
{name: '申请单位', key_name: 'APPLY_DEPARTMENT_NAME', key_id: 'APPLY_DEPARTMENT_ID', type: 0},
{name: '申请人', key_name: 'APPLY_USER_NAME', key_id: 'APPLY_USER_ID', type: 0},
{name: '作业分公司', key_name: 'CORP_NAME', key_id: 'CORP_ID', type: 0},
{name: '受限空间所属单位', key_name: 'BELONG_CORP', type: 0},
{name: '受限空间名称', key_name: 'LIMITSPACE_NAME', key_id: 'LIMITSPACE_ID', type: 0},
{name: '受限空间内原有介质名称', key_name: 'MEDIUM_NAME', type: 0},
{name: '作业内容', key_name: 'WORK_CONTENT', type: 0},
{name: '作业开始时间', key_name: 'WORK_START_DATE', type: 0},
{name: '作业结束时间', key_name: 'WORK_END_DATE', type: 0},
{name: '经度', key_name: 'WORK_LONGITUDE', type: 0},
{name: '纬度', key_name: 'WORK_LATITUDE', type: 0},
{name: '作业人', key_name: 'WORK_USER', type: 0},
{name: '关联的其他特殊作业及安全作业票编号', key_name: 'SPECIAL_WORK', type: 0},
{name: '风险辨识结果', key_name: 'RISK_IDENTIFICATION', type: 0},
],
form: {
APPLY_DEPARTMENT_ID: this.$store.getters.getUserInfo.DEPARTMENT_ID,
APPLY_DEPARTMENT_NAME: this.$store.getters.getUserInfo.DEPARTMENT_NAME,
APPLY_USER_ID: this.$store.getters.getUserInfo.USER_ID,
APPLY_USER_NAME: this.$store.getters.getUserInfo.NAME,
CORP_ID: '',
CORP_NAME: '',
BELONG_CORP: '',
LIMITSPACE_NAME: '',
LIMITSPACE_ID: '',
MEDIUM_NAME: '',
WORK_CONTENT: '',
WORK_START_DATE: '',
WORK_END_DATE: '',
WORK_LONGITUDE: '1',
WORK_LATITUDE: '2',
WORK_USER: '',
SPECIAL_WORK: '',
RISK_IDENTIFICATION: '',
},
rules: {
APPLY_DEPARTMENT_ID: [{type: 'string', required: true, message: '请选择申请单位', trigger: 'blur'}],
APPLY_DEPARTMENT_NAME: [{type: 'string', required: true, message: '请选择申请人', trigger: 'blur'}],
APPLY_USER_NAME: [{type: 'string', required: true, message: '请选择申请人', trigger: 'blur'}],
CORP_NAME: [{type: 'string', required: true, message: '请选择作业分公司', trigger: 'blur'}],
BELONG_CORP: [{type: 'string', required: true, message: '请输入受限空间所属单位', trigger: 'blur'}],
// LIMITSPACE_NAME: [{type: 'string', required: true, message: '', trigger: 'blur'}],
MEDIUM_NAME: [{type: 'string', required: true, message: '请输入受限空间内原有介质名称', trigger: 'blur'}],
WORK_CONTENT: [{type: 'string', required: true, message: '请输入作业内容', trigger: 'blur'}],
WORK_START_DATE: [{type: 'string', required: true, message: '请选择作业开始时间', trigger: 'blur'}],
WORK_END_DATE: [{type: 'string', required: true, message: '请选择作业结束时间', trigger: 'blur'}],
WORK_LONGITUDE: [{type: 'string', required: true, message: '请选择经度', trigger: 'blur'}],
WORK_LATITUDE: [{type: 'string', required: true, message: '请选择纬度', trigger: 'blur'}],
WORK_USER: [{type: 'string', required: true, message: '请输入作业人', trigger: 'blur'}],
SPECIAL_WORK: [{
type: 'string',
required: true,
message: '请输入关联的其他特殊作业及安全作业票编号',
trigger: 'blur'
}],
RISK_IDENTIFICATION: [{type: 'string', required: true, message: '请输入风险辨识结果', trigger: 'blur'}],
},
picker: {
show: false,
columns: [],
key: 'NAME',
type: 'picker'
},
dateTimePicker: {
show: false,
value: Number(new Date()),
min: new Date().getTime(),
mode: 'datetime',
type: 'datetime-picker'
},
otherAssignmentsShow: false,
otherIdentificationShow: false,
}
},
onLoad(options) {
this.form.CORP_ID = options.CORPINFO_ID
this.form.CORP_NAME = options.CORP_NAME
},
methods: {
async fnGetConfinedSpaceSelectList() {
const resData = await getConfinedSpaceSelectList({TYPE: 2})
this.picker.columns = [resData.list.list]
},
fnSingleChoiceClick(event) {
this.picker.type = event
if (event === 'LIMITSPACE_NAME') this.fnGetConfinedSpaceSelectList()
this.picker.show = true
},
fnSingleChoiceConfirm(event) {
if (this.picker.type === 'LIMITSPACE_NAME') {
this.form.LIMITSPACE_ID = event.value[0].LIMITSPACE_ID
this.form.LIMITSPACE_NAME = event.value[0].NAME
}
this.fnSingleChoiceCancel()
},
fnSingleChoiceCancel() {
this.picker.show = false
},
fnDateTimePickerClick(event) {
this.dateTimePicker.type = event
this.dateTimePicker.value = Number(new Date(this.form[event])) || Number(new Date())
this.dateTimePicker.show = true
},
fnDateTimePickerConfirm(event) {
this.form[this.dateTimePicker.type] = uni.$u.timeFormat(event.value, 'yyyy-mm-dd hh:MM')
this.fnDateTimePickerCancel()
},
fnDateTimePickerCancel() {
this.dateTimePicker.show = false
},
fnLocation() {
uni.navigateTo({
url: '/pages/map/index',
events: {
acceptLocationData: (event) => {
this.form.WORK_LONGITUDE = event.data.longitue;
this.form.WORK_LATITUDE = event.data.latitude;
}
},
})
},
async fnSubmit() {
try {
await this.$refs.formRef.validate()
try {
await setSubmitForm({
form: this.form,
formItems: this.formItems,
TYPE: 'confinedSpace',
CORP_ID: this.form.CORP_ID
})
} catch {
}
} catch {
uni.$u.toast('请补全必填项')
}
}
}
}
</script>
<style>
</style>
</style>

View File

@ -19,20 +19,20 @@
return {
baseList: [
{
img: require('../../../static/icon-apps/app_icons.png'),
img: require('../../../static/icon-apps/i9.png'),
title: '申请',
url: '/pages/selete_corp_info/index',
url: '/pages/eight_assignments/select_corp_info',
params: {
type: 'confined_space'
}
},
{
img: require('../../../static/icon-apps/app_icons.png'),
img: require('../../../static/icon-apps/i10.png'),
title: '待办',
url: '/pages/eight_assignments/confined_space/index'
},
{
img: require('../../../static/icon-apps/app_icons.png'),
img: require('../../../static/icon-apps/i11.png'),
title: '已办',
url: '/pages/eight_assignments/confined_space/index'
},
@ -63,8 +63,8 @@
margin-top: 20upx;
image {
width: 136upx;
height: 136upx;
width: 110upx;
height: 110upx;
}
.text {
@ -74,4 +74,4 @@
}
}
}
</style>
</style>

View File

@ -19,42 +19,42 @@
return {
baseList: [
{
img: require('../../static/icon-apps/app_icons.png'),
img: require('../../static/icon-apps/i1.png'),
title: '受限空间安全作业',
url: '/pages/eight_assignments/confined_space/index'
},
{
img: require('../../static/icon-apps/app_icons.png'),
img: require('../../static/icon-apps/i2.png'),
title: '盲板抽堵作业',
url: '/pages/electronic_work_card/index'
},
{
img: require('../../static/icon-apps/app_icons.png'),
img: require('../../static/icon-apps/i3.png'),
title: '动土作业',
url: '/pages/electronic_work_card/index'
},
{
img: require('../../static/icon-apps/app_icons.png'),
img: require('../../static/icon-apps/i4.png'),
title: '高处作业',
url: '/pages/electronic_work_card/index'
},
{
img: require('../../static/icon-apps/app_icons.png'),
img: require('../../static/icon-apps/i5.png'),
title: '吊装作业',
url: '/pages/electronic_work_card/index'
},
{
img: require('../../static/icon-apps/app_icons.png'),
img: require('../../static/icon-apps/i6.png'),
title: '临时用电作业',
url: '/pages/electronic_work_card/index'
},
{
img: require('../../static/icon-apps/app_icons.png'),
img: require('../../static/icon-apps/i7.png'),
title: '动火作业',
url: '/pages/electronic_work_card/index'
},
{
img: require('../../static/icon-apps/app_icons.png'),
img: require('../../static/icon-apps/i8.png'),
title: '断路作业',
url: '/pages/electronic_work_card/index'
},
@ -84,8 +84,8 @@
margin-top: 20upx;
image {
width: 136upx;
height: 136upx;
width: 110upx;
height: 110upx;
}
.text {
@ -95,4 +95,4 @@
}
}
}
</style>
</style>

View File

@ -1,9 +1,9 @@
<template>
<view class="content">
<view class="card">
<u-radio-group v-model="selete_corp" placement="column">
<u-radio :customStyle="{marginBottom: '20upx'}" v-for="(item, index) in list" :key="item.CORPINFO_ID"
:label="item.CORP_NAME" :name="item.CORPINFO_ID">
<u-radio-group v-model="select_corp" placement="column">
<u-radio :customStyle="{marginBottom: '20rpx'}" v-for="item in list" :key="item.CORPINFO_ID"
:label="item.NAME" :name="item.CORPINFO_ID">
</u-radio>
</u-radio-group>
<view class="button_placeholder"></view>
@ -17,14 +17,14 @@
<script>
import {
getCorpInfoList
} from '../../api/index'
} from '../../api'
export default {
data() {
return {
type: '',
list: [],
selete_corp: ''
select_corp: ''
}
},
onLoad(options) {
@ -34,10 +34,10 @@
methods: {
async fnGetData() {
const resData = await getCorpInfoList()
this.list = resData.data
this.list = resData.list.corpInfoDos
},
fnConfirm() {
if (!this.selete_corp) {
if (!this.select_corp) {
uni.$u.toast('请选择作业分公司')
return;
}
@ -47,13 +47,13 @@
'default': '/pages/eight_assignments/confined_space/apply'
}
}
const url = urlByTypeMap[this.type][this.selete_corp] ?? urlByTypeMap[this.type].default
const url = urlByTypeMap[this.type][this.select_corp] ?? urlByTypeMap[this.type].default
let params = {}
for (let i = 0; i < this.list.length; i++) {
if (this.list[i].CORPINFO_ID === this.selete_corp) {
if (this.list[i].CORPINFO_ID === this.select_corp) {
params = {
CORPINFO_ID: this.list[i].CORPINFO_ID,
CORP_NAME: this.list[i].CORP_NAME,
CORP_NAME: this.list[i].NAME,
}
break
}
@ -70,7 +70,7 @@
<style scoped lang="scss">
.button_placeholder {
height: 100upx;
height: 100rpx;
}
.button {
@ -79,4 +79,4 @@
left: 0;
right: 0;
}
</style>
</style>

View File

@ -0,0 +1,88 @@
<template>
<view>
<u-modal :show="modelShow" title="选择所属端" showCancelButton cancelText="返回" @cancel="fnModalCancel"
@confirm="fnModalConfirm">
<u-radio-group v-model="type" placement="column">
<u-radio :customStyle="{marginBottom: '8px'}" label="企业端" name="0"/>
<u-radio :customStyle="{marginBottom: '8px'}" label="监管端" name="1"/>
<u-radio :customStyle="{marginBottom: '8px'}" label="相关方端" name="2"/>
</u-radio-group>
</u-modal>
<next-tree
v-if="!modelShow"
uiMode="page"
ref="nextTreeRef"
checkStrictly
funcMode="radio"
selectParent
:ifSearch="false"
:treeData="treeData"
themeColor="#2a56f7"
page-height="92vh"
labelKey="DEPARTMENT_NAME"
valueKey="DEPARTMENT_ID"
childrenKey="nodes"
@change="fnTreeChange"
>
<template #fixedBottomBar>
<view style="padding: 20upx;margin-bottom: 20upx;">
<u-button type="primary" text="确定" @click="fnTreeConfirm"/>
</view>
</template>
</next-tree>
</view>
</template>
<script>
import {getDepartmentTree} from "@/api";
export default {
data() {
return {
modelShow: true,
type: '',
CORP_ID: '',
treeData:[],
treeSelectData:[]
}
},
onLoad(query) {
this.CORP_ID = query.CORP_ID
},
methods: {
fnModalCancel() {
uni.navigateBack()
},
fnModalConfirm() {
if (!this.type) {
uni.$u.toast('请选择所属端')
return
}
this.modelShow = false
this.fnGetDepartmentTree()
},
async fnGetDepartmentTree() {
let CORP_ID = ''
if (this.type === '0') CORP_ID = this.CORP_ID
if (this.type === '2') CORP_ID = this.$store.getters.getUserInfo.CORPINFO_ID
let resData = await getDepartmentTree({TYPE: this.type, CORP_ID})
this.treeData = resData.tree.tree
},
fnTreeChange(event){
this.treeSelectData = event
},
fnTreeConfirm(){
this.getOpenerEventChannel().emit("confirm", {
DEPARTMENT_NAME: this.treeSelectData[0].DEPARTMENT_NAME,
DEPARTMENT_ID: this.treeSelectData[0].DEPARTMENT_ID,
TYPE: this.type
});
uni.navigateBack();
}
},
}
</script>
<style scoped lang="scss">
</style>

View File

@ -0,0 +1,131 @@
<template>
<view>
<view class="content">
<view class="card">
<u-form labelPosition="left" :model="form" :rules="rules" ref="formRef" labelWidth="140px">
<u-form-item v-for="(item, index) in list" :key="index" :label="item.name" :prop="item.key_name"
borderBottom :required="item.isRequired === '1'" @click="fnSelect(item)">
<u-input v-model="form[item.key_name]" border="none" readonly/>
<u-icon name="arrow-right"></u-icon>
</u-form-item>
</u-form>
<view class="mt-10">
<u-button type="primary" text="下一步" @click="$u.debounce(fnSubmit, 1000,true)"/>
</view>
</view>
</view>
<u-picker :show="picker.show" :columns="picker.columns" keyName="NAME"
:key="picker.currentColumnKey" @confirm="fnPickerConfirm" @cancel="fnPickerCancel"/>
</view>
</template>
<script>
import {getUserList} from "@/api";
import {setPersonnelForm} from "@/utils/submitHomeworkProcess";
export default {
data() {
return {
taskId: '',
CORP_ID: '',
TYPE: '',
list: [],
form: {},
rules: {},
picker: {
show: false,
columnsAll: {},
columns: [],
currentColumnKey: '',
currentName: '',
currentId: '',
}
}
},
onLoad() {
const eventChannel = this.getOpenerEventChannel();
eventChannel.on('nextNodes', (data) => {
this.list = data.nextNodes
this.taskId = data.taskId
this.CORP_ID = data.CORP_ID
this.TYPE = data.TYPE
this.fnInitFormAndRules()
})
},
methods: {
fnInitFormAndRules() {
this.list.forEach((item) => {
this.$set(this.form, item.key_name, '')
this.$set(this.form, item.key_id, '')
this.$set(this.rules, item.key_name, [{
required: item.isRequired === '1',
message: item.name + '不能为空',
trigger: 'blur',
}])
})
},
fnSelect({key_name, key_id, type, value}) {
if (type === '1') {
this.fnSelectDepartment(key_name, key_id, value)
return
}
if (type === '0') {
//
this.fnSelectUser(key_name, key_id, value)
}
},
fnSelectDepartment(key_name, key_id, value) {
uni.navigateTo({
url: `/pages/eight_assignments/select_department?CORP_ID=${this.CORP_ID}`,
events: {
confirm: (event) => {
this.form[key_name] = event.DEPARTMENT_NAME
this.form[key_id] = event.DEPARTMENT_ID
this.form[value + '_USER_ID'] = ''
this.form[value + '_USER_NAME'] = ''
this.fnGetUserList(event, value)
}
},
})
},
async fnGetUserList({DEPARTMENT_ID, TYPE}, value) {
let resData = await getUserList({DEPARTMENT_ID, TYPE})
this.$set(this.picker.columnsAll, value, [resData.list.list])
},
fnSelectUser(key_name, key_id, value) {
this.picker.currentName = key_name
this.picker.currentId = key_id
this.picker.currentColumnKey = value
this.picker.columns = this.picker.columnsAll[this.picker.currentColumnKey]
if (!this.picker.columnsAll[this.picker.currentColumnKey]) {
uni.$u.toast('没有选择部门或当前部门没有人员')
return
}
this.picker.show = true
},
fnPickerConfirm(event) {
this.form[this.picker.currentId] = event.value[0].USER_ID
this.form[this.picker.currentName] = event.value[0].NAME
this.fnPickerCancel()
},
fnPickerCancel() {
this.picker.show = false
},
async fnSubmit() {
try {
await this.$refs.formRef.validate()
try {
await setPersonnelForm({form: this.form,list:this.list, taskId: this.taskId, CORP_ID: this.CORP_ID, TYPE: this.TYPE})
} catch {
}
} catch {
uni.$u.toast('请补全必填项')
}
}
},
}
</script>
<style scoped lang="scss">
</style>

View File

@ -16,14 +16,16 @@
</view>
</view>
<view class="home-apps">
<view class="home-apps-item" v-for="(item,index) in baseList" :key="index" @click="fnNavigator(index)">
<view class="home-apps-item-img">
<image :src="item.img" mode=""></image>
<template v-for="(item,index) in baseList">
<view class="home-apps-item" :key="index" v-if="fnIsShow(index)" @click="fnNavigator(index)">
<view class="home-apps-item-img">
<image :src="item.img" mode=""></image>
</view>
<view class="text">
<text>{{ item.title }}</text>
</view>
</view>
<view class="text">
<text>{{ item.title }}</text>
</view>
</view>
</template>
</view>
<u-modal :show="updateVersion.modalShow" title="温馨提示" :showConfirmButton="updateVersion.showConfirmButton"
:showCancelButton="updateVersion.showCancelButton" :confirmText="updateVersion.confirmText" :cancelText="updateVersion.cancelText"
@ -70,13 +72,18 @@ export default {
url: '/pages/employed_by/index'
},
{
img: require('../../static/icon-apps/app_icons5.png'),
img: require('../../static/icon-apps/app_icons6.png'),
title: '高危作业',
url: '/pages/eight_assignments/index'
},
],
}
},
computed: {
userInfo() {
return this.$store.getters.getUserInfo
}
},
onLoad() {
this.fnUpdateVersion(false)
},
@ -109,6 +116,10 @@ export default {
}
});
},
fnIsShow(index){
if(index === 5) return !!this.userInfo.CORPINFO_ID
return true
},
fnNavigator(e) {
uni.$u.route({
url: this.baseList[e].url

View File

@ -36,8 +36,8 @@ export default {
return {
publicKey: 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2zCyUYSD0pNrbtaYdvGfHfWoRV+fo/2N9O2PLLz/jZvMkigkq4eAq4JO+Ek0wDHI9WxP6iTSLYCHhIOs9CQTPvyldJFm8riZtQZlBTD8Plkb3rjrgwTqbBi3w3+HKYdkSvGFXJIdSOPbpXnj5BzN8vlVaybs24R/vpUzG9178lwIDAQAB',
form: {
userName: '',
userPwd: ''
userName: '14730797906',
userPwd: 'Aa@123456789'
}
}
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
static/icon-apps/i1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
static/icon-apps/i10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

BIN
static/icon-apps/i11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
static/icon-apps/i2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
static/icon-apps/i3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
static/icon-apps/i4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
static/icon-apps/i5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

BIN
static/icon-apps/i6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

BIN
static/icon-apps/i7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
static/icon-apps/i8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
static/icon-apps/i9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@ -0,0 +1,20 @@
## 1.0.92023-07-06
增加clear时同事发送input事件
## 1.0.82023-06-16
更新修复input事件
## 1.0.72023-06-15
增加输入事件
## 1.0.62023-06-09
增加demo
## 1.0.52023-06-09
更新more插槽的使用说明
## 1.0.42023-06-09
修复mode=more模式下input事件
## 1.0.32023-06-08
更改模式
## 1.0.22023-06-08
更改说明文件模式
## 1.0.12023-06-08
更新说明
## 1.0.02023-06-08
初始化next-search-more

View File

@ -0,0 +1,239 @@
<template>
<view class="next-search-more">
<view class="search" :style="{ backgroundColor: backgroundColor }">
<view class="content" :style="{ 'border-radius': radius + 'px', border: border }">
<view class="content-box" :class="{ center: mode === 'center' }">
<text class="icon icon-search">&#xe66f;</text>
<input class="input" :class="{ center: !active && mode === 'center' }" :focus="isFocus" :placeholder="placeholder" v-model="inputVal" @input="input" @focus="focus" @blur="blur" />
<text v-if="isDelShow" class="icon icon-del" @click="clear">&#xe61c;</text>
</view>
<view v-show="(active && isFixedSearchBtn && button === 'inside') || (isDelShow && button === 'inside')" class="searchBtn" @click="search"></view>
</view>
<template v-if="mode === 'common' || mode ==='center'">
<view v-if="button === 'outside'" class="button" :class="{ active: isFixedSearchBtn || active }" @click="search">
<view class="button-item">{{ !isFixedSearchBtn ? searchName : '搜索' }}</view>
</view>
</template>
<template v-else-if="mode === 'more'">
<view class="button active" @click="selectMore">
<view class="button-item"><text class="icon icon-more">&#xe61a;</text></view>
</view>
</template>
</view>
<view class="more-container-parent">
<view v-if="mode === 'more' && showMore" class="more-container">
<slot name="more"></slot>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
mode: {
type: String,
default: 'common'
},
button: {
type: String,
default: 'outside'
},
isFixedSearchBtn: {
type: Boolean,
default: true
},
radius: {
type: String,
default: '60'
},
placeholder: {
type: String,
default: '请输入搜索内容'
},
backgroundColor: {
type: String,
default: '#fff'
},
showMore: {
type: Boolean,
default: false
},
border: { type: String, default: '1px #f5f5f5 solid' }
},
data() {
return {
active: false,
inputVal: '',
searchName: '取消',
isDelShow: false,
isFocus: false,
timer: 0
};
},
methods: {
focus() {
this.active = true;
},
blur() {
this.isFocus = false;
if (!this.inputVal) {
this.active = false;
}
},
input() {
clearInterval(this.timer)
this.timer = setTimeout(() => {
this.$emit('input', this.inputVal);
}, 500)
},
clear() {
this.inputVal = '';
this.active = false;
this.$emit('input', this.inputVal);
this.$emit('search', '');
},
getFocus() {
this.isFocus = true;
},
search() {
if (!this.inputVal) return;
this.$emit('search', this.inputVal);
},
selectMore() {
this.$emit('moreClick')
}
},
created() {
this.$watch(() => this.inputVal, (newVal) => {
if (newVal) {
this.searchName = '搜索';
this.isDelShow = true;
} else {
this.searchName = '取消';
this.isDelShow = false;
}
})
}
};
</script>
<style lang="scss" scoped>
.next-search-more {
.search {
display: flex;
width: 100%;
border-bottom: 1px #f5f5f5 solid;
box-sizing: border-box;
padding: 15upx;
font-size: $uni-font-size-base;
background: #fff;
.content {
display: flex;
align-items: center;
width: 100%;
height: 60upx;
border: 1px #ccc solid;
background: #fff;
overflow: hidden;
transition: all 0.2s linear;
border-radius: 30px;
.content-box {
width: 100%;
display: flex;
align-items: center;
&.center {
justify-content: center;
}
.icon {
padding: 0 15upx;
&.icon-del {
font-size: 38upx;
}
}
.input {
width: 100%;
max-width: 100%;
line-height: 60upx;
height: 60upx;
transition: all 0.2s linear;
&.center {
width: 200upx;
}
&.sub {
// position: absolute;
width: auto;
color: grey;
}
}
}
.searchBtn {
height: 100%;
flex-shrink: 0;
padding: 0 30upx;
background: $uni-color-success;
line-height: 60upx;
color: #fff;
border-left: 1px #ccc solid;
transition: all 0.3s;
}
}
.button {
display: flex;
align-items: center;
justify-content: center;
position: relative;
flex-shrink: 0;
width: 0;
transition: all 0.2s linear;
white-space: nowrap;
overflow: hidden;
&.active {
padding-left: 15upx;
width: 100upx;
}
.icon-more {
font-size: 48upx;
}
}
}
.more-container-parent {
flex-shrink: 0;
width: 100%;
// position: fixed;
// position: sticky;
z-index: 997;
flex-wrap: nowrap;
display: flex;
flex-direction: row;
position: relative;
flex-direction: column;
.more-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: auto;
background-color: #ffffff;
padding: 20rpx;
border-radius: 0 0 30rpx 30rpx;
box-sizing: border-box;
overflow: hidden;
}
}
}
@font-face {
font-family: 'iconfont';
src: url('https://at.alicdn.com/t/c/font_4110624_nikfg21uyk8.ttf?t=1686190660183') format('truetype');
}
.icon {
font-family: iconfont;
font-size: 32upx;
font-style: normal;
color: #999;
}
</style>

View File

@ -0,0 +1,79 @@
{
"id": "next-search-more",
"displayName": "next-search-more(vue2 vue3多端通用)搜索框组合、搜索下拉框组件全端可用",
"version": "1.0.9",
"description": "搜索下拉框,支持多种展示形式,可以结合第三方组件一起使用,可自定义",
"keywords": [
"远程搜索",
"组合搜索",
"配置搜索",
"自定义搜索",
"搜索下拉框"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.1"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "插件不采集任何数据",
"permissions": "无"
},
"npmurl": "",
"type": "component-vue"
},
"uni_modules": {
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "n",
"app-nvue": "n"
},
"H5-mobile": {
"Safari": "n",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "n",
"Edge": "n",
"Firefox": "n",
"Safari": "n"
},
"小程序": {
"微信": "y",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u"
},
"快应用": {
"华为": "n",
"联盟": "n"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

View File

@ -0,0 +1,215 @@
## next-search-more --搜索更多搜索下拉search-more
> 遇到问题或有建议可以加入QQ群(<font color=#f00>455948571</font>)反馈
> 如果觉得组件不错,<font color=#f00>给五星鼓励鼓励</font>咯!
## 使用
>[从uniapp插件市场导入](https://ext.dcloud.net.cn/plugin?name=next-search-more)
```html
<template>
<view class="index">
<view style="padding: 10px 0;background-color:#000000;color: #fff;font-size: 13px;"><text>1. mode=more模式</text></view>
<next-search-more mode="more" :showMore="showMore" @moreClick="moreClick">
<!--以下demo你可以借助第三方的插件实现你想要的任何复杂功能-->
<template #more>
<u--form labelWidth="80" labelAlign="right">
<u-form-item label="radio:">
<u-radio-group v-model="searchForm.radio" placement="row">
<u-radio v-for="(item, index) in optionslist" :key="index" :label="item.name" :name="item.name" />
</u-radio-group>
</u-form-item>
<u-form-item label="checkbox:">
<u-checkbox-group v-model="searchForm.checkbox" placement="row">
<u-checkbox v-for="(item, index) in optionslist" :key="index" :label="item.name" :name="item.name" />
</u-checkbox-group>
</u-form-item>
<u-form-item label="rate:">
<u-rate :count="5" v-model="searchForm.rate" />
</u-form-item>
<u-form-item label="switch:">
<u-switch v-model="searchForm.switch"></u-switch>
</u-form-item>
<u-form-item label="other:">
<next-search-select
:multiple="false"
:list="options"
label-key="projectName"
value-key="id"
placeholder=" 请选择报备项目"
title="选择报备项目"
v-model:value="searchForm.projectId"
@search="searchFunc"
@change="changeCallback"
clearable
></next-search-select>
</u-form-item>
<view class="flex-row">
<u-button @click="cancel" :customStyle="{margin: '10rpx'}" text="取消"></u-button>
<u-button @click="comfirm" :customStyle="{margin: '10rpx'}" type="primary" text="确定"></u-button>
</view>
</u--form>
</template>
</next-search-more>
<view style="padding: 10px 0;background-color:#000000;color: #fff;font-size: 13px;"><text>2. mode=common;button=outside模式</text></view>
<next-search-more mode="common" button="outside" />
<view style="padding: 10px 0;background-color:#000000;color: #fff;font-size: 13px;"><text>3. mode=common;button=inside模式</text></view>
<next-search-more mode="common" button="inside" />
<view style="padding: 10px 0;background-color:#000000;color: #fff;font-size: 13px;"><text>4. mode=center;button=outside模式</text></view>
<next-search-more mode="center" button="outside" />
<view style="padding: 10px 0;background-color:#000000;color: #fff;font-size: 13px;"><text>5. mode=center;button=inside模式</text></view>
<next-search-more mode="center" button="inside" />
<view style="padding: 10px 0;background-color:#000000;color: #fff;font-size: 13px;"><text>6. mode=center;button=inside;isFixedSearchBtn=false模式</text></view>
<next-search-more mode="center" button="inside" :isFixedSearchBtn="false" />
<view class="content-block"><text>全站ICON图标海量下载iconfont图标大全,为你优选-包图网,全站ICON图标海量下载iconfont图标大全,为你优选-包图网</text></view>
</view>
</template>
```
### vue3 + ts 使用
```js
<script lang="ts">
import { ref, nextTick, toRefs, toRaw, unref, reactive } from 'vue'
export default {
setup() {
const showMore = ref(false)
const searchForm = reactive({
radio: '',
checkbox: '',
rate: 3,
switch: false,
projectId: ''
})
let dataLength = 0
const options = ref<any>([])
const optionslist = ref([{
name: '苹果',
disabled: false
},
{
name: '香蕉',
},
{
name: '橙子',
}
])
function cancel () {
showMore.value = false
}
function comfirm () {
showMore.value = false
}
function moreClick () {
showMore.value = !unref(showMore)
}
function searchFunc(val?) {
console.log("搜索的关键字:", val)
uni.showLoading({
title: '请稍后...',
icon: 'none'
})
// 模拟ajax请求
setTimeout(() => {
options.value = []
dataLength = 0
if (dataLength < 40) {
for (let i = 0; i < 40; i++) {
options.value.push({
id: `id-${val ? val + '-' : ''}${dataLength + i}`,
projectName: `项目item-${val ? val + '-' : ''}${dataLength + i}`,
ohterKey: `test-${i}`
})
}
dataLength = unref(options).length
}
uni.hideLoading()
}, 1000)
}
function changeCallback(item) {
console.log("选中的item", item)
}
searchFunc()
return {
showMore,
moreClick,
optionslist,
searchForm,
searchFunc,
options,
changeCallback,
comfirm,
cancel
}
}
}
</script>
<style lang="scss">
.flex-row {
display: flex;
justify-content: space-around;
}
.content-block {
border-radius: 20rpx;
border: 1rpx solid #ccc;
margin: 20rpx;
padding: 20rpx;
}
</style>
<style lang="scss">
page {
background: #ccc;
}
</style>
```
### vue2 同样支持在这里不再写demo
### 组件按需加载
如果不需要组件全局加载而已把组件拷贝到项目的components目录下单独引入进来使用即可达到按需加载的效果
### 预览
***
| 功能预览 | | 项目中应用演示 |
| :--------------------------------------------------------------------------:| | :-----------------------------------------------------------------------------:|
| ![](https://lixueshiaa.github.io/webtest/www/static/next-search-more.gif) | | ![](https://lixueshiaa.github.io/webtest/www/static/next-search-more-demo.gif) |
## 参数
### next-search-more Props
可选参数属性列表
|参数名 |说明 |类型 |是否必填 |默认值 |可选值 |
|---- |---- |---- |---- |---- |---- |
|mode |模式mode支持common模式 center模式 more模式 |String |否 |common |center,more|
|button |搜索按钮的模式支持outside模式 inside模式 |String |否 |outside |inside |
|isFixedSearchBtn |是否固定搜索按钮 |Boolean |否 |true |false |
|radius |搜索控件的radius |String, Number |否 |60 |- |
|placeholder | placeholder |String |否 |请输入搜索内容 |- |
|backgroundColor |搜索控件的背景颜色 |String |否 |#fff |- |
|showMore | mode=more模式下用于控制打开下拉弹层 |Boolean |否 |false |true |
|border| border |String |否 |1px #f5f5f5 solid |- |
# Event 事件
|事件名 |说明 |类型 |回调参数 |
|---- |---- |---- |---- |
|input |搜索框输入事件 |emit |- |
|search|搜索触发的事件 |emit |- |
|moreClick|更多按钮点击触发事件 |emit |- |
## Slot 插槽
|名称 |说明 |参数 |
|---- |---- |---- |
|more |more插槽在mode=more模式下用于存放下拉框内容 |无 |

View File

@ -0,0 +1,173 @@
## 1.8.92024-06-28
完善说明文件
## 1.8.82024-06-21
更新插件
## 1.8.72024-05-08
fix bug
## 1.8.62024-04-07
功能更新
## 1.8.52024-04-07
修复bug
## 1.8.32024-04-06
update
## 1.8.22024-04-06
update
## 1.8.12024-04-06
fix bug
## 1.8.02024-04-03
优化
## 1.7.92024-04-03
优化编辑tree功能
## 1.7.82024-04-02
超集功能上线
## 1.7.72024-03-26
增加expandedMode=singe
## 1.7.62024-02-27
修复特殊字符的处理方法
## 1.7.52024-02-26
增加无子节点的父节点配置
## 1.7.42024-02-05
修复vue2语法使用问题
## 1.7.32024-02-05
修复vue2插槽不显示bug
## 1.7.22024-02-05
优化大数据的性能
## 1.7.12024-01-25
优化功能说明
## 1.7.02024-01-24
增加expandedKeys默认展开项目配置
## 1.6.92024-01-23
增加change事件
## 1.6.82024-01-22
搜索模式下,不再响应展开收起逻辑
## 1.6.72024-01-04
修复异步加载节点搜索展示bug
## 1.6.62023-12-29
修复next-tree异步加载节点关闭bug
## 1.6.52023-12-21
fix bug
## 1.6.42023-12-21
fix bug
## 1.6.32023-12-21
更新vue2版本说明文档
## 1.6.22023-12-21
修复说明文档
## 1.6.12023-12-18
增加empty插槽
## 1.6.02023-12-18
增加empty插槽
## 1.5.92023-12-15
修改说明文件
## 1.5.82023-12-15
修复changeVerify函数单选时返回参数bug
## 1.5.72023-12-14
修复checkStrictlyModel === 'strong'的bug
## 1.5.62023-12-13
代码优化
## 1.5.52023-12-13
优化changeVerify的使用
## 1.5.42023-12-12
修复提示层级问题
## 1.5.32023-12-12
优化uiMode=page模式下的使用
## 1.5.22023-12-11
增加uiMode配置实现页面模式展示
## 1.5.12023-12-06
更新说明
## 1.5.02023-12-06
更新插件使用注意事项
## 1.4.92023-12-01
增加topBar插槽
## 1.4.82023-11-30
增加changeVerify验证函数实现change的各种控制
## 1.4.72023-11-30
增加弹层容器高度可配置
## 1.4.62023-11-28
修复bug
## 1.4.52023-11-28
修复disabled是需要显示灰色不可操作
## 1.4.42023-11-28
增加说明
## 1.4.32023-11-28
增加主题配置
## 1.4.22023-11-28
增加异步加载时,子节点说明
## 1.4.12023-11-27
修复说明bug
## 1.4.02023-11-27
next-tree 全面说明文档
## 1.3.62023-11-27
增加远程加载loadData全面实现全功能覆盖
## 1.3.52023-11-27
增加title的定义
## 1.3.42023-11-27
增加title支持自定义定制
## 1.3.32023-11-21
增加搜索模式searchModel=depHighlight模式从属高亮显示模式
## 1.3.22023-11-20
修复valueKey设置bug
## 1.3.12023-11-17
增加说明文件和demo
## 1.3.02023-11-17
修复clear时不支持关联模式的设置
## 1.2.92023-11-17
增加checkStrictlyModel模式设置强关联和弱关联
## 1.2.82023-11-16
增加next-tree的辅助线模式
## 1.2.72023-11-16
优化next-tree
## 1.2.62023-11-16
修复搜索时,隐藏未打开的数据
## 1.2.52023-11-16
修复搜索无法点击,和级联半选不生效问题
## 1.2.42023-11-16
更新新功能插件使用说明
## 1.2.32023-11-16
增加插槽模式只是高ui要求定制
## 1.2.22023-11-15
修复checkStrictly配置下子关联父的选择状态
## 1.2.12023-11-15
增加半选提示功能配置showHalfCheckedTips
## 1.2.02023-11-14
修复disabled配置状态下父子级联不需要改变disabled设置项的选择状态
## 1.1.92023-11-13
增强大数据量体验交互,增加筛选搜索模式
## 1.1.82023-11-13
增加清除clear和取消cancel事件
## 1.1.72023-11-08
更新next-tree插件功能清单说明
## 1.1.62023-11-07
update说明文档
## 1.1.52023-11-07
update
## 1.1.42023-11-07
更新readme.md说明
## 1.1.32023-11-07
更新说明demo
## 1.1.22023-11-07
增加子节点按需渲染演示demo
## 1.1.12023-11-07
增加清空功能
## 1.1.02023-11-07
增加子孙节点按需渲染,扩展本插件支持大数据量渲染;
## 1.0.92023-10-26
增加文件说明
## 1.0.82023-09-14
增加禁用节点属性配置disabledKey
## 1.0.72023-09-06
增加checkStrictly实现父子节点关联
## 1.0.62023-09-06
更新vue2使用过程视图不更新的技术说明
## 1.0.52023-09-06
修复说明文档
## 1.0.42023-06-19
修改demo
## 1.0.32023-06-19
更新vue2的使用demo
## 1.0.22023-06-19
修复说明文档
## 1.0.12023-05-10
更新说明文件
## 1.0.02023-05-09
初始化项目

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,272 @@
@font-face {
font-family: 'iconfont';
src: url('//at.alicdn.com/t/c/font_4110624_qs48wckazsh.ttf?t=1712479573821') format('truetype');
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.iconfont {
font-family: iconfont;
font-style: normal;
}
.iconfont-loading {
font-family: iconfont;
display: inline-block;
font-style: normal;
animation: spin 1s linear infinite;
}
.next-tree-mask {
position: fixed;
top: 0rpx;
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
z-index: 997;
background-color: rgba(0, 0, 0, 0.6);
opacity: 0;
transition: all 0.3s ease;
visibility: hidden;
}
.next-tree-mask.show {
visibility: visible;
opacity: 1;
}
.next-tree-cnt {
position: fixed;
top: 0rpx;
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
z-index: 997;
top: 360rpx;
transition: all 0.3s ease;
transform: translateY(100%);
}
.next-tree-cnt.next-tree-cnt-page {
transition: none;
}
.next-tree-cnt.show {
transform: translateY(0);
}
.next-tree-bar {
background-color: #fff;
height: 72rpx;
padding-left: 20rpx;
padding-right: 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
border-bottom-width: 1rpx !important;
border-bottom-style: solid;
border-bottom-color: #f5f5f5;
font-size: 32rpx;
color: #757575;
line-height: 1;
}
.next-tree-bar-btns {
display: inline-block;
display: flex;
flex-direction: row;
}
.btn-divid {
display: inline-block;
width: 1px;
margin: 0 10px;
background-color: #ccc;
}
.next-tree-bar-confirm {
color: #f9ae3d;
}
.next-tree-view {
position: absolute;
top: 0rpx;
right: 0rpx;
bottom: 0rpx;
left: 0rpx;
top: 72rpx;
background-color: #fff;
padding-top: 20rpx;
padding-right: 20rpx;
padding-bottom: 20rpx;
padding-left: 20rpx;
}
.next-tree-view-sc {
height: 100%;
overflow: hidden;
}
.next-tree-view-sc .empty {
text-align: center;
color: #757575;
padding: 30rpx;
}
.next-tree-item-block {
}
.next-tree-item {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 26rpx;
color: #757575;
line-height: 1;
height: 0;
opacity: 0;
transition: 0.2s;
position: relative;
overflow: hidden;
}
.next-tree-item .icon-btn {
font-size: 30rpx;
margin-right: 20rpx;
}
.next-tree-item .left-line {
position: relative;
width: 1rpx;
height: 100%;
box-sizing: border-box;
}
.next-tree-item .left-line::before {
position: absolute;
content: "";
width: 1rpx;
height: 100%;
background-color: rgba(204,204,204,0.9);
box-sizing: border-box;
left: -18rpx;
}
.next-tree-item .parent-horizontal-line {
width: 1rpx;
height: 100%;
position: absolute;
top: 0;
left: 0rpx;
box-sizing: border-box;
background-color: rgba(204,204,204,0.9);
}
.next-tree-item .left-line .horizontal-line {
width: 20rpx;
height: 1rpx;
position: absolute;
top: 40rpx;
left: 0rpx;
background-color: rgba(204,204,204,0.9);
box-sizing: border-box;
}
.next-tree-item.show {
min-height: 80rpx;
margin-top: 10rpx;
height: 100%;
opacity: 1;
}
.next-tree-item.showchild:before {
transform: rotate(90deg);
}
.next-tree-item.border {
border-bottom: 1rpx solid rgba(204,204,204,0.2);
}
.next-tree-item.last:before {
opacity: 0;
}
.next-tree-item.disabled {
color: #ccc!important;
}
.next-tree-icon {
width: 26rpx;
height: 26rpx;
margin-right: 8rpx;
}
.next-tree-label {
flex: 1;
display: flex;
align-items: center;
height: 100%;
line-height: 1.2;
}
.next-tree-label .label-input {
border: 1rpx solid #f0f0f0;
border-radius: 10rpx;
width: 100%;
padding: 12rpx 18rpx;
margin-right: 30rpx;
}
.next-tree-check {
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center;
}
.next-tree-check-yes,
.next-tree-check-no {
width: 20px;
height: 20px;
border-top-left-radius: 20%;
border-top-right-radius: 20%;
border-bottom-right-radius: 20%;
border-bottom-left-radius: 20%;
border-top-width: 1rpx;
border-left-width: 1rpx;
border-bottom-width: 1rpx;
border-right-width: 1rpx;
border-style: solid;
border-color: #f9ae3d;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
}
.next-tree-check-yes-b {
border-top-left-radius: 20%;
border-top-right-radius: 20%;
border-bottom-right-radius: 20%;
border-bottom-left-radius: 20%;
background-color: #f9ae3d;
color: #fff;
}
.next-tree-check-yes-b .icon-text {
font-size: 14px;
font-weight: normal;
font-family: uicon-iconfont;
display: flex;
flex-direction: row;
align-items: center;
}
.next-tree-check .radio {
border-top-left-radius: 50%;
border-top-right-radius: 50%;
border-bottom-right-radius: 50%;
border-bottom-left-radius: 50%;
}
.next-tree-check .radio .next-tree-check-yes-b {
border-top-left-radius: 50%;
border-top-right-radius: 50%;
border-bottom-right-radius: 50%;
border-bottom-left-radius: 50%;
}
.next-tree-item.disabled .next-tree-check-no {
color: #ccc!important;
}
.next-tree-item.disabled .next-tree-check-yes-b {
background-color: #ccc!important;
}
.hover-c {
opacity: 0.6;
}
.fixed-bottom-bar {
border-top: 1px solid #ccc;
position: fixed;
bottom: 0rpx;
left: 0rpx;
right: 0rpx;
z-index: 998;
}

View File

@ -0,0 +1,84 @@
{
"id": "next-tree",
"displayName": "next-tree超强树选择器、树组件、树插件、无限级联树、单选树、多选树、自定义样式树、树形选择器",
"version": "1.8.9",
"description": "next-tree 弹窗树形选择器,支持多选,支持大数据, 无限级联,单选,父子级级联,远程/ajax加载子节点增量/异步渲染,自定义样式定制,具名插槽等;支持h5/小程序/APP全端通用",
"keywords": [
"树选择",
"tree",
"弹窗树选择器",
"多选树",
"单选树"
],
"engines": {
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "修改版本说明",
"permissions": "无"
},
"npmurl": "",
"type": "component-vue"
},
"uni_modules": {
"dependencies": ["next-search-more"],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y",
"alipay": "n"
},
"client": {
"Vue": {
"vue2": "y",
"vue3": "y"
},
"App": {
"app-vue": "y",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "n",
"Edge": "y",
"Firefox": "y",
"Safari": "u"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "u",
"QQ": "y",
"钉钉": "y",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@ -0,0 +1,843 @@
## next-tree --下拉树
> 遇到问题或有建议可以加入QQ群(<font color=#f00>455948571</font>)反馈
> 如果觉得组件不错,<font color=#f00>给五星鼓励鼓励</font>咯!
## 亮点功能说明(打造你不得不用的好插件)
### 本插件自1.5.0版本后支持一下功能
> 1.大数据量渲染本插件智能判断如果子孙集数据量大于50时会响应等待渲染视图
> 2.子节点按需渲染(自动启用,无需配置)
> 3.父子级联选择设置
> 4.单选多选设置
> 5.父节点是否可选设置
> 6.回显默认选中值
> 7.不可选项disabled设置
> 8.增强大数据量体验交互,增加筛选搜索模式
> 9.增强样式定制,提供自定义插槽,实现高要求样式定制
> 10.增加辅助线模式,外观更加精美
> 11.支持动态配置title
> 12.支持搜索模式searchModel=depHighlight模式从属高亮显示模式
> 13.支持异步加载子节点ajax加载子节点
> 14.增加可配置主题,自由定制插件主题颜色
> 15.支持动态校验,可以进行提示控制校验
> 16.支持页面模式/弹层模式,可以进行单页面展示或者弹层展示
> 17.支持半选提示状态显示
> 18.支持展开项expandedKeys配置
> 19.全面支持vue2/vue3
> 20.增加无子节点的父节点配置支持当item[childrenKey]为null时代表无子节点的父节点
> 21.终极支持超数据量使用增加展开模式配置单链路配置使用expandedMode=singe使得ui组件使用进一步不在限制与数据量
> 22.功能模式再次增强支持单选tree多选tree编辑tree展示tree
## 注意
### 作者不介意你对组件源码进行改造使用,为了开源更加高效,谢谢你的配合;为了节省不必要的沟通浪费,以下情况请不要再反馈给作者,请自行解决;
### 在这感各位的理解,我支持开源,但是作者时间有限;谢谢各位的配合;在这里期望我写的小小插件能为你提供便捷;
> 1.如果你对源码进行了修改使用,请不需要对作者做任何的反馈,作者确实没有空陪你做技术分析解答;
> 2.如果你引入插件连插件是否有正常被uniapp框架识别解析都不清楚请你换个插件使用
> 3.如果你引入插件,针对自己项目进行功能改造的,请自行仔细阅读源码并了解其原理,自行改造;这里作者不愿意浪费过多时间进行技术解答;
> 4.如果你不想进行全局加载next-tree需要按需加载next-tree中有相关依赖的组件需要你自行在组件内部单独引入依赖组件可以在package.json中找到
> 5.理论上作者不再解决由于本地开发环境问题所导致的插件使用问题请自行到uniapp官网学习解决
## 使用
### 超集功能即将不对外开源;
>[从uniapp插件市场导入](https://ext.dcloud.net.cn/plugin?name=next-tree)
## 关注作者的动态
[点击进入主页,关注作者](https://ask.dcloud.net.cn/people/ponder_7464)
## 关注作者其他开源
npm开源包[npm](https://www.npmjs.com/~lixueshiaa);
github开源项目[github](https://github.com/lixueshiaa);
```html
<template>
<view style="padding:10px;color: #333;font-weight: 500;">
<view style="padding: 10px 0"><text>1、设置单选和父级不可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(false, false)">设置</button>
<view style="padding: 10px 0"><text>2、设置多选和父级不可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, false)">设置</button>
<view style="padding: 10px 0"><text>3、设置单选和父级可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(false, true)">设置</button>
<view style="padding: 10px 0"><text>4、设置多选和父级可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, true)" >设置</button>
<view style="padding: 10px 0"><text>4、设置多选和父级可选和父级关联子级选择</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, true, true)" >设置</button>
<view style="padding: 10px 0"><text>5、设置默认回显(默认选中: '上海-2', '黄埔区-35')</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="echoDefault()" >设置</button>
<!-- 异步加载demo -->
<view style="padding: 10px 0"><text>6、异步加载渲染demo</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="openTree()" >设置</button>
</view>
<!-- 异步加载demo -->
<next-tree :selectParent="false" :checkStrictly="true" funcMode="checkbox" ref="nextTreeAsyncRef" :treeData="asyncTreeData" :loadData="loadData" />
<next-tree :expandedKeys="['3','3-1']" :changeVerify="changeVerify" :title="getTitle" ref="nextTreeRef" :checkStrictly="checkStrictly" :selectParent="selectParent" :funcMode="funcMode" :treeData="treeData" @cancel="oncancel" @confirm="onconfirm">
<!-- label插槽示意代码 -->
<!-- <template #label="{data: {id, label, iconSrc, prev, post}}">
<view class="line-block">
<image class="img" v-if="iconSrc" :src="iconSrc"></image>
<text space="nbsp" v-if="prev">{{prev}}&nbsp;</text><text>{{label}}</text><text space="nbsp" v-if="post">&nbsp;{{post}}</text>
</view>
</template> -->
<!-- <template #topBar>
<view style="color: #666;padding:5px;"><text style="font-size: 12px;">历史记录</text></view>
<view style="display: flex;justify-content: space-between;padding-bottom: 10px;border-bottom: 1rpx solid #f0f0f0;">
<button @click="checkedFunc('1-3-3-4')" :style="'background-color:'+ (activeId === '1-3-3-4' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">北京区-4</button>
<button @click="checkedFunc('3-1-2')" :style="'background-color:'+ (activeId === '3-1-2' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-2</button>
<button @click="checkedFunc('3-1-6')" :style="'background-color:'+ (activeId === '3-1-6' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-5</button>
</view>
</template> -->
</next-tree>
</template>
```
### vue3 + ts 使用
```ts
<script setup lang="ts">
import { ref, unref } from 'vue'
import nextTree from '@/components/next-tree/next-tree.vue'
const funcMode = ref('radio');
const selectParent = ref(false)
const nextTreeRef = ref()
const nextTreeAsyncRef = ref()
const activeId = ref('')
const localData: any = {
'a1': [{id: 'a1-1', label: 'a1-1'}, {id: 'a1-2', label: 'a1-2',children: [] },{id: 'a1-3', label: 'a1-3'}],
'b1': [{id: 'b1-1', label: 'b1-1',children: []}, {id: 'b1-2', label: 'b1-2'},{id: 'b1-3', label: 'b1-3'}],
'c1': [{id: 'c1-1', label: 'c1-1'}, {id: 'c1-2', label: 'c1-2'},{id: 'c1-3', label: 'c1-3',children: []}],
'a1-2': [{id: 'a1-2-1', label: 'a1-2-1'}, {id: 'a1-2-2', label: 'a1-2-2'}],
'b1-1': [{id: 'b1-1-1', label: 'b1-1-1'}, {id: 'b1-1-2', label: 'b1-1-2'}],
'c1-3': [{id: 'c1-3-1', label: 'c1-3-1'}, {id: 'c1-3-2', label: 'c1-3-2'}]
}
const checkStrictly = ref(false)
const asyncTreeData = ref([{id: 'a1', label: 'a1', children: []},{id: 'b1', label: 'b1', children: []},{id: 'c1', label: 'c1', children: []}])
const treeData = ref([
{id: '1', label: '北京'},
{id: '2', label: '上海', children: [
{id: '2-1', label: '上海-1'},
{id: '2-2', label: '上海-2'},
{id: '2-3', label: '上海-3'},
] },
{id: '3', label: '广州', children: [
{id: '3-1', label: '海珠区', children: [
{id: '3-1-1', label: '海珠区-1'},
{id: '3-1-2', label: '海珠区-2'},
{id: '3-1-4', label: '海珠区-3'},
{id: '3-1-5', label: '海珠区-4'},
{id: '3-1-6', label: '海珠区-5'},
{id: '3-1-7', label: '海珠区-6'},
{id: '3-1-8', label: '海珠区-7'},
{id: '3-1-9', label: '海珠区-8'},
{id: '3-1-10', label: '海珠区-9'},
{id: '3-1-11', label: '海珠区-10'},
]},
{id: '3-2', label: '番禺区', children: [
{id: '3-2-1', label: '番禺区-1'},
{id: '3-2-2', label: '番禺区-2'},
{id: '3-2-4', label: '番禺区-3', children: null}, // 注意: 当childrenKey的值设为null代表无子节点的父节点
{id: '3-2-5', label: '番禺区-4'},
{id: '3-2-6', label: '番禺区-5'},
{id: '3-2-7', label: '番禺区-6'},
{id: '3-2-8', label: '番禺区-7'},
{id: '3-2-9', label: '番禺区-8'},
{id: '3-2-10', label: '番禺区-9'},
{id: '3-2-11', label: '番禺区-10'},
]},
{id: '3-3', label: '黄埔区', children: [
{id: '3-3-1', label: '黄埔区-1'},
{id: '3-3-2', label: '黄埔区-2'},
{id: '3-3-3', label: '黄埔区-3'},
{id: '3-3-4', label: '黄埔区-4'},
{id: '3-3-5', label: '黄埔区-5'},
{id: '3-3-6', label: '黄埔区-6'},
{id: '3-3-7', label: '黄埔区-7'},
{id: '3-3-8', label: '黄埔区-8'},
{id: '3-3-9', label: '黄埔区-9'},
{id: '3-3-10', label: '黄埔区-10'},
{id: '3-3-12', label: '黄埔区-11'},
{id: '3-3-13', label: '黄埔区-12'},
{id: '3-3-13', label: '黄埔区-13'},
{id: '3-3-14', label: '黄埔区-14'},
{id: '3-3-15', label: '黄埔区-15'},
{id: '3-3-16', label: '黄埔区-16'},
{id: '3-3-17', label: '黄埔区-17'},
{id: '3-3-18', label: '黄埔区-18'},
{id: '3-3-19', label: '黄埔区-19'},
{id: '3-3-20', label: '黄埔区-20'},
{id: '3-3-21', label: '黄埔区-21'},
{id: '3-3-22', label: '黄埔区-22'},
{id: '3-3-23', label: '黄埔区-23'},
{id: '3-3-24', label: '黄埔区-24'},
{id: '3-3-25', label: '黄埔区-25'},
{id: '3-3-26', label: '黄埔区-26'},
{id: '3-3-27', label: '黄埔区-27'},
{id: '3-3-28', label: '黄埔区-28'},
{id: '3-3-29', label: '黄埔区-29'},
{id: '3-3-30', label: '黄埔区-30'},
{id: '3-3-31', label: '黄埔区-31'},
{id: '3-3-32', label: '黄埔区-32'},
{id: '3-3-33', label: '黄埔区-33'},
{id: '3-3-34', label: '黄埔区-34'},
{id: '3-3-35', label: '黄埔区-35'},
{id: '3-3-36', label: '黄埔区-36'},
]},
],
}])
function getTitle(checked) {
return `已选:${checked.length}项`
}
function itemclick (_multiple, _selectParent, _checkStrictly = false) {
funcMode.value = _multiple ? 'checkbox' : 'radio';
selectParent.value = _selectParent
checkStrictly.value = _checkStrictly
unref(nextTreeRef).showTree = true
}
function checkedFunc(id) {
if(unref(activeId) === id) {
activeId.value = '';
unref(nextTreeRef).checkedFunc(id, false)
} else {
activeId.value = id;
unref(nextTreeRef).checkedFunc(id)
}
}
function changeVerify(current, chooseList) {
// 注意:返回非空字符串会阻止原有行为,并提示返回的字符串
// 如果函数体不做return返回值即验证通过控件正常处理业务
console.log('当前变化的数据', current)
console.log('已选择的数据', chooseList)
if(chooseList && chooseList.length > 4) {
return '最多可以选择4个节点'
}
}
function openTree() {
unref(nextTreeAsyncRef).showTree = true
}
function echoDefault () {
const selectIds = ['2-1','3-3-35']
checkedTreeData(unref(treeData), selectIds)
console.log('treeData的数据', unref(treeData))
funcMode.value = 'checkbox'
unref(nextTreeRef).showTree = true
}
function loadData(data) {
const type = data.$type; // 加载类型
const source = data.source // 源数据
// 同步实现的代码处理方式
if (type === 'nodeLoad') {
const nodeItem = source;
// 同步实现的代码处理方式
// 如果期望子集节点中还存在孙子节点可以打开,请在初始化数据的时候,初始化个空数组的子节点配置值{[this.childrenKey]: []}
// if(nodeItem && localData[nodeItem.id]) {
// return localData[nodeItem.id]
// } else {
// return []
// }
// 异步的代码实现方式
// 如果期望子集节点中还存在孙子节点可以打开,请在初始化数据的时候,初始化个空数组的子节点配置值{[this.childrenKey]: []}
return new Promise((resolve, reject) => {
setTimeout(() => {
if(nodeItem && localData[nodeItem.id]) {
return resolve(localData[nodeItem.id])
} else {
return resolve([])
}
}, 1000)
})
} else if(type === 'remoteSearch') { // searchModel=remote的时候会在loadData函数中返回type参数供做业务处理
// ...doing
}
}
function checkedTreeData (treeData, selectIds) {
treeData.map(item => {
if (selectIds.indexOf(item.id) !== -1) {
item.checked = true
} else {
item.checked = false
}
if (item.children && item.children.length) {
checkedTreeData(item.children, selectIds)
}
})
}
function oncancel() {
// 清除treeData的选中状态
checkedTreeData(unref(treeData), [])
}
function onconfirm(list) {
console.log('选中项的数量列表list', list)
}
</script>
<style lang="scss">
.line-block {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
.img {
width: 40rpx;
height: 40rpx;
border-radius: 10rpx;
margin: 0 20rpx;
}
}
</style>
```
### vue2 使用
```html
<template>
<view>
<view style="padding:10px;color: #333;font-weight: 500;">
<view style="padding: 10px 0"><text>1、设置单选和父级不可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(false, false)">设置</button>
<view style="padding: 10px 0"><text>2、设置多选和父级不可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, false)">设置</button>
<view style="padding: 10px 0"><text>3、设置单选和父级可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(false, true)">设置</button>
<view style="padding: 10px 0"><text>4、设置多选和父级可选</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, true)" >设置</button>
<view style="padding: 10px 0"><text>4、设置多选和父级可选和父级关联子级选择</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="itemclick(true, true, true)" >设置</button>
<view style="padding: 10px 0"><text>5、设置默认回显(默认选中: '上海-2', '黄埔区-35')</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="echoDefault()" >设置</button>
<!-- 异步加载demo -->
<view style="padding: 10px 0"><text>6、异步加载渲染demo</text></view>
<button style="width: 100%;background-color: #f9ae3d;color:#fff" size="mini" @click="openTree()" >设置</button>
</view>
<!-- 异步加载demo -->
<next-tree :selectParent="false" :checkStrictly="true" funcMode="checkbox" ref="nextTreeAsyncRef" :treeData="asyncTreeData" :loadData="loadData" />
<next-tree :expandedKeys="['3','3-1']" :changeVerify="changeVerify" :title="getTitle" ref="nextTreeRef" :checkStrictly="checkStrictly" :selectParent="selectParent" :funcMode="funcMode" :treeData="treeData" @cancel="oncancel" @confirm="onconfirm">
<!-- label插槽示意代码 -->
<!-- <template v-slot:label="{data}">
<view class="line-block">
<image class="img" v-if="data.iconSrc" :src="data.iconSrc"></image>
<text space="nbsp" v-if="data.prev">{{data.prev}}&nbsp;</text><text>{{data.label}}</text><text space="nbsp" v-if="data.post">&nbsp;{{data.post}}</text>
</view>
</template> -->
<!-- <template #topBar>
<view style="color: #666;padding:5px;"><text style="font-size: 12px;">历史记录</text></view>
<view style="display: flex;justify-content: space-between;padding-bottom: 10px;border-bottom: 1rpx solid #f0f0f0;">
<button @click="checkedFunc('1-3-3-4')" :style="'background-color:'+ (activeId === '1-3-3-4' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">北京区-4</button>
<button @click="checkedFunc('3-1-2')" :style="'background-color:'+ (activeId === '3-1-2' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-2</button>
<button @click="checkedFunc('3-1-6')" :style="'background-color:'+ (activeId === '3-1-6' ? '#f9ae3d' : '#ccc') + ';color:#fff;margin: 5px'" size="mini">海珠区-5</button>
</view>
</template> -->
</next-tree>
</view>
</template>
```
```js
<script>
let self = null;
export default {
data () {
return {
funcMode: 'radio',
selectParent: false,
checkStrictly: false,
activeId: '',
localData:{
'a1': [{id: 'a1-1', label: 'a1-1'}, {id: 'a1-2', label: 'a1-2',children: [] },{id: 'a1-3', label: 'a1-3'}],
'b1': [{id: 'b1-1', label: 'b1-1',children: []}, {id: 'b1-2', label: 'b1-2'},{id: 'b1-3', label: 'b1-3'}],
'c1': [{id: 'c1-1', label: 'c1-1'}, {id: 'c1-2', label: 'c1-2'},{id: 'c1-3', label: 'c1-3',children: []}],
'a1-2': [{id: 'a1-2-1', label: 'a1-2-1'}, {id: 'a1-2-2', label: 'a1-2-2'}],
'b1-1': [{id: 'b1-1-1', label: 'b1-1-1'}, {id: 'b1-1-2', label: 'b1-1-2'}],
'c1-3': [{id: 'c1-3-1', label: 'c1-3-1'}, {id: 'c1-3-2', label: 'c1-3-2'}]
},
asyncTreeData: [{id: 'a1', label: 'a1', children: []},{id: 'b1', label: 'b1', children: []},{id: 'c1', label: 'c1', children: []}],
treeData: [
{id: '1', label: '北京', checked: false},
{id: '2', label: '上海', checked: false, children: [
{id: '2-1', label: '上海-1', checked: false},
{id: '2-2', label: '上海-2', checked: false},
{id: '2-3', label: '上海-3', checked: false},
] },
{id: '3', label: '广州', children: [
{id: '3-1', label: '海珠区', checked: false, children: [
{id: '3-1-1', label: '海珠区-1', checked: false, disabled: true},
{id: '3-1-2', label: '海珠区-2', checked: false},
{id: '3-1-4', label: '海珠区-3', checked: false},
{id: '3-1-5', label: '海珠区-4', checked: false},
{id: '3-1-6', label: '海珠区-5', checked: false},
{id: '3-1-7', label: '海珠区-6', checked: false},
{id: '3-1-8', label: '海珠区-7', checked: false},
{id: '3-1-9', label: '海珠区-8', checked: false},
{id: '3-1-10', label: '海珠区-9', checked: false},
{id: '3-1-11', label: '海珠区-10', checked: false},
]},
{id: '3-2', label: '番禺区', checked: false, children: [
{id: '3-2-1', label: '番禺区-1', checked: false},
{id: '3-2-2', label: '番禺区-2', checked: false},
{id: '3-2-4', label: '番禺区-3', checked: false},
{id: '3-2-5', label: '番禺区-4', checked: false},
{id: '3-2-6', label: '番禺区-5', checked: false},
{id: '3-2-7', label: '番禺区-6', checked: false},
{id: '3-2-8', label: '番禺区-7', checked: false},
{id: '3-2-9', label: '番禺区-8', checked: false},
{id: '3-2-10', label: '番禺区-9', checked: false},
{id: '3-2-11', label: '番禺区-10', checked: false},
]},
{id: '3-3', label: '黄埔区', checked: false, children: [
{id: '3-3-1', label: '黄埔区-1', checked: false},
{id: '3-3-2', label: '黄埔区-2', checked: false},
{id: '3-3-3', label: '黄埔区-3', checked: false},
{id: '3-3-4', label: '黄埔区-4', checked: false},
{id: '3-3-5', label: '黄埔区-5', checked: false},
{id: '3-3-6', label: '黄埔区-6', checked: false},
{id: '3-3-7', label: '黄埔区-7', checked: false},
{id: '3-3-8', label: '黄埔区-8', checked: false},
{id: '3-3-9', label: '黄埔区-9', checked: false},
{id: '3-3-10', label: '黄埔区-10', checked: false},
{id: '3-3-12', label: '黄埔区-11', checked: false},
{id: '3-3-13', label: '黄埔区-12', checked: false},
{id: '3-3-13', label: '黄埔区-13', checked: false},
{id: '3-3-14', label: '黄埔区-14', checked: false},
{id: '3-3-15', label: '黄埔区-15', checked: false},
{id: '3-3-16', label: '黄埔区-16', checked: false},
{id: '3-3-17', label: '黄埔区-17', checked: false},
{id: '3-3-18', label: '黄埔区-18', checked: false},
{id: '3-3-19', label: '黄埔区-19', checked: false},
{id: '3-3-20', label: '黄埔区-20', checked: false},
{id: '3-3-21', label: '黄埔区-21', checked: false},
{id: '3-3-22', label: '黄埔区-22', checked: false},
{id: '3-3-23', label: '黄埔区-23', checked: false},
{id: '3-3-24', label: '黄埔区-24', checked: false},
{id: '3-3-25', label: '黄埔区-25', checked: false},
{id: '3-3-26', label: '黄埔区-26', checked: false},
{id: '3-3-27', label: '黄埔区-27', checked: false},
{id: '3-3-28', label: '黄埔区-28', checked: false},
{id: '3-3-29', label: '黄埔区-29', checked: false},
{id: '3-3-30', label: '黄埔区-30', checked: false},
{id: '3-3-31', label: '黄埔区-31', checked: false},
{id: '3-3-32', label: '黄埔区-32', checked: false},
{id: '3-3-33', label: '黄埔区-33', checked: false},
{id: '3-3-34', label: '黄埔区-34', checked: false},
{id: '3-3-35', label: '黄埔区-35', checked: false},
{id: '3-3-36', label: '黄埔区-36', checked: false},
]},
],
}]
}
},
methods: {
openTree: function() {
this.$refs.nextTreeAsyncRef.showTree = true
},
changeVerify: function(current, chooseList) {
// 注意:返回非空字符串会阻止原有行为,并提示返回的字符串
// 如果函数体不做return返回值即验证通过控件正常处理业务
console.log('当前变化的数据', current)
console.log('已选择的数据', chooseList)
if(chooseList && chooseList.length > 4) {
return '最多可以选择4个节点'
}
},
checkedFunc: function(id) {
if(this.activeId === id) {
this.activeId = '';
this.$refs.nextTreeRef.checkedFunc(id, false)
} else {
this.activeId = id;
this.$refs.nextTreeRef.checkedFunc(id)
}
},
function loadData(data) {
const type = data.$type; // 加载类型
const source = data.source // 源数据
// 同步实现的代码处理方式
if (type === 'nodeLoad') {
const nodeItem = source;
// 同步实现的代码处理方式 可以返回单个子节点的集合也可以返回子孙节点的集合
// 如果期望子集节点中还存在孙子节点可以打开,请在初始化数据的时候,初始化个空数组的子节点配置值{[this.childrenKey]: []}
// if(nodeItem && this.localData[nodeItem.id]) {
// return this.localData[nodeItem.id]
// } else {
// return []
// }
// 异步的代码实现方式 可以返回单个子节点的集合也可以返回子孙节点的集合
// 如果期望子集节点中还存在孙子节点可以打开,请在初始化数据的时候,初始化个空数组的子节点配置值{[this.childrenKey]: []}
return new Promise((resolve, reject) => {
setTimeout(() => {
if(nodeItem && self.localData[nodeItem.id]) {
return resolve(self.localData[nodeItem.id])
} else {
return resolve([])
}
}, 1000)
})
} else if(type === 'remoteSearch') { // searchModel=remote的时候会在loadData函数中返回type参数供做业务处理
// ...doing
}
},
getTitle: function(checked) {
return `已选:${checked.length}项`
},
echoDefault: function() {
const selectIds = ['2-1','3-3-35']
this.checkedTreeData(this.treeData, selectIds)
console.log('treeData的数据', this.treeData)
this.funcMode = 'checkbox'
this.$refs.nextTreeRef.showTree = true
},
itemclick: function(_multiple, _selectParent, _checkStrictly = false) {
this.funcMode = _multiple ? 'checkbox' : 'radio'
this.selectParent = _selectParent
this.checkStrictly = _checkStrictly
this.$refs.nextTreeRef.showTree = true
},
checkedTreeData: function(treeData, selectIds) {
// 注意 vue2当数据深嵌套时如果没有在treeData里面初始化checked属性那在改变数据的时候直接将checked属性赋值为true这时候ui界面有可能不会更新
// 这时候建议使用this.$set去更新checked属性值或者在初始化this.treeData的时候初始化checked属性
(treeData || []).map(item => {
if (selectIds.indexOf(item.id) !== -1) {
item.checked = true
} else {
item.checked = false
}
if (item.children && item.children.length) {
this.checkedTreeData(item.children, selectIds)
}
})
},
onconfirm: function(list) {
console.log('选中项的数量列表list', list)
},
oncancel: function() {
// 清除treeData的选中状态
this.checkedTreeData(this.treeData, [])
}
},
created() {
self = this
}
}
</script>
<style lang="scss">
.line-block {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
.img {
width: 40rpx;
height: 40rpx;
border-radius: 10rpx;
margin: 0 20rpx;
}
}
</style>
```
### 个性化自定义样式渲染
如果你的需求对样式需求比较高请使用插槽模式渲染本组件提供label插槽供你自定义定制
```js
<script>
// 提供参考一组自定义渲染数据demotreeData如下
const treeData = [
{id: '1', label: '北京', prev: 'PonderNext-', iconSrc: 'https://img95.699pic.com/xsj/03/fg/hj.jpg%21/fh/300', children: [
{id: '1-3-3-1', label: '北京区-1', prev: '前置-'},
{id: '1-3-3-2', label: '北京区-2', post: '-后置'},
{id: '1-3-3-3', label: '北京区-3', post: '-后置', prev: '前置-'},
{id: '1-3-3-4', label: '北京区-4'},
{id: '1-3-3-5', label: '北京区-5'},
{id: '1-3-3-6', label: '北京区-6'},
{id: '1-3-3-7', label: '北京区-7'},
{id: '1-3-3-8', label: '北京区-8'},
{id: '1-3-3-9', label: '北京区-9'},
{id: '1-3-3-10', label: '北京区-10'},
{id: '1-3-3-12', label: '北京区-11'},
{id: '1-3-3-13', label: '北京区-12'},
{id: '1-3-3-13', label: '北京区-13'},
{id: '1-3-3-14', label: '北京区-14'},
{id: '1-3-3-15', label: '北京区-15'},
{id: '1-3-3-16', label: '北京区-16'},
{id: '1-3-3-17', label: '北京区-17'},
{id: '1-3-3-18', label: '北京区-18'},
{id: '1-3-3-19', label: '北京区-19'},
{id: '1-3-3-20', label: '北京区-20'},
{id: '1-3-3-21', label: '北京区-21'},
{id: '1-3-3-22', label: '北京区-22'},
{id: '1-3-3-23', label: '北京区-23'},
{id: '1-3-3-24', label: '北京区-24'},
{id: '1-3-3-25', label: '北京区-25'},
{id: '1-3-3-26', label: '北京区-26'},
{id: '1-3-3-27', label: '北京区-27'},
{id: '1-3-3-28', label: '北京区-28'},
{id: '1-3-3-29', label: '北京区-29'},
{id: '1-1-3-3-30', label: '北京区-30'},
{id: '1-3-3-31', label: '北京区-31'},
{id: '1-3-3-32', label: '北京区-32'},
{id: '1-3-3-33', label: '北京区-33'},
{id: '1-3-3-34', label: '北京区-34'},
{id: '1-3-3-35', label: '北京区-35'},
{id: '1-3-3-36', label: '北京区-36'},
{id: '1-3-3-37', label: '北京区-37'},
{id: '1-3-3-38', label: '北京区-38'},
{id: '1-3-3-39', label: '北京区-39'},
{id: '1-3-3-40', label: '北京区-40'},
{id: '1-3-3-41', label: '北京区-41'},
{id: '1-3-3-42', label: '北京区-42'},
{id: '1-3-3-43', label: '北京区-43'},
{id: '1-3-3-44', label: '北京区-44'},
{id: '1-3-3-45', label: '北京区-45'},
{id: '1-3-3-46', label: '北京区-46'},
{id: '1-3-3-47', label: '北京区-47'},
{id: '1-3-3-48', label: '北京区-48'},
{id: '1-3-3-49', label: '北京区-49'},
{id: '1-3-3-50', label: '北京区-50'},
{id: '1-3-3-51', label: '北京区-51'},
{id: '1-3-3-52', label: '北京区-52'},
{id: '1-3-3-53', label: '北京区-53'},
{id: '1-3-3-54', label: '北京区-54'},
]},
{id: '2', label: '上海', prev: 'PonderNext-', iconSrc: 'https://img95.699pic.com/xsj/0g/hb/tc.jpg%21/fh/300', children: [
{id: '2-1', label: '上海-1', iconSrc: 'https://img1.baidu.com/it/u=1997340124,765201109&fm=253&fmt=auto&app=120&f=JPEG?w=285&h=285'},
{id: '2-2', label: '上海-2', iconSrc: 'https://img1.baidu.com/it/u=1997340124,765201109&fm=253&fmt=auto&app=120&f=JPEG?w=285&h=285'},
{id: '2-3', label: '上海-3', iconSrc: 'https://img1.baidu.com/it/u=1997340124,765201109&fm=253&fmt=auto&app=120&f=JPEG?w=285&h=285'},
] },
{id: '3', label: '广州', prev: 'PonderNext-', iconSrc: 'https://storage-public.zhaopin.cn/user/avatar/1589350028141684980/d00a1afa-e3ec-40a5-a68e-aef1f684b189.jpg', children: [
{id: '3-1', label: '海珠区', iconSrc: 'https://img95.699pic.com/xsj/0u/f3/5h.jpg%21/fh/300', children: [
{id: '3-1-1', label: '海珠区-1', disabled: true},
{id: '3-1-2', label: '海珠区-2', post: '-后置', prev: '前置-'},
{id: '3-1-4', label: '海珠区-3', post: '-后置',},
{id: '3-1-5', label: '海珠区-4', children: [
{ id: '3-1-5-1', label: '海珠区-4-200号'},
{ id: '3-1-5-2', label: '海珠区-4-201号', children: [
{ id: '3-1-5-1-1', label: '海珠区-4-200号-2'},
{ id: '3-1-5-2-1', label: '海珠区-4-201号-3'},
]},
]},
{id: '3-1-6', label: '海珠区-5'},
{id: '3-1-7', label: '海珠区-6'},
{id: '3-1-8', label: '海珠区-7', post: '-后置',},
{id: '3-1-9', label: '海珠区-8'},
{id: '3-1-10', label: '海珠区-9'},
{id: '3-1-11', label: '海珠区-10'},
{id: '3-1-1', label: '海珠区-11', disabled: true},
{id: '3-1-2', label: '海珠区-12'},
{id: '3-1-4', label: '海珠区-13'},
{id: '3-1-5', label: '海珠区-14'},
{id: '3-1-6', label: '海珠区-15'},
{id: '3-1-7', label: '海珠区-16'},
{id: '3-1-8', label: '海珠区-17'},
{id: '3-1-9', label: '海珠区-18'},
{id: '3-1-10', label: '海珠区-19', prev: '前置-'},
{id: '3-1-11', label: '海珠区-20'},
{id: '3-1-1', label: '海珠区-21', disabled: true},
{id: '3-1-2', label: '海珠区-22'},
{id: '3-1-4', label: '海珠区-23'},
{id: '3-1-5', label: '海珠区-24'},
{id: '3-1-6', label: '海珠区-25'},
{id: '3-1-7', label: '海珠区-26'},
{id: '3-1-8', label: '海珠区-27'},
{id: '3-1-9', label: '海珠区-28'},
{id: '3-1-10', label: '海珠区-29'},
{id: '3-1-11', label: '海珠区-30'},
{id: '3-1-1', label: '海珠区-31', disabled: true},
{id: '3-1-2', label: '海珠区-32'},
{id: '3-1-4', label: '海珠区-33'},
{id: '3-1-5', label: '海珠区-34'},
{id: '3-1-6', label: '海珠区-35'},
{id: '3-1-7', label: '海珠区-36'},
{id: '3-1-8', label: '海珠区-37'},
{id: '3-1-9', label: '海珠区-38'},
{id: '3-1-10', label: '海珠区-39'},
{id: '3-1-11', label: '海珠区-40'},
{id: '3-1-1', label: '海珠区-41', disabled: true},
{id: '3-1-2', label: '海珠区-42'},
{id: '3-1-4', label: '海珠区-43'},
{id: '3-1-5', label: '海珠区-44'},
{id: '3-1-6', label: '海珠区-45'},
{id: '3-1-7', label: '海珠区-46'},
{id: '3-1-8', label: '海珠区-47'},
{id: '3-1-9', label: '海珠区-48'},
{id: '3-1-10', label: '海珠区-49'},
{id: '3-1-11', label: '海珠区-50'},
{id: '3-1-11', label: '海珠区-51'},
]},
{id: '3-2', label: '番禺区', iconSrc: 'https://img1.baidu.com/it/u=931648192,3196263841&fm=253&fmt=auto&app=120&f=JPEG?w=285&h=285', disabled: true, checked: true, children: [
{id: '3-2-1', label: '番禺区-1'},
{id: '3-2-2', label: '番禺区-2'},
{id: '3-2-4', label: '番禺区-3'},
{id: '3-2-5', label: '番禺区-4'},
{id: '3-2-6', label: '番禺区-5'},
{id: '3-2-7', label: '番禺区-6'},
{id: '3-2-8', label: '番禺区-7'},
{id: '3-2-9', label: '番禺区-8'},
{id: '3-2-10', label: '番禺区-9'},
{id: '3-2-11', label: '番禺区-10'},
]},
{id: '3-3', label: '黄埔区', iconSrc: 'https://img.jiaoyubao.cn/43423/20210423113959473-20210423114005024.jpeg', children: [
{id: '3-3-1', label: '黄埔区-1'},
{id: '3-3-2', label: '黄埔区-2'},
{id: '3-3-3', label: '黄埔区-3'},
{id: '3-3-4', label: '黄埔区-4'},
{id: '3-3-5', label: '黄埔区-5'},
{id: '3-3-6', label: '黄埔区-6'},
{id: '3-3-7', label: '黄埔区-7'},
{id: '3-3-8', label: '黄埔区-8'},
{id: '3-3-9', label: '黄埔区-9'},
{id: '3-3-10', label: '黄埔区-10'},
{id: '3-3-12', label: '黄埔区-11'},
{id: '3-3-13', label: '黄埔区-12'},
{id: '3-3-13', label: '黄埔区-13'},
{id: '3-3-14', label: '黄埔区-14'},
{id: '3-3-15', label: '黄埔区-15'},
{id: '3-3-16', label: '黄埔区-16'},
{id: '3-3-17', label: '黄埔区-17'},
{id: '3-3-18', label: '黄埔区-18'},
{id: '3-3-19', label: '黄埔区-19'},
{id: '3-3-20', label: '黄埔区-20'},
{id: '3-3-21', label: '黄埔区-21'},
{id: '3-3-22', label: '黄埔区-22'},
{id: '3-3-23', label: '黄埔区-23'},
{id: '3-3-24', label: '黄埔区-24'},
{id: '3-3-25', label: '黄埔区-25'},
{id: '3-3-26', label: '黄埔区-26'},
{id: '3-3-27', label: '黄埔区-27'},
{id: '3-3-28', label: '黄埔区-28'},
{id: '3-3-29', label: '黄埔区-29'},
{id: '3-3-30', label: '黄埔区-30'},
{id: '3-3-31', label: '黄埔区-31'},
{id: '3-3-32', label: '黄埔区-32'},
{id: '3-3-33', label: '黄埔区-33'},
{id: '3-3-34', label: '黄埔区-34'},
{id: '3-3-35', label: '黄埔区-35'},
{id: '3-3-36', label: '黄埔区-36'},
{id: '3-3-37', label: '黄埔区-37'},
{id: '3-3-38', label: '黄埔区-38'},
{id: '3-3-39', label: '黄埔区-39'},
{id: '3-3-40', label: '黄埔区-40'},
{id: '3-3-41', label: '黄埔区-41'},
{id: '3-3-42', label: '黄埔区-42'},
{id: '3-3-43', label: '黄埔区-43'},
{id: '3-3-44', label: '黄埔区-44'},
{id: '3-3-45', label: '黄埔区-45'},
{id: '3-3-46', label: '黄埔区-46'},
{id: '3-3-47', label: '黄埔区-47'},
{id: '3-3-48', label: '黄埔区-48'},
{id: '3-3-49', label: '黄埔区-49'},
{id: '3-3-50', label: '黄埔区-50'},
{id: '3-3-51', label: '黄埔区-51'},
{id: '3-3-52', label: '黄埔区-52'},
{id: '3-3-53', label: '黄埔区-53'},
{id: '3-3-54', label: '黄埔区-54'},
]},
],
}]
</script>
```
### 预览
###
***
| 功能预览 | 父子级关联演示 | 全面支持大数据量子孙节点ui按需渲染(按需渲染数据) |
| :------------------------------------------------------------------: | :------------------------------------------------------------------: | :------------------------------------------------------------------: |
| ![](https://lixueshiaa.github.io/webtest/www/static/next-tree.gif) | ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-b.gif) | ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-d.gif) |
| 增强控件交互能力增加筛选search模式全面支持大数据量交互 | 超强的样式定制能力,满足你高精美组件的需求 | 打开精美的辅助线模式,让你的控件更加友好 |
| :------------------------------------------------------------------: | :------------------------------------------------------------------: | :------------------------------------------------------------------: |
| ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-e.gif) | ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-f.gif) | ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-u.gif) |
| 增加搜索模式searchModel=depHighlight模式从属高亮显示模式 | 支持异步加载子节点子树集ajax远程加载数据等 | 支持不同主题的切换ui定制更简单 |
| :------------------------------------------------------------------: | :------------------------------------------------------------------: | :------------------------------------------------------------------: |
| ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-p.gif) | ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-k.gif) | ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-n.gif) |
| 增加验证函数和topBar插槽使得更加容易和组件进行交互 | 增加页面模式支持整页ui展示模式 | 增加展开模式expandedMode配置支持单链路展开理论上支持几万数据量 |
| :------------------------------------------------------------------: | :------------------------------------------------------------------: | :------------------------------------------------------------------: |
| ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-cc.gif)| ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-uu.gif)| ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-aab.gif) |
### 超集功能预览(增值功能)
###
| 实现tree的功能模式扩展让你的tree组件实现可编辑态 |
| :--------------------------------------------------------------------: |
| ![](https://lixueshiaa.github.io/webtest/www/static/next-tree-eeee.gif)|
## 参数
可选参数属性列表
|参数名 |说明 |类型 |是否必填 |默认值 |可选值 |
|---- |---- |---- |---- |---- |----------------------- |
|uiMode |ui表现方式popup<弹窗> page<页面>;默认是 popup |String |是 |popup |page |
|funcMode |功能模式配置display<展示模式> edit<编辑模式>checkbox<多选模式> radio<单选模式>;默认是 radio |String |是 |radio |dispaly,edit,checkbox |
|treeData |树源数据列表 |Array |是 |[] |- |
|valueKey |绑定value的键属性(项的唯一key标识) |String |否 |id |- |
|labelKey |用于显示的字段 |String |否 |label |- |
|disabledKey |禁用节点绑定属性 |String |否 |disabled |- |
|childrenKey |子节点绑定属性 (注意当item[childrenKey]的值设为null时代表是无下级数据的父节点即非叶子节点) |String |否 |children |- |
|title | 弹出标题(如果是函数时会返回所选项的值作为回调参数如title: (checked):String => {}) |String, Function |否 |'' |- |
|selectParent |作用于funcMode=display模式下是否可以选父级 |Boolean |否 |false |true |
|foldAll| 折叠时关闭所有已经打开的子集,再次打开时需要一级一级打开 |Boolean |否 |false |true |
|themeColor |主题颜色 |String |否 |#f9ae3d |- |
|cancelColor |取消按钮颜色 |String |否 |#757575 |- |
|titleColor |标题颜色 |String |否 |#757575 |- |
|border |是否有分割线 |Boolean |否 |false |true |
|checkStrictly|作用于funcMode=checkbox模式下 状态下节点选择完全受控(父子节点选中状态不再关联) |Boolean |否 |false |true |
|checkStrictlyModel|作用于funcMode=checkbox模式下父子节点关联模式strong:强关联不再受限节点的disabled控制weak弱关联节点关联受disabled控制 |String |是 |weak |strong |
|showHalfCheckedTips|作用于funcMode=checkbox模式下 checkStrictly为false的状态下生效父子节点选中状态不再关联是否展示半选提示 |Boolean |否 |false |true |
|ifSearch| 筛选search模式 |Boolean |否 |true |false |
|searchModel| 搜索模式配置 depHighlight: 从属高亮显示层级并高亮显示common: 一般remote: 远程 |String |否 |common |depHighlight |
|showAuxiliaryLine| 是否打开辅助线 |Boolean |否 |false |true |
|loadData| 异步加载函数 (node):Promise([childData]) => {} // demo有说明 |Function |否 |- |- |
|height| 只在uiMode=popup时生效弹层容器的高度默认是500 |Number |否 |500 |- |
|changeVerify|作用于funcMode=display模式下 验证函数 (current as any, chooseList as any []):String => {} // 验证函数会把当前控件的选择值作为参数返给函数体demo有说明 |Function |否 |- |- |
|expandedKeys| (Controlled) Specifies the keys of the expanded treeNodes 展开配置项,格式为[valueKey] |Array |否 |[] |- |
|expandedMode| 展开模式配置: common: 一般模式singe: 单一模式; |String |否 |common |singe |
# Event 事件
|事件名 |说明 |类型 |回调参数 |
|---- |---- |---- |---- |
|confirm|菜单收起时返回的筛选结果 |emit |array |
|clear|点击清除按钮时触发 |emit |- |
|cancel|关闭弹层和点击取消时触发 |emit |- |
|change|选项改变时触发 |emit |array |
## Slot 插槽
|名称 |说明 |参数 |
|---- |---- |---- |
|label |label插槽 |data(当前项对于treeData里面的数据) |
|topBar |topBar插槽 |----滚动区域顶部topBar插槽 |
|bottomBar |bottomBar插槽 |----滚动区域底部bottomBar插槽 |
|fixedBottomBar |fixedBottomBar插槽 |----固定在页面的底部使用fixed进行定位 |
|empty |empty插槽 |----数据为空的插槽 |

View File

@ -1,5 +1,5 @@
// let requestPath = 'http://192.168.0.31:8992/qa-prevention-xgf/'; // 后台请求地址
let requestPath = 'https://skqhdg.porthebei.com:9006/qa-prevention-xgf/'; // 后台请求地址
let requestPath = 'http://192.168.0.99:8199/'; // 后台请求地址
// let requestPath = 'https://skqhdg.porthebei.com:9006/qa-prevention-xgf/'; // 后台请求地址
// let requestPath = 'https://qgxgf.qhdsafety.com/qa-prevention-xgf/'; // 外网地址
import store from '../store/index'
@ -19,16 +19,16 @@ function post(url, data) {
},
method: 'POST',
header: {
'Content-type': 'application/x-www-form-urlencoded'
'Content-type': data?.postMethod || 'application/x-www-form-urlencoded'
},
success: (res) => {
if (res.statusCode != 200){
uni.showToast({
title: '网络错误请重试,' +res.statusCode,
title: '网络错误请重试',
icon: 'error',
duration: 2000
});
reject(err)
reject(res)
}
if (data && data.loading !== false) {
uni.hideLoading();

View File

@ -0,0 +1,76 @@
import {getCurrentNextOperation, setTaskSave} from "../api/index";
// 处理表单数据
const processFormData = (formData, formItems) => {
const form = []
for (let i = 0; i < formItems.length; i++) {
const formItem = formItems[i]
form.push({
ITEM: formItem.name,
ITEM_NAME: formItem.key_name,
ITEM_VALUE: formData[formItem.key_name],
FK_NAME: formItem.key_id || '',
FK_VALUE: formData[formItem.key_id] || '',
TYPE: formItem.type,
SORT: i + 1
})
}
return form
}
// 提交表单基础信息
export const setSubmitForm = async ({form, formItems, TYPE, CORP_ID}) => {
const {taskIds} = await setTaskSave({
data: [{form: processFormData(form, formItems)}],
TYPE,
postMethod: 'application/json',
})
await resolveNextOperation(taskIds[0], CORP_ID, TYPE)
}
// 处理选择人员数据
const processingSelectedPersonnelData = (formData, list) => {
const form = []
for (let i = 0; i < list.length; i++) {
const item = list[i]
form.push({
TYPE_NAME: item.desc,
TYPE: item.code,
DEPARTMENT_ID: list[i].type === '1' ? formData[item.key_id] : '',
DEPARTMENT_NAME: list[i].type === '1' ? formData[item.key_name] : '',
USER_ID: list[i].type === '0' ? formData[item.key_id] : '',
USER_NAME: list[i].type === '0' ? formData[item.key_name] : '',
isDepartment: list[i].type
})
}
return form
}
// 提交人员信息
export const setPersonnelForm = async ({form, list, taskId, CORP_ID, TYPE}) => {
await setTaskSave({
data: [{jobs: processingSelectedPersonnelData(form, list), task: {EW_RU_TASK_ID: taskId}}],
postMethod: 'application/json',
})
await resolveNextOperation(taskId, CORP_ID, TYPE)
}
// 决定下一步操作 EW_RU_TASK_ID当前任务id CORP_ID 选择的企业id TYPE作业类型
const resolveNextOperation = async (EW_RU_TASK_ID, CORP_ID, TYPE) => {
const {info} = await getCurrentNextOperation({EW_RU_TASK_ID})
// 选人
if (info.chooseNextFlag === '1') {
uni.navigateTo({
url: '/pages/eight_assignments/select_review_personnel',
success: ({eventChannel}) => {
eventChannel.emit('nextNodes', {nextNodes: info.nextNodes, taskId: EW_RU_TASK_ID, CORP_ID, TYPE})
}
})
return
}
// 填写安全措施
if (info.completeFlag === '1') {
return
}
// 填写其它安全措施
if (info.canAddFlag === '1') {
return
}
console.log('没有下一步了')
}