release/2.19.1.2501.01
This commit is contained in:
parent
eecb7f34f2
commit
ecf34e4886
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* 核算编辑
|
||||||
|
* 数据查看锚点
|
||||||
|
* @Author: 黎永顺
|
||||||
|
* @Date: 2025/2/10
|
||||||
|
* @Wechat:
|
||||||
|
* @Email: 971387674@qq.com
|
||||||
|
* @description:
|
||||||
|
*/
|
||||||
|
import React, { Component } from "react";
|
||||||
|
import { WeaLocaleProvider } from "ecCom";
|
||||||
|
import classnames from "classnames";
|
||||||
|
|
||||||
|
const getLabel = WeaLocaleProvider.getLabel;
|
||||||
|
|
||||||
|
class CalcAnchorList extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
collapsed: false, currentIndex: 0
|
||||||
|
};
|
||||||
|
this.isClickRef = null;
|
||||||
|
this.timerRef = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
document.getElementById("salary_anchor_area").addEventListener("scroll", this.handlerScroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(nextProps, nextContext) {
|
||||||
|
if (nextProps.visible !== this.props.visible && !nextProps.visible) this.setState({
|
||||||
|
collapsed: false,
|
||||||
|
currentIndex: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
document.getElementById("salary_anchor_area").removeEventListener("scroll", this.handlerScroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
handlerScroll = () => {
|
||||||
|
// 点击锚点时,不执行滚动函数
|
||||||
|
if (this.isClickRef) return;
|
||||||
|
// 获取滚动容器的滚动高度(这里相对于#salary_anchor_area滚动的)
|
||||||
|
const scrollTop = document.getElementById("salary_anchor_area").scrollTop;
|
||||||
|
// 获取所有wea-search-group anchor_开头的元素集合
|
||||||
|
const contentList = document.querySelectorAll("[class^='wea-search-group anchor_']");
|
||||||
|
const offsetTopArr = [];
|
||||||
|
contentList.forEach((item) => {
|
||||||
|
// 获取每个wea-search-group anchor_开头的元素的offsetTop
|
||||||
|
offsetTopArr.push(item.offsetTop);
|
||||||
|
});
|
||||||
|
for (let i = 0; i < offsetTopArr.length; i++) {
|
||||||
|
// 当滚动条高度达到对应wea-search-group anchor_开头的元素的滚动高度、则将锚点设置为高亮状态
|
||||||
|
if (scrollTop + 190 >= offsetTopArr[i]) this.setState({ currentIndex: i });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
onClickAnchor = (item, index) => {
|
||||||
|
const anchorElement = document.getElementById("salary_anchor_area");
|
||||||
|
const el = document.querySelector(`.anchor_${item.salarySobItemGroupId}`);
|
||||||
|
if (el) {
|
||||||
|
anchorElement.scroll({ top: el.offsetTop, behavior: "smooth" });
|
||||||
|
}
|
||||||
|
this.setState({ currentIndex: index });
|
||||||
|
// 点击时设置为true,为了防止同时执行滚动事件
|
||||||
|
this.isClickRef = true;
|
||||||
|
// 清除定时器,防止滚动事件触发、出现走马灯闪烁问题
|
||||||
|
if (this.timerRef) clearTimeout(this.timerRef);
|
||||||
|
this.timerRef = setTimeout(() => {
|
||||||
|
this.isClickRef = false;
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { collapsed, currentIndex } = this.state, { datas } = this.props;
|
||||||
|
return (
|
||||||
|
<div id="anchorList-contianer" style={{ position: "sticky", top: 8, zIndex: 10086 }}>
|
||||||
|
<div className={classnames("anchor-list-wrapper", { "anchor-list-collapsed": collapsed })}>
|
||||||
|
{
|
||||||
|
collapsed ?
|
||||||
|
<div className="anchor-list-collapsed-btn">
|
||||||
|
<i className="icon-coms02-Initialize-template"
|
||||||
|
onClick={() => this.setState({ collapsed: !collapsed })}/>
|
||||||
|
</div> :
|
||||||
|
<React.Fragment>
|
||||||
|
<div className="anchor-list-header">
|
||||||
|
<i className="icon-coms-right" onClick={() => this.setState({ collapsed: !collapsed })}/>
|
||||||
|
</div>
|
||||||
|
<div className="anchor-list">
|
||||||
|
<div className="anchor-list-ink">
|
||||||
|
<span className="anchor-list-ink-ball visible"
|
||||||
|
style={{ top: `${2.5 + currentIndex * 27.7}px`, height: 23 }}/>
|
||||||
|
</div>
|
||||||
|
{_.map(datas, (o, i) => (
|
||||||
|
<div className={classnames("anchor-list-link", { "anchor-list-link-active": currentIndex === i })}
|
||||||
|
onClick={() => this.onClickAnchor(o, i)}>
|
||||||
|
<span
|
||||||
|
className={classnames("anchor-list-link-title", { "anchor-list-link-title-active": currentIndex === i })}>{o.salarySobItemGroupName}</span>
|
||||||
|
</div>)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CalcAnchorList;
|
||||||
|
|
@ -30,7 +30,7 @@ class EditCalcTable extends Component {
|
||||||
this.state = {
|
this.state = {
|
||||||
loading: false, pageInfo: { current: 1, pageSize: 10, total: 0 },
|
loading: false, pageInfo: { current: 1, pageSize: 10, total: 0 },
|
||||||
selectedRowKeys: [], progressVisible: false, progress: 0,
|
selectedRowKeys: [], progressVisible: false, progress: 0,
|
||||||
salaryCalcSlide: { visible: false, id: "" }, originPayloadData: {},
|
salaryCalcSlide: { visible: false, id: "", viewAttr: 2 }, originPayloadData: {},
|
||||||
batchUpdateDialog: {
|
batchUpdateDialog: {
|
||||||
visible: false, salaryAcctRecordId: "", idList: [], salaryItemId: "",
|
visible: false, salaryAcctRecordId: "", idList: [], salaryItemId: "",
|
||||||
conditions: [], pattern: 0, dataType: ""
|
conditions: [], pattern: 0, dataType: ""
|
||||||
|
|
@ -73,9 +73,9 @@ class EditCalcTable extends Component {
|
||||||
this.updateEmpLockStatus({ ...params });
|
this.updateEmpLockStatus({ ...params });
|
||||||
break;
|
break;
|
||||||
case "EDIT":
|
case "EDIT":
|
||||||
const { id: salaryCalcId } = params;
|
const { id: salaryCalcId, showSee } = params;
|
||||||
this.setState({
|
this.setState({
|
||||||
salaryCalcSlide: { visible: true, id: salaryCalcId }
|
salaryCalcSlide: { visible: true, id: salaryCalcId, viewAttr: showSee ? 1 : 2 }
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "DIAGRAM":
|
case "DIAGRAM":
|
||||||
|
|
@ -238,7 +238,7 @@ class EditCalcTable extends Component {
|
||||||
"总计": getLabel(523, "总计"), "批量解锁": getLabel(111, "批量解锁"),
|
"总计": getLabel(523, "总计"), "批量解锁": getLabel(111, "批量解锁"),
|
||||||
"批量锁定": getLabel(111, "批量锁定"), "批量更新": getLabel(111, "批量更新"),
|
"批量锁定": getLabel(111, "批量锁定"), "批量更新": getLabel(111, "批量更新"),
|
||||||
"查看拓扑图": getLabel(111, "查看拓扑图"), "锁定": getLabel(111, "锁定"),
|
"查看拓扑图": getLabel(111, "查看拓扑图"), "锁定": getLabel(111, "锁定"),
|
||||||
"解锁": getLabel(111, "解锁")
|
"解锁": getLabel(111, "解锁"), "查看": getLabel(111, "查看")
|
||||||
};
|
};
|
||||||
this.setState({ originPayloadData: { ...payload, i18n } });
|
this.setState({ originPayloadData: { ...payload, i18n } });
|
||||||
const childFrameObj = document.getElementById("atdTable");
|
const childFrameObj = document.getElementById("atdTable");
|
||||||
|
|
@ -269,7 +269,7 @@ class EditCalcTable extends Component {
|
||||||
const sumRowlistUrl = this.props.showTotalCell ? "/api/bs/hrmsalary/salaryacct/acctresult/sum" : "";
|
const sumRowlistUrl = this.props.showTotalCell ? "/api/bs/hrmsalary/salaryacct/acctresult/sum" : "";
|
||||||
this.postMessageToChild({
|
this.postMessageToChild({
|
||||||
dataSource, pageInfo, selectedRowKeys, showTotalCell: this.props.showTotalCell, sumRowlistUrl, payload,
|
dataSource, pageInfo, selectedRowKeys, showTotalCell: this.props.showTotalCell, sumRowlistUrl, payload,
|
||||||
calcDetail,
|
calcDetail, showSee: true,
|
||||||
columns: _.every(traverse(columns, calcDetail), (it, idx) => !it.fixed) ? _.map(traverse(columns, calcDetail), (it, idx) => ({
|
columns: _.every(traverse(columns, calcDetail), (it, idx) => !it.fixed) ? _.map(traverse(columns, calcDetail), (it, idx) => ({
|
||||||
...it,
|
...it,
|
||||||
fixed: idx < 2 ? "left" : false
|
fixed: idx < 2 ? "left" : false
|
||||||
|
|
@ -304,10 +304,7 @@ class EditCalcTable extends Component {
|
||||||
/>
|
/>
|
||||||
<EditSalaryCalcSlide {...salaryCalcSlide}
|
<EditSalaryCalcSlide {...salaryCalcSlide}
|
||||||
onClose={(isFresh) => this.setState({
|
onClose={(isFresh) => this.setState({
|
||||||
salaryCalcSlide: {
|
salaryCalcSlide: { visible: false, id: "", viewAttr: 2 }
|
||||||
visible: false,
|
|
||||||
id: ""
|
|
||||||
}
|
|
||||||
}, () => isFresh === "true" && this.queryCalcResultList())}/>
|
}, () => isFresh === "true" && this.queryCalcResultList())}/>
|
||||||
{
|
{
|
||||||
progressVisible &&
|
progressVisible &&
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@ import PayrollItemsTable from "../../../../calculateDetail/payrollItemsTable";
|
||||||
import IssuedAndReissueTable from "../../../../calculateDetail/issuedAndReissueTable";
|
import IssuedAndReissueTable from "../../../../calculateDetail/issuedAndReissueTable";
|
||||||
import { acctresultDetail, saveAcctResult } from "../../../../../apis/calculate";
|
import { acctresultDetail, saveAcctResult } from "../../../../../apis/calculate";
|
||||||
import { toDecimal_n } from "../../../../../util";
|
import { toDecimal_n } from "../../../../../util";
|
||||||
|
import CalcAnchorList from "./calcAnchorList";
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
|
|
||||||
|
|
||||||
const getLabel = WeaLocaleProvider.getLabel;
|
const getLabel = WeaLocaleProvider.getLabel;
|
||||||
|
|
||||||
class EditSalaryCalcSlide extends Component {
|
class EditSalaryCalcSlide extends Component {
|
||||||
|
|
@ -29,7 +29,7 @@ class EditSalaryCalcSlide extends Component {
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps, nextContext) {
|
componentWillReceiveProps(nextProps, nextContext) {
|
||||||
if (nextProps.visible !== this.props.visible && nextProps.visible) this.acctresultDetail(nextProps.id);
|
if (nextProps.visible !== this.props.visible && nextProps.visible) this.acctresultDetail(nextProps.id);
|
||||||
if (nextProps.visible !== this.props.visible && !nextProps.visible) this.setState({ selectedKey: "0" });
|
if (nextProps.visible !== this.props.visible && !nextProps.visible) this.setState({ selectedKey: "0" }, () => document.getElementById("salary_anchor_area").scrollTop = 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
acctresultDetail = (id) => {
|
acctresultDetail = (id) => {
|
||||||
|
|
@ -43,14 +43,17 @@ class EditSalaryCalcSlide extends Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
renderTitle = () => {
|
renderTitle = () => {
|
||||||
const { loading } = this.state;
|
const { loading } = this.state, { viewAttr } = this.props;
|
||||||
return <div className="titleDialog">
|
return <div className="titleDialog">
|
||||||
<div className="titleCol titleLeftBox">
|
<div className="titleCol titleLeftBox">
|
||||||
<div className="titleIcon"><i className="icon-coms-fa"/></div>
|
<div className="titleIcon"><i className="icon-coms-fa"/></div>
|
||||||
<div className="title">{getLabel(543559, "编辑薪资")}</div>
|
<div className="title">{viewAttr === 2 ? getLabel(543559, "编辑薪资") : getLabel(111, "查看薪资")}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="titleCol titleRightBox">
|
<div className="titleCol titleRightBox">
|
||||||
<Button type="primary" onClick={this.save} loading={loading}>{getLabel(537558, "保存")}</Button>
|
{
|
||||||
|
viewAttr === 2 &&
|
||||||
|
<Button type="primary" onClick={this.save} loading={loading}>{getLabel(537558, "保存")}</Button>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
};
|
};
|
||||||
|
|
@ -139,7 +142,9 @@ class EditSalaryCalcSlide extends Component {
|
||||||
className="salary-calculate-esf-layout" {...this.props}
|
className="salary-calculate-esf-layout" {...this.props}
|
||||||
top={0} width={60} height={100} measure={"%"}
|
top={0} width={60} height={100} measure={"%"}
|
||||||
direction={"right"} title={this.renderTitle()}
|
direction={"right"} title={this.renderTitle()}
|
||||||
content={<div className="salary-calculate-esf-area">
|
content={<div className="salary-calculate-esf-area" id="salary_anchor_area">
|
||||||
|
{/*锚点*/}
|
||||||
|
<CalcAnchorList datas={itemsByGroup} visible={this.props.visible}/>
|
||||||
<EditSalaryBaseInfo {...this.props} baseInfo={baseInfo}
|
<EditSalaryBaseInfo {...this.props} baseInfo={baseInfo}
|
||||||
onChange={baseInfo => this.setState({ baseInfo })}/>
|
onChange={baseInfo => this.setState({ baseInfo })}/>
|
||||||
<WeaTab keyParam="viewcondition" className="calc-esf-tab"
|
<WeaTab keyParam="viewcondition" className="calc-esf-tab"
|
||||||
|
|
@ -148,12 +153,14 @@ class EditSalaryCalcSlide extends Component {
|
||||||
/>
|
/>
|
||||||
{
|
{
|
||||||
selectedKey === "0" && _.map(itemsByGroup, item => {
|
selectedKey === "0" && _.map(itemsByGroup, item => {
|
||||||
return <PayrollItemsTable {...item} onChangeIssueReissueValue={this.handleItemValueChange}/>;
|
return <PayrollItemsTable {...this.props} {...item}
|
||||||
|
onChangeIssueReissueValue={this.handleItemValueChange}/>;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
selectedKey === "1" &&
|
selectedKey === "1" &&
|
||||||
<IssuedAndReissueTable
|
<IssuedAndReissueTable
|
||||||
|
{...this.props}
|
||||||
dataSource={issuedAndReissueItems}
|
dataSource={issuedAndReissueItems}
|
||||||
onChangeIssueReissueValue={this.handleItemValueChange}
|
onChangeIssueReissueValue={this.handleItemValueChange}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,7 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.salary-calculate-esf-area {
|
.salary-calculate-esf-area {
|
||||||
|
position: relative;
|
||||||
background: #f6f6f6;
|
background: #f6f6f6;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
@ -191,6 +192,109 @@
|
||||||
.wea-search-group {
|
.wea-search-group {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//锚点按钮
|
||||||
|
.anchor-list-collapsed {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.anchor-list-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
margin: 10px 15px 20px;
|
||||||
|
padding: 8px 10px;
|
||||||
|
overflow: auto;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0 3px 12px 0 rgba(0, 0, 0, .12);
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.anchor-list-collapsed-btn {
|
||||||
|
opacity: .5;
|
||||||
|
background: #000;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 3px;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.anchor-list-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
min-width: 130px;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.anchor-list {
|
||||||
|
padding: 0 10px;
|
||||||
|
position: relative;
|
||||||
|
margin-top: 10px;
|
||||||
|
transition: margin-top .3s;
|
||||||
|
|
||||||
|
.anchor-list-ink {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 5px;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.anchor-list-ink-ball.visible {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.anchor-list-ink-ball {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
display: none;
|
||||||
|
width: 3px;
|
||||||
|
height: 8px;
|
||||||
|
background-color: #5d9cec;
|
||||||
|
border: 1.5px solid #5d9cec;
|
||||||
|
border-radius: 8px;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
transition: top .3s ease-in-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.anchor-list-ink:before {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
width: 1px;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
content: " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
.anchor-list-link {
|
||||||
|
padding: 7px 0 7px 10px;
|
||||||
|
line-height: 1.143;
|
||||||
|
|
||||||
|
.anchor-list-link-title {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #666;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
transition: all .3s;
|
||||||
|
cursor: pointer;
|
||||||
|
outline: none;
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.anchor-list-link-active > .anchor-list-link-title {
|
||||||
|
color: #5d9cec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,11 @@ class IssuedAndReissueTable extends Component {
|
||||||
/>
|
/>
|
||||||
</span>,
|
</span>,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
const { canEdit, pattern } = record;
|
const { canEdit, pattern } = record, { viewAttr } = this.props;
|
||||||
return <WeaInputNumber
|
return <WeaInputNumber
|
||||||
disabled={!canEdit}
|
disabled={!canEdit}
|
||||||
min={0}
|
min={0}
|
||||||
|
viewAttr={viewAttr}
|
||||||
precision={pattern || 2}
|
precision={pattern || 2}
|
||||||
value={text || 0}
|
value={text || 0}
|
||||||
onChange={(value) => onChangeIssueReissueValue(record.salaryItemName, value, "issuedAndReissueItems")}
|
onChange={(value) => onChangeIssueReissueValue(record.salaryItemName, value, "issuedAndReissueItems")}
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,9 @@ class PayrollItemsTable extends Component {
|
||||||
</span>,
|
</span>,
|
||||||
width: "20%",
|
width: "20%",
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
const { canEdit, dataType, pattern } = record;
|
const { canEdit, dataType, pattern } = record, { viewAttr } = this.props;
|
||||||
return dataType === "number" ? <WeaInputNumber
|
return dataType === "number" ? <WeaInputNumber
|
||||||
|
viewAttr={viewAttr}
|
||||||
disabled={!canEdit}
|
disabled={!canEdit}
|
||||||
precision={!_.isNil(pattern) ? pattern : 0}
|
precision={!_.isNil(pattern) ? pattern : 0}
|
||||||
value={text || 0}
|
value={text || 0}
|
||||||
|
|
@ -46,6 +47,7 @@ class PayrollItemsTable extends Component {
|
||||||
/> : <WeaInput
|
/> : <WeaInput
|
||||||
disabled={!canEdit}
|
disabled={!canEdit}
|
||||||
value={text}
|
value={text}
|
||||||
|
viewAttr={viewAttr}
|
||||||
onChange={(value) => onChangeIssueReissueValue(record.salaryItemId, value, "itemsByGroup", salarySobItemGroupId)}
|
onChange={(value) => onChangeIssueReissueValue(record.salaryItemId, value, "itemsByGroup", salarySobItemGroupId)}
|
||||||
/>;
|
/>;
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +68,7 @@ class PayrollItemsTable extends Component {
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<WeaSearchGroup title={salarySobItemGroupName} showGroup needTigger>
|
<WeaSearchGroup title={salarySobItemGroupName} showGroup needTigger className={`anchor_${salarySobItemGroupId}`}>
|
||||||
<WeaTable
|
<WeaTable
|
||||||
rowKey="salaryItemId"
|
rowKey="salaryItemId"
|
||||||
dataSource={dataSource}
|
dataSource={dataSource}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue