Files
2025-07-07 16:05:18 +08:00

398 lines
11 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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

<template>
<NavBar />
<view class="container">
<view class="title">
<PageTitle :title="$t('ib.fundSetting')" />
</view>
<template v-if="!loading && allJunior">
<view style="height: 56upx; margin-bottom: 20upx" v-if="allJunior && allJunior.power == 'children'">
{{ $t('fundSetting.childrenMaxHierarchy') }}
<text style="font-size: 36upx">{{ selectedRow.hierarchy_value }}</text>
</view>
<view style="height: 80upx; margin-bottom: 20upx; position: relative" v-if="allJunior && allJunior.power == 'all'">
<view class="searchWrapper">
<uni-data-select :clear="false" :localdata="searchTypeOptions" v-model="searchType"></uni-data-select>
<uni-easyinput primaryColor="#29BBE4" v-model="searchValue" />
<button class="primaryButton searchBtn" @click="query">{{ $t('form.search') }}</button>
</view>
</view>
</template>
</view>
<uni-popup ref="resultDialog" :isMaskClick="false">
<view style="width: 600upx">
<view class="tableSection">
<uni-table :emptyText="$t('common.noData')" @click="hideSearchDialog">
<uni-tr v-for="row in searchResult" :key="row.rowKey ?? row.id" @click="handleRow(row)">
<uni-td class="columnItem">
<view style="width: 100%">
<view>{{ row?.['text'] ?? '-' }}</view>
</view>
</uni-td>
</uni-tr>
</uni-table>
</view>
</view>
</uni-popup>
<view>
<template v-if="!loading">
<view v-if="allJunior" style="width: 100%; padding: 0 20upx; box-sizing: border-box">
<scroll-view :style="{ height: contentHeight }" scroll-y scroll-x scroll-with-animation="true" @scroll="handleScroll" :scroll-top="scrollTop">
<BaseTree ref="tree" class="mtl-tree" treeLine v-model="treeNodes">
<template #default="{ node, stat }">
<image
src="@/static/partner/collapse.png"
mode="aspectFill"
class="tree-node-icon"
v-if="stat.open && stat.children.length"
@click.native="stat.open = false"
></image>
<image
src="@/static/partner/unfold.png"
mode="aspectFill"
class="tree-node-icon"
v-else-if="!stat.open && stat.children.length"
@click.native="stat.open = true"
></image>
<view class="tree-node" :id="'refN' + node.id">
<text class="level">{{ stat.level }}</text>
<text class="label">{{ node.text }}</text>
<uni-easyinput
type="digit"
inputmode="decimal"
:readonly="node.readonly"
:disabled="node.readonly"
:clearable="false"
:primaryColor="(stat.level == 1 ? selectedRow.hierarchy_value : stat.parent.data.val) < node.val ? 'red' : '#29BBE4'"
style="min-width: 100upx; margin-left: 10upx; flex-grow: 0"
:class="{ 't-input-error': (stat.level == 1 ? selectedRow.hierarchy_value : stat.parent.data.val) < node.val && !node.readonly }"
v-model="node.val"
/>
<text class="diff" :class="{ 'error-diff': (stat.parent.data.val ? stat.parent.data.val : 0) < node.val }" v-if="stat.level != 1">
{{ $t('partner.difference', { n: (stat.parent.data.val ? stat.parent.data.val : 0) - (node.val ? node.val : 0) }) }}
</text>
</view>
</template>
</BaseTree>
</scroll-view>
<view>
<!-- 保存和返回 -->
<button class="primaryButton" style="margin-top: 20upx" :disabled="saveLoading" @click="save">
<image v-show="saveLoading" src="/static/loadingCircle.svg" mode="aspectFit" style="width: 16px; height: 16px"></image>
{{ $t('form.save') }}
</button>
</view>
</view>
</template>
<Spin v-show="loading" />
</view>
</template>
<script>
import { useUserStore } from '@/stores/user';
import { getAllJunior, saveRebateSet } from '@/services/partner/myClient.ts';
import BaseTree, { walkTreeData } from '@/pages/components/baseTree/baseTree.vue';
import '@/pages/components/baseTree/style/default.css';
import '@/pages/components/baseTree/style/material-design.css';
export default {
components: { BaseTree },
data() {
return {
scrollTop: 0,
curScrollTop: 0,
contentHeight: 'auto',
loading: true,
saveLoading: false,
searchTypeOptions: [
{ text: this.$t('fundSetting.account'), value: 'n' },
{ text: this.$t('fundSetting.value'), value: 'v' }
],
searchType: 'n',
searchValue: null,
searchResult: null,
allJunior: null,
bigAgentId: null,
selectedRow: null,
treeNodes: []
};
},
methods: {
async loadData(currentRow) {
this.loading = true;
const resp = await getAllJunior({ rebate_id: currentRow.id });
this.loading = false;
if (resp.code == 0) {
this.allJunior = resp.data;
if (resp.data.power === 'all') {
this.loadTree(currentRow);
} else if (resp.data.power === 'children') {
this.loadChildren(currentRow);
}
}
},
/**
* 加载所有下级
*/
loadTree(currentRow) {
const { tree, listAll, listVal } = this.allJunior;
let valueMap = new Map();
if (listVal && listVal.length) {
for (let i = 0; i < listVal.length; i++) {
let val = listVal[i].hierarchy_value;
let if_fixed = listVal[i].if_fixed;
if (val == null || val == '' || isNaN(val)) {
val = 0;
}
valueMap.set(listVal[i].user_id, { val: val, if_fixed: if_fixed });
}
}
let node0 = [];
if (tree && tree.length) {
this.bigAgentId = listAll[0].id;
node0.push({
level: 0,
levelNum: listAll[0].level,
id: listAll[0].id,
text: listAll[0].user_code + '(' + listAll[0].id + ')',
// 大代理的值时默认的,不允许修改
readonly: true,
pid: 0,
val: currentRow.hierarchy_value
});
}
node0[0].children = this.getTree(tree, valueMap, 0);
this.treeNodes = node0;
valueMap.clear();
},
/**
* 加载直属下级
*/
loadChildren(currentRow) {
const { listAll, noChangeUserMap } = this.allJunior;
let nodes = [];
for (let i = 0; i < listAll.length; i++) {
let readonly = false;
if (noChangeUserMap != null && !this.isEmpty(noChangeUserMap[listAll[i].id])) {
readonly = true;
}
let item = listAll[i];
nodes.push({
level: 0,
readonly: readonly,
id: item.id,
text: item.user_code + '(' + item.id + ')',
val: this.returnFloat(item.hierarchy_value),
children: []
});
}
this.treeNodes = nodes;
},
getTree(tree, valueMap, level) {
if (!tree) {
return [];
}
let nodes = [];
const { noChangeUserMap } = this.allJunior;
for (let i = 0; i < tree.length; i++) {
let readonly = false;
if (noChangeUserMap != null && !this.isEmpty(noChangeUserMap[tree[i].id])) {
readonly = true;
}
let val = 0;
let if_fixed = 0;
if (valueMap && valueMap.get(tree[i].id)) {
val = valueMap.get(tree[i].id).val;
if_fixed = valueMap.get(tree[i].id).if_fixed;
}
nodes.push({
readonly: readonly,
levelNum: tree[i].level,
id: tree[i].id,
text: tree[i].user_code + '(' + tree[i].id + ')',
val: val,
if_fixed: if_fixed,
level: level + 1,
children: this.getTree(tree[i].child, valueMap, level + 1)
});
}
return nodes;
},
getData(nodes, result, maxValue) {
if (nodes && nodes.length) {
for (var j = 0; j < nodes.length; j++) {
let i = nodes[j];
if (!i.readonly) {
result.push({
user_id: i.id,
hierarchy_value: i.val
});
if (maxValue < i.val) {
return false;
}
}
if (i.children && i.children.length) {
if (!this.getData(i.children, result, i.val)) {
return false;
}
}
}
}
return true;
},
async save() {
let data = {
rebate_id: this.selectedRow.id
};
let tmp = [];
if (!this.getData(this.treeNodes, tmp, this.selectedRow.hierarchy_value)) {
return;
}
data.json = JSON.stringify(tmp);
this.saveLoading = true;
const resp = await saveRebateSet(data);
this.saveLoading = false;
if (resp.code == 0) {
this.$cusModal.showModal({
type: 'message',
status: 'success',
contentText: this.$t('common.success.action')
});
} else {
this.$cusModal.showModal({
type: 'message',
status: 'warning',
contentText: resp.msg ?? this.$t('common.error.sysError')
});
}
},
isEmpty(str) {
if (typeof value === 'number' && !isNaN(str)) str = str + '';
if (str == 'undefined' || str == 'null' || str == null || str == '' || str == undefined) {
return true;
} else {
return false;
}
},
returnFloat(value) {
if (this.isEmpty(value)) return '0.00';
var value = Math.round(parseFloat(value) * 100) / 100;
var s = value.toString().split('.');
if (s.length == 1) {
value = value.toString() + '.00';
return value;
}
if (s.length > 1) {
if (s[1].length < 2) {
value = value.toString() + '0';
}
return value;
}
},
/**
* searchType n=按名字v=按值
*/
query() {
this.searchResult = null;
let str = this.searchValue;
if (this.isEmpty(str)) {
this.searchResult = null;
} else {
let tmp = [];
walkTreeData(
this.treeNodes,
(node, index, parent) => {
if (this.searchType == 'n') {
if (node.text.indexOf(str) >= 0) {
tmp.push(node);
}
} else if (this.searchType == 'v') {
str = parseFloat(str);
let ibvalue = node.val;
if (this.isEmpty(ibvalue)) {
ibvalue = 0;
} else {
ibvalue = parseFloat(ibvalue);
}
if (ibvalue == str) {
tmp.push(node);
}
}
},
{
childrenKey: 'children',
reverse: false,
childFirst: false
}
);
this.searchResult = tmp;
this.$refs.resultDialog.open();
}
},
handleRow(rowData) {
this.closeSearchDialog();
this.$refs.tree.openNodeAndParents(rowData);
const query = uni.createSelectorQuery();
query.select('#refN' + rowData.id).boundingClientRect();
query.select('.container').boundingClientRect();
query.exec((res) => {
this.scrollTop = this.curScrollTop + res[0].top - res[1].height - res[1].top;
});
},
hideSearchDialog() {
if (!this.searchResult || !this.searchResult.length) {
this.closeSearchDialog()
}
},
closeSearchDialog() {
this.$refs.resultDialog.close();
},
handleScroll(e) {
this.curScrollTop = e.detail.scrollTop;
}
},
created() {
const userStore = useUserStore();
this.selectedRow = userStore.currentRow;
this.loadData(this.selectedRow);
},
mounted() {
this.$nextTick(() => {
const query = uni.createSelectorQuery().in(this);
query
.select('.container')
.boundingClientRect((data) => {
if (data) {
this.contentHeight = `calc(100vh - ${data.height + 100}px - 200upx)`;
}
})
.exec();
});
}
};
</script>
<style lang="scss" scoped>
@import './tree.scss';
</style>
<style lang="scss">
.tree-node {
.uni-easyinput__content-input {
height: 50upx !important;
}
}
.t-input-error {
border: 1px solid red;
}
.diff {
padding-left: 16upx;
flex-shrink: 0;
}
.error-diff {
color: red;
}
</style>