소스 검색

科目选择弹出层组件

wulanhaote
zhao 2 년 전
부모
커밋
0f3453de21
2개의 변경된 파일256개의 추가작업 그리고 0개의 파일을 삭제
  1. +188
    -0
      src/components/form/SubjectTreeChooser.vue
  2. +68
    -0
      src/components/form/SubjectTreeChooserNodeItem.vue

+ 188
- 0
src/components/form/SubjectTreeChooser.vue 파일 보기

@@ -0,0 +1,188 @@
<!-- 级联树选择器表单组件 zhao -->
<template>
<van-popup v-model="popupVisible" position="bottom" :style="{'height': height || 'unset',}">
<van-search
v-model="searchValue"
placeholder="按科目编码/名称筛选"
@input="onSearch"
/>

<van-tabs v-model="active" @change="onTabChanged">
<van-tab :title="item.subjectName" :name="item.subjectId" v-for="(item, index) in subjects">
<SubjectTreeChooserNodeItem :ref="'tree' + index" :subjects="item.children" @clicked="onItemClicked" :can-select-non-leaf="canSelectNonLeaf"></SubjectTreeChooserNodeItem>
</van-tab>
</van-tabs>
</van-popup>
</template>

<script>
import request from "@/utils/request";
import SubjectTreeChooserNodeItem from "./SubjectTreeChooserNodeItem";

export default {
name: "SubjectTreeChooser",
components: {SubjectTreeChooserNodeItem},
props: [
'value', 'visible', 'height', 'canSelectNonLeaf',
],
watch: {
value: function (newVal, oldVal) {
if(newVal != this.internalValue)
{
this.internalValue = newVal;
this.syncIndex();
}
},
visible: function(newVal, oldVal) {
if(this.popupVisible !== newVal)
{
this.popupVisible = newVal;
if(newVal)
this.syncIndex();
}
},
popupVisible: function(newVal, oldVal) {
if(newVal !== this.visible)
this.$emit('update:visible', newVal);
},
},
created() {
this.getSubjects();
},
data() {
return {
popupVisible: false,
internalValue: this.value,
searchValue: '',
active: '1',
subjects: [],
};
},
methods: {
getSubjects() {
this.subjects = [];
let map = {};
this.getDicts('subject_type').then((resp) => {
this.subjects = resp.data.map((x) => {
let item = {
subjectId: x.dictValue,
subjectName: x.dictLabel,
subjectNameAll: x.dictLabel,
subjectType: x.dictValue,
subjectLevel: 0,
children: [],
visible: true,
};
map[x.dictValue] = item;
return item;
});
let url = '/finance/subject/listAll'; // '/villageAffairs/public/subjects/153'
request(url).then((resp) => {
let list = this.makeTree(resp.rows || resp.data);
for(let v of list)
{
if(v.subjectId.length === 3)
{
map[v.subjectType].children.push(v);
}
}
})
});
},
onItemClicked(subject) {
if(this.canSelectNonLeaf || subject.is_last === 'Y')
{
this.internalValue = subject.subjectId
this.$emit('input', subject.subjectId);
this.$emit('select', subject);
this.close();
}
},
onItemToggle({subject, on}) {
},
onCancel() {
this.close();
},
makeTree(list) {
function isnull(p) {
return p === null || p === undefined || p === '';
}
function makeTree_r(l, p) {
const isRoot = isnull(p);
let res = [];
for(let v of l)
{
if((isRoot && isnull(v.parentId)) || (!isRoot && v.parentId == p))
{
let arr = makeTree_r(l, v.subjectId);
if(arr.length > 0)
v.children = arr;
else
delete v.children;
res.push(v);
}
}
return res;
}
return makeTree_r(list.map((x) => {
x.visible = true;
return x;
}));
},
onSearch(value) {
function handleTree_r(l, func) {
let res = 0;
for(let v of l)
{
let r = func(v) ? 1 : 0;
if(v.children && Array.isArray(v.children) && v.children.length > 0)
{
r += handleTree_r(v.children, func);
}
v.visible = r > 0;
res += r;
}
return res;
}

for(let v of this.subjects)
{
if(v.subjectId === this.active && value)
{
handleTree_r(v.children, (x) => x.subjectId.startsWith(value) || x.subjectName.indexOf(value) !== -1);
}
else
{
handleTree_r(v.children, (x) => true);
}
}
},
onTabChanged() {
this.searchValue = '';
this.onSearch();
},
folderAll() { // TODO: not work
for(let i in this.subjects)
{
if(this.$refs['tree' + i])
this.$refs['tree' + i][0].folderAll();
}
},
close() {
this.popupVisible = false;
this.folderAll();
this.searchValue = '';
this.active = '1';
this.$emit('cancel');
},
syncIndex() {
if(this.subjects.length === 0 || !this.internalValue)
return;
this.active = this.internalValue[0];
},
},
}
</script>

<style scoped>
</style>

+ 68
- 0
src/components/form/SubjectTreeChooserNodeItem.vue 파일 보기

@@ -0,0 +1,68 @@
<!-- 级联树选择器表单组件 zhao -->
<template>
<van-collapse v-model="active">
<template v-for="(subject, index) in subjects">
<van-collapse-item :ref="'collapse' + index" :lazy-render="false" :title="subject.subjectId + ' ' + subject.subjectName" :name="subject.subjectId" :is-link="subject.is_last !== 'Y'" :class="subject.is_last === 'Y' ? 'subject-tree-node-leaf' : 'subject-tree-node-non-leaf'" v-if="subject.visible">
<template #title>
<div @click="($event) => onItemClicked($event, subject)">{{ subject.subjectId }} {{ subject.subjectName }}</div>
</template>
<SubjectTreeChooserNodeItem :ref="'childCollapse' + index" :subjects="subject.children" v-if="subject.children && Array.isArray(subject.children) && subject.children.length > 0" @clicked="onChildItemClicked" :can-select-non-leaf="canSelectNonLeaf">
</SubjectTreeChooserNodeItem>
</van-collapse-item>
</template>
</van-collapse>
</template>

<script>

export default {
name: "SubjectTreeChooserNodeItem",
props: [
'subjects', 'canSelectNonLeaf',
],
watch: {
},
created() {
},
data() {
return {
active: [],
};
},
methods: {
onItemClicked($event, subject) {
if(this.canSelectNonLeaf || subject.is_last === 'Y')
{
this.$emit('clicked', subject);
//$event.preventDefault();
$event.stopPropagation();
}
},
onChildItemClicked(subject) {
this.$emit('clicked', subject);
},
folderAll() { // TODO: not work
for(let i in this.subjects)
{
if(this.$refs['childCollapse' + i])
this.$refs['childCollapse' + i][0].folderAll();
if(this.$refs['collapse' + i])
this.$refs['collapse' + i][0].toggle(false);
}
},
},
}
</script>

<style>
.subject-tree-node-non-leaf .van-collapse-item__content {
padding-right: 0;
padding-top: 0;
padding-bottom: 0;
}
.subject-tree-node-leaf .van-collapse-item__content {
padding-right: 0;
padding-top: 0;
padding-bottom: 0;
}
</style>

불러오는 중...
취소
저장