liubp
2025-12-19 5bdaf416d66b675131004de1aba5d161772a52b0
添加所属小区字段
20个文件已修改
1022 ■■■■ 已修改文件
public/css/vc.css 310 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/admin/addContract/addContract.html 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/admin/addContract/addContract.js 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/admin/contractChangeManage/contractChangeManage.html 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/admin/contractChangeManage/contractChangeManage.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/admin/contractManage/contractManage.html 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/admin/contractManage/contractManage.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/admin/contractTypeManage/contractTypeManage.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/admin/expirationContractManage/expirationContractManage.html 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/admin/expirationContractManage/expirationContractManage.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/admin/newContractManage/newContractManage.html 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/admin/newContractManage/newContractManage.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/common/communityManage/add/add.html 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/common/communityManage/add/add.js 94 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/common/communityManage/detail/detail.html 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/common/communityManage/detail/detail.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/common/communityManage/edit/edit.html 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/common/communityManage/edit/edit.js 75 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/property/costDetail/costDetail.html 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/pages/property/costDetail/costDetail.js 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/css/vc.css
@@ -9,7 +9,7 @@
    --vc-menu-sub-font-color: #545761;
    --vc-menu-sub-bg-active-color: #EAF0FE;
    --vc-menu-sub-active-font-color: #3E77FC;
    --vc-menu-sub-title-font-color: #4F525C;
    --vc-menu-sub-title-font-color: #404357;
    --vc-menu-sub-footer: #F6F6F7;
    --vc-nav-bg: #1D1F2D;
    --vc-nav-color: #888888;
@@ -534,7 +534,7 @@
}
.border-bottom {
    border-bottom: 1px solid #e7eaec !important;
    border-bottom: 1px solid #e7eaec;
}
.border-radius {
@@ -747,7 +747,7 @@
.vc-nav ul li.active {
    color: var(--vc-nav-active-color);
    border-bottom: 2px solid var(--vc-nav-active-color) !important;
    border-bottom: 2px solid var(--vc-nav-active-color);
}
.vc-main .vc-main-content {
@@ -1042,7 +1042,7 @@
}
.table-scroll {
    overflow-y: scroll !important;
    overflow-y: scroll;
}
.hc-table-div::-webkit-scrollbar {
@@ -1197,6 +1197,7 @@
    font-size: 14px;
    font-weight: bold;
    margin: 10px 0 5px;
    color: #404357;
}
.community-add .detail-note {
@@ -1240,13 +1241,310 @@
.community-add input.error,
.community-add select.error {
    border-color: #dc3545 !important;
    border-color: #dc3545;
    background-color: #fff5f5;
    box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
}
.community-add input.error:focus,
.community-add select.error:focus {
    border-color: #dc3545 !important;
    border-color: #dc3545;
    box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
}
.cost-detail-container {
    width: 98%;
    margin: 20px auto;
    font-family: "微软雅黑", sans-serif;
    background: transparent;
    padding: 0;
}
.cost-detail-container * {
    box-sizing: border-box;
}
.cost-detail-container h2 {
    margin-bottom: 20px;
    color: #333;
    font-size: 18px;
    font-weight: 600;
}
.cost-detail-container .search-bar {
    margin-bottom: 15px;
    padding: 15px;
    background: #f5f5f5;
    border-radius: 4px;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
}
.cost-detail-container .search-bar div {
    display: flex;
    align-items: center;
    gap: 8px;
}
.cost-detail-container .search-bar label {
    font-size: 14px;
    color: #333;
    white-space: nowrap;
    font-weight: 500;
}
.cost-detail-container .search-bar input,
.cost-detail-container .search-bar select {
    padding: 6px 12px;
    border: 1px solid #d9d9d9;
    border-radius: 4px;
    font-size: 14px;
    height: 32px;
    min-width: 150px;
    background: #fff;
}
.cost-detail-container .search-bar .queryDate {
    position: relative;
}
.cost-detail-container .search-bar input:focus,
.cost-detail-container .search-bar select:focus {
    outline: none;
    border-color: #1677ff;
}
.cost-detail-container .search-bar button {
    padding: 6px 16px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
    height: 32px;
    transition: all 0.3s;
}
.cost-detail-container .search-bar .query-btn {
    background: #1677ff;
    color: #fff;
    border: 1px solid #1677ff;
}
.cost-detail-container .search-bar .query-btn:hover {
    background: #4096ff;
    color: #fff;
    border-color: #4096ff;
}
.cost-detail-container .search-bar .reset-btn {
    background: #fff;
    color: #666;
    border: 1px solid #d9d9d9;
}
.cost-detail-container .search-bar .reset-btn:hover {
    color: #333;
    border-color: #bfbfbf;
}
.cost-detail-container .search-bar .action-buttons {
    margin-left: auto;
    display: flex;
    gap: 12px;
}
.cost-detail-container .action-buttons button {
    padding: 6px 16px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
    height: 32px;
    transition: all 0.3s;
}
.cost-detail-container .action-buttons .add-btn {
    background: #1677ff;
    color: #fff;
    border: 1px solid #1677ff;
}
.cost-detail-container .action-buttons .add-btn:hover {
    background: #4096ff;
}
.cost-detail-container .action-buttons .import-btn {
    background: #fff;
    color: #333;
    border: 1px solid #d9d9d9;
}
.cost-detail-container .action-buttons .import-btn:hover {
    background: #f5f5f5;
    border-color: #bfbfbf;
}
.cost-detail-container table {
    width: 100%;
    border-collapse: collapse;
    border: 1px solid #e8e8e8;
    font-size: 14px;
    background: #fff;
    margin-bottom: 0;
}
.cost-detail-container table th,
.cost-detail-container table td {
    padding: 12px;
    border: 1px solid #e8e8e8;
    text-align: center;
}
.cost-detail-container table th {
    background: #f5f5f5;
    font-weight: 600;
    white-space: nowrap;
    color: #333;
    text-align: center;
}
.cost-detail-container table td {
    color: #333;
    text-align: center;
}
.cost-detail-container table tbody tr {
    background: #fff;
}
.cost-detail-container table tbody tr:hover {
    background: #f5f5f5;
}
.cost-detail-container table td a {
    color: #1677ff;
    text-decoration: none;
    margin-right: 12px;
    cursor: pointer;
    white-space: nowrap;
}
.cost-detail-container table td a:hover {
    text-decoration: underline;
    color: #4096ff;
}
.cost-detail-container table td a:last-child {
    margin-right: 0;
}
.cost-detail-container .pagination {
    margin-top: 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    color: #333;
}
.cost-detail-container .pagination .pagination-info {
    color: #666;
}
.cost-detail-container .pagination .pagination-controls {
    display: flex;
    align-items: center;
    gap: 8px;
}
.cost-detail-container .pagination .page-size-select {
    padding: 4px 8px;
    border: 1px solid #d9d9d9;
    border-radius: 4px;
    font-size: 14px;
    height: 32px;
    width: 60px;
}
.cost-detail-container .pagination .page-size-label,
.cost-detail-container .pagination .jump-label,
.cost-detail-container .pagination .page-label {
    color: #666;
    margin: 0 4px;
}
.cost-detail-container .pagination .page-btn {
    padding: 4px 8px;
    border: 1px solid #d9d9d9;
    background: #fff;
    cursor: pointer;
    font-size: 14px;
    min-width: 32px;
    height: 32px;
    border-radius: 4px;
    transition: all 0.3s;
    color: #333;
}
.cost-detail-container .pagination .page-btn:hover:not(:disabled) {
    color: #1677ff;
    border-color: #1677ff;
}
.cost-detail-container .pagination .page-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    background: #f5f5f5;
}
.cost-detail-container .pagination .page-btn.active {
    background: #1677ff;
    color: #fff;
    border-color: #1677ff;
}
.cost-detail-container .pagination .page-ellipsis {
    color: #666;
    padding: 0 4px;
}
.cost-detail-container .pagination .jump-input {
    width: 50px;
    padding: 4px 8px;
    text-align: center;
    border: 1px solid #d9d9d9;
    border-radius: 4px;
    font-size: 14px;
    height: 32px;
    margin: 0 4px;
}
.cost-detail-container .pagination .jump-input:focus {
    outline: none;
    border-color: #1677ff;
}
.cost-detail-container .action-buttons .add-btn i {
    margin-right: 4px;
}
.cost-detail-container .pagination .page-btn[disabled] {
    background-color: #f5f5f5;
    border-color: #d9d9d9;
    color: rgba(0, 0, 0, 0.25);
}
@media (max-width: 1200px) {
    .cost-detail-container {
        width: 95%;
        overflow-x: auto;
    }
    .cost-detail-container table {
        min-width: 1400px;
    }
}
#costDetailTableHead th{
    background-color: rgb(233, 243, 255);
}
public/pages/admin/addContract/addContract.html
@@ -57,6 +57,25 @@
                            <div class="form-group row">
                                <label class="col-sm-3 col-form-label padding-lr-sm text-right">
                                    <span>
                                        <vc:i18n name="所属小区" namespace="addContract"></vc:i18n>
                                    </span>
                                </label>
                                <div class="col-sm-9 padding-lr-xs">
                                    <select class="custom-select" v-model="addContractInfo.communityId"
                                        @change="_changeCommunity()">
                                        <option selected disabled value="">
                                            {{vc.i18n('请选择所属小区','addContract')}}
                                        </option>
                                        <option v-for="(item,index) in addContractInfo.communities" :key="index" :value="item.communityId">{{item.name}}
                                        </option>
                                    </select>
                                </div>
                            </div>
                        </div>
                        <div class="col-sm-4">
                            <div class="form-group row">
                                <label class="col-sm-3 col-form-label padding-lr-sm text-right">
                                    <span>
                                        <vc:i18n name="合同名称" namespace="addContract"></vc:i18n>
                                    </span>
                                </label>
public/pages/admin/addContract/addContract.js
@@ -3,6 +3,7 @@
        data: {
            addContractInfo: {
                communityId: vc.getCurrentCommunity().communityId,
                communities: [],
                contractId: '',
                contractName: '',
                contractCode: '',
@@ -53,6 +54,7 @@
        },
        _initMethod: function () {
            vc.component._initAddContractInfo();
            $that._loadCommunities();
            $that._loadAddContractType();
            $that._loadAddContractParkA();
            $that._loadAddContractParkB();
@@ -344,6 +346,13 @@
                            param: "",
                            errInfo: "合同签订时间不能为空"
                        }
                    ],
                    'addContractInfo.communityId': [
                        {
                            limit: "required",
                            param: "",
                            errInfo: "请选择所属小区"
                        }
                    ]
                });
            },
@@ -372,7 +381,8 @@
                    vc.toast(vc.validate.errInfo);
                    return;
                }
                $that.addContractInfo.communityId = vc.getCurrentCommunity().communityId;
                // 使用下拉框选中的communityId传递给接口
                // addContractInfo.communityId 已通过 v-model 绑定,包含用户选择的值
                vc.http.apiPost(
                    '/contract/saveContract',
@@ -443,6 +453,27 @@
                    staffName: '',
                    nextUserId: ''
                };
            },
            _loadCommunities: function () {
                let param = {
                    params: {
                        page: 1,
                        row: 100
                    }
                };
                //发送get请求
                vc.http.apiGet('/community.listCommunitys',
                    param,
                    function (json, res) {
                        let _communityInfo = JSON.parse(json);
                        if (_communityInfo.code == 0) {
                            $that.addContractInfo.communities = _communityInfo.communitys || [];
                        }
                    },
                    function (errInfo, error) {
                        console.log('请求失败处理');
                    }
                );
            },
            _loadAddContractType: function () {
                let param = {
@@ -567,6 +598,9 @@
                    }
                );
            },
            _changeCommunity: function () {
                // 小区变更时的处理逻辑
            },
            _goBack: function () {
                vc.goBack();
            },
public/pages/admin/contractChangeManage/contractChangeManage.html
@@ -76,6 +76,9 @@
                        <thead>
                        <tr>
                            <th class="text-center">
                                <vc:i18n name="所属小区" namespace="contractChangeManage"></vc:i18n>
                            </th>
                            <th class="text-center">
                                <vc:i18n name="合同名称" namespace="contractChangeManage"></vc:i18n>
                            </th>
                            <th class="text-center">
@@ -112,6 +115,7 @@
                        </thead>
                        <tbody>
                        <tr v-for="contract in contractChangeManageInfo.contracts">
                            <td class="text-center">{{contract.communityName}}</td>
                            <td class="text-center">{{contract.contractName}}</td>
                            <td class="text-center">{{contract.contractCode}}</td>
                            <td class="text-center">{{contract.contractTypeName}}</td>
public/pages/admin/contractChangeManage/contractChangeManage.js
@@ -13,7 +13,7 @@
                moreCondition: false,
                contractId: '',
                conditions: {
                    communityId: vc.getCurrentCommunity().communityId,
                    // communityId: vc.getCurrentCommunity().communityId,
                    contractName: '',
                    contractCode: '',
                    contractType: ''
@@ -40,7 +40,7 @@
                var param = {
                    params: vc.component.contractChangeManageInfo.conditions
                };
                param.params.communityId = vc.getCurrentCommunity().communityId;
                // param.params.communityId = vc.getCurrentCommunity().communityId;
                param.params.contractName = param.params.contractName.trim();
                param.params.contractCode = param.params.contractCode.trim();
                //发送get请求
@@ -96,7 +96,7 @@
            },
            //重置
            _resetContractMethod: function () {
                vc.component.contractChangeManageInfo.conditions.communityId = vc.getCurrentCommunity().communityId;
                // vc.component.contractChangeManageInfo.conditions.communityId = vc.getCurrentCommunity().communityId;
                vc.component.contractChangeManageInfo.conditions.contractName = "";
                vc.component.contractChangeManageInfo.conditions.contractCode = "";
                vc.component.contractChangeManageInfo.conditions.contractType = "";
public/pages/admin/contractManage/contractManage.html
@@ -99,6 +99,9 @@
                        <thead>
                        <tr>
                            <th class="text-center">
                                <vc:i18n name="所属小区" namespace="contractManage"></vc:i18n>
                            </th>
                            <th class="text-center">
                                <vc:i18n name="合同名称" namespace="contractManage"></vc:i18n>
                            </th>
                            <th class="text-center">
@@ -135,6 +138,7 @@
                        </thead>
                        <tbody>
                        <tr v-for="contract in contractManageInfo.contracts">
                            <td class="text-center">{{contract.communityName}}</td>
                            <td class="text-center">{{contract.contractName}}</td>
                            <td class="text-center">{{contract.contractCode}}</td>
                            <td class="text-center">
public/pages/admin/contractManage/contractManage.js
@@ -13,7 +13,7 @@
                moreCondition: false,
                contractId: '',
                conditions: {
                    communityId: vc.getCurrentCommunity().communityId,
                    // communityId: vc.getCurrentCommunity().communityId,
                    contractNameLike: '',
                    contractCodeLike: '',
                    contractType: '',
@@ -101,7 +101,7 @@
                var param = {
                    params: vc.component.contractManageInfo.conditions
                };
                param.params.communityId = vc.getCurrentCommunity().communityId;
                // param.params.communityId = vc.getCurrentCommunity().communityId;
                param.params.contractNameLike = param.params.contractNameLike.trim();
                param.params.contractCodeLike = param.params.contractCodeLike.trim();
                param.params.partyBLike = param.params.partyBLike.trim();
@@ -159,7 +159,7 @@
            },
            //重置
            _resetContractMethod: function () {
                vc.component.contractManageInfo.conditions.communityId = vc.getCurrentCommunity().communityId;
                // vc.component.contractManageInfo.conditions.communityId = vc.getCurrentCommunity().communityId;
                vc.component.contractManageInfo.conditions.contractNameLike = "";
                // vc.component.contractManageInfo.conditions.contractCode = "";
                vc.component.contractManageInfo.conditions.contractType = "";
public/pages/admin/contractTypeManage/contractTypeManage.js
@@ -21,7 +21,7 @@
                    typeName: '',
                    audit: '',
                    contractTypeId: '',
                    communityId: vc.getCurrentCommunity().communityId,
                    // communityId: vc.getCurrentCommunity().communityId,
                }
            }
@@ -50,7 +50,7 @@
                var param = {
                    params: vc.component.contractTypeManageInfo.conditions
                };
                param.params.communityId = vc.getCurrentCommunity().communityId;
                // param.params.communityId = vc.getCurrentCommunity().communityId;
                param.params.typeName = param.params.typeName.trim();
                param.params.audit = param.params.audit.trim();
                //发送get请求
@@ -88,7 +88,7 @@
            //重置
            _resetContractTypeMethod: function () {
                vc.component.contractTypeManageInfo.conditions.typeName = "";
                vc.component.contractTypeManageInfo.conditions.communityId = vc.getCurrentCommunity().communityId;
                // vc.component.contractTypeManageInfo.conditions.communityId = vc.getCurrentCommunity().communityId;
                vc.component.contractTypeManageInfo.conditions.audit = "";
                vc.component._listContractTypes(DEFAULT_PAGE, DEFAULT_ROWS);
            },
public/pages/admin/expirationContractManage/expirationContractManage.html
@@ -64,6 +64,9 @@
                        <thead>
                        <tr>
                            <th class="text-center">
                                <span><vc:i18n name="所属小区" namespace="expirationContractManage"></vc:i18n></span>
                            </th>
                            <th class="text-center">
                                <span><vc:i18n name="合同名称" namespace="expirationContractManage"></vc:i18n></span>
                            </th>
                            <th class="text-center">
@@ -100,6 +103,7 @@
                        </thead>
                        <tbody>
                        <tr v-for="contract in expirationContractInfo.contracts">
                            <td class="text-center">{{contract.communityName}}</td>
                            <td class="text-center">{{contract.contractName}}</td>
                            <td class="text-center">{{contract.contractCode}}</td>
                            <td class="text-center">{{contract.contractTypeName}}</td>
public/pages/admin/expirationContractManage/expirationContractManage.js
@@ -13,7 +13,7 @@
                moreCondition: false,
                contractId: '',
                conditions: {
                    communityId: vc.getCurrentCommunity().communityId,
                    // communityId: vc.getCurrentCommunity().communityId,
                    contractNameLike: '',
                    contractCode: '',
                    contractType: '',
@@ -93,7 +93,7 @@
            },
            //重置
            _resetContractMethod: function () {
                vc.component.expirationContractInfo.conditions.communityId = vc.getCurrentCommunity().communityId;
                // vc.component.expirationContractInfo.conditions.communityId = vc.getCurrentCommunity().communityId;
                vc.component.expirationContractInfo.conditions.contractNameLike = "";
                vc.component.expirationContractInfo.conditions.contractCode = "";
                vc.component.expirationContractInfo.conditions.contractType = "";
public/pages/admin/newContractManage/newContractManage.html
@@ -67,6 +67,9 @@
                        <thead>
                        <tr>
                            <th class="text-center">
                                <span><vc:i18n name="所属小区" namespace="newContractManage"></vc:i18n></span>
                            </th>
                            <th class="text-center">
                                <span><vc:i18n name="合同名称" namespace="newContractManage"></vc:i18n></span>
                            </th>
                            <th class="text-center">
@@ -103,6 +106,7 @@
                        </thead>
                        <tbody>
                        <tr v-for="contract in newContractManageInfo.contracts">
                            <td class="text-center">{{contract.communityName}}</td>
                            <td class="text-center">{{contract.contractName}}</td>
                            <td class="text-center">{{contract.contractCode}}</td>
                            <td class="text-center">
public/pages/admin/newContractManage/newContractManage.js
@@ -14,7 +14,7 @@
                contractId: '',
                conditions: {
                    contractNameLike: '',
                    communityId: vc.getCurrentCommunity().communityId,
                    // communityId: vc.getCurrentCommunity().communityId,
                    contractCode: '',
                    contractType: '',
                    state: ''
@@ -42,7 +42,7 @@
                    params: vc.component.newContractManageInfo.conditions
                };
                param.params.contractNameLike = param.params.contractNameLike.trim();
                param.params.communityId = vc.getCurrentCommunity().communityId;
                // param.params.communityId = vc.getCurrentCommunity().communityId;
                param.params.contractCode = param.params.contractCode.trim();
                //发送get请求
                vc.http.apiGet('/contract/queryContract',
@@ -102,7 +102,7 @@
            //重置
            _resetContractMethod: function () {
                vc.component.newContractManageInfo.conditions.contractNameLike = "";
                vc.component.newContractManageInfo.conditions.communityId = vc.getCurrentCommunity().communityId;
                // vc.component.newContractManageInfo.conditions.communityId = vc.getCurrentCommunity().communityId;
                vc.component.newContractManageInfo.conditions.contractCode = "";
                vc.component.newContractManageInfo.conditions.contractType = "";
                vc.component._listContracts(DEFAULT_PAGE, DEFAULT_ROWS);
public/pages/common/communityManage/add/add.html
@@ -238,10 +238,10 @@
                
                <div class="radio-group" style="width: 153px; margin-right: 90px;">
                    <label>是否有固定的装修垃圾堆放点</label>
                    <label style="margin-left: -40px;"><input type="radio" name="garbage" value=true v-model="formData.hasDecorationRubbishPoint"> 有</label>
                    <label style="margin-left: -40px;"><input type="radio" name="garbage" value=false v-model="formData.hasDecorationRubbishPoint"> 无</label>
                    <label><input type="radio" name="garbage" value="是" v-model="formData.hasDecorationRubbishPoint"> 有</label>
                    <label><input type="radio" name="garbage" value="否" v-model="formData.hasDecorationRubbishPoint"> 无</label>
                </div>
                <label>需保安值守出入口(个)</label>
                <label style="margin-left: 100px;">需保安值守出入口(个)</label>
                <input type="text" placeholder="请输入" style="width: 153px;" v-model.number="formData.securityEntranceCount">
            </div>
        </div>
public/pages/common/communityManage/add/add.js
@@ -122,7 +122,7 @@
            // 确保 vc.component 已完全初始化后再调用
            let retryCount = 0;
            const maxRetries = 20; // 最多重试20次(约1秒)
            const loadData = function() {
            const loadData = function () {
                if (vc.component && typeof vc.component._loadCommunityDetail === 'function') {
                    vc.component._loadCommunityDetail();
                } else {
@@ -140,14 +140,14 @@
        _initEvent: function () {
            // 初始化时添加输入事件监听,自动移除错误样式
            const $that = this;
            setTimeout(function() {
            setTimeout(function () {
                // 为所有输入框和选择框添加输入事件监听
                const inputs = document.querySelectorAll('.community-add input, .community-add select');
                inputs.forEach(function(input) {
                    input.addEventListener('input', function() {
                inputs.forEach(function (input) {
                    input.addEventListener('input', function () {
                        $that.removeError(input.id);
                    });
                    input.addEventListener('change', function() {
                    input.addEventListener('change', function () {
                        $that.removeError(input.id);
                    });
                });
@@ -155,33 +155,33 @@
        },
        methods: {
            // 添加错误样式
            addError: function(elementId) {
            addError: function (elementId) {
                const element = document.getElementById(elementId);
                if (element) {
                    element.classList.add('error');
                }
            },
            // 移除错误样式
            removeError: function(elementId) {
            removeError: function (elementId) {
                const element = document.getElementById(elementId);
                if (element) {
                    element.classList.remove('error');
                }
            },
            // 清除所有错误样式
            clearAllErrors: function() {
            clearAllErrors: function () {
                const elements = document.querySelectorAll('.community-add input.error, .community-add select.error');
                elements.forEach(function(element) {
                elements.forEach(function (element) {
                    element.classList.remove('error');
                });
            },
            toBoolString: function(value, defaultValue) {
            toBoolString: function (value, defaultValue) {
                if (value === undefined || value === null) {
                    return defaultValue;
                }
                return value ? 'true' : 'false';
            },
            chooseProvince: function(event) {
            chooseProvince: function (event) {
                const provCode = event.target.value;
                vc.component.selectProv = provCode;
                vc.component.selectCity = '';
@@ -190,7 +190,7 @@
                vc.component.areas = [];
                // 更新 formData 中的省份名称
                if (vc.component.provs && vc.component.provs.length > 0) {
                    vc.component.provs.forEach(function(_param) {
                    vc.component.provs.forEach(function (_param) {
                        if (_param.areaCode == provCode) {
                            vc.component.selectProvName = _param.areaName;
                            vc.component.formData.projectAddressProvince = _param.areaName;
@@ -204,14 +204,14 @@
                    vc.component._initArea('202', provCode);
                }
            },
            chooseCity: function(event) {
            chooseCity: function (event) {
                const cityCode = event.target.value;
                vc.component.selectCity = cityCode;
                vc.component.selectArea = '';
                vc.component.areas = [];
                // 更新 formData 中的城市名称
                if (vc.component.citys && vc.component.citys.length > 0) {
                    vc.component.citys.forEach(function(_param) {
                    vc.component.citys.forEach(function (_param) {
                        if (_param.areaCode == cityCode) {
                            vc.component.selectCityName = _param.areaName;
                            vc.component.formData.projectAddressCity = _param.areaName;
@@ -224,25 +224,25 @@
                    vc.component._initArea('303', cityCode);
                }
            },
            chooseArea: function(event) {
            chooseArea: function (event) {
                const areaCode = event.target.value;
                vc.component.selectArea = areaCode;
                vc.component.formData.cityCode = areaCode;
                vc.component.formData.areaAddress = '';
                // 更新 formData 中的区县名称
                if (vc.component.areas && vc.component.areas.length > 0) {
                    vc.component.areas.forEach(function(_param) {
                    vc.component.areas.forEach(function (_param) {
                        if (_param.areaCode == areaCode) {
                            vc.component.selectAreaName = _param.areaName;
                            vc.component.formData.projectAddressDistrict = _param.areaName;
                        }
                    });
                }
                // 构建区域地址
                if (vc.component.provs && vc.component.provs.length > 0) {
                    vc.component.provs.forEach(function(_param) {
                    vc.component.provs.forEach(function (_param) {
                        if (_param.areaCode == vc.component.selectProv) {
                            vc.component.selectProvName = _param.areaName;
                            vc.component.formData.areaAddress = _param.areaName;
@@ -250,7 +250,7 @@
                    });
                }
                if (vc.component.citys && vc.component.citys.length > 0) {
                    vc.component.citys.forEach(function(_param) {
                    vc.component.citys.forEach(function (_param) {
                        if (_param.areaCode == vc.component.selectCity) {
                            vc.component.selectCityName = _param.areaName;
                            if (vc.component.formData.areaAddress) {
@@ -262,7 +262,7 @@
                    });
                }
                if (vc.component.areas && vc.component.areas.length > 0) {
                    vc.component.areas.forEach(function(_param) {
                    vc.component.areas.forEach(function (_param) {
                        if (_param.areaCode == vc.component.selectArea) {
                            vc.component.selectAreaName = _param.areaName;
                            if (vc.component.formData.areaAddress) {
@@ -274,7 +274,7 @@
                    });
                }
            },
            _initArea: function(_areaLevel, _parentAreaCode) {
            _initArea: function (_areaLevel, _parentAreaCode) {
                var _param = {
                    params: {
                        areaLevel: _areaLevel,
@@ -291,7 +291,7 @@
                                // 填充省份下拉框
                                const provinceSelect = document.getElementById('province');
                                if (provinceSelect) {
                                    _tmpAreas.forEach(function(item) {
                                    _tmpAreas.forEach(function (item) {
                                        const option = document.createElement('option');
                                        option.value = item.areaCode;
                                        option.textContent = item.areaName;
@@ -304,7 +304,7 @@
                                const citySelect = document.getElementById('city');
                                if (citySelect) {
                                    citySelect.innerHTML = '<option value="">请选择市</option>';
                                    _tmpAreas.forEach(function(item) {
                                    _tmpAreas.forEach(function (item) {
                                        const option = document.createElement('option');
                                        option.value = item.areaCode;
                                        option.textContent = item.areaName;
@@ -317,7 +317,7 @@
                                const areaSelect = document.getElementById('area');
                                if (areaSelect) {
                                    areaSelect.innerHTML = '<option value="">请选择区</option>';
                                    _tmpAreas.forEach(function(item) {
                                    _tmpAreas.forEach(function (item) {
                                        const option = document.createElement('option');
                                        option.value = item.areaCode;
                                        option.textContent = item.areaName;
@@ -338,7 +338,7 @@
                    return {};
                }
                return {
                    communityId: info.communityId || info.communityId || '',
                    communityId: info.communityId || '',
                    newBId: info.newBId || '',
                    feePrice: info.feePrice || '',
                    projectAddressProvince: info.projectAddressProvince || info.provinceName || '',
@@ -393,7 +393,7 @@
                    groundNonMotorVehicleArea: info.groundNonMotorVehicleArea || info.nonElectricCarGroundArea || '',
                    undergroundNonMotorVehicleArea: info.undergroundNonMotorVehicleArea || info.nonElectricCarUndergroundArea || '',
                    clubhouseArea: info.clubhouseArea || info.clubArea || '',
                    hasDecorationRubbishPoint: vc.component.toBoolString(info.hasDecorationRubbishPoint, info.garbageFixed ? 'true' : 'false'),
                    hasDecorationRubbishPoint: info.hasDecorationRubbishPoint === '是' || info.garbageFixed == 1 ? '是' : '否',
                    securityEntranceCount: info.securityEntranceCount || info.gateGuardTotal || '',
                    elevatorCount: info.elevatorCount || info.elevatorTotal || '',
                    elevatorType: info.elevatorType || '',
@@ -435,17 +435,17 @@
                }
                const $that = this;
                const formData = vc.component.formData;
                // 清除之前的错误样式
                vc.component.clearAllErrors();
                // 验证必填字段
                if (!formData.name || formData.name.trim() === '') {
                    vc.toast('请输入小区名称');
                    vc.component.addError('input-name');
                    return;
                }
                // 构建详细地址
                const addressParts = [];
                if (formData.projectAddressTown) {
@@ -455,7 +455,7 @@
                    addressParts.push(formData.projectAddressRoad);
                }
                const address = addressParts.join(' ') || '';
                if (!address || address.trim() === '') {
                    vc.toast('请输入详细地址');
                    if (!formData.projectAddressTown || formData.projectAddressTown.trim() === '') {
@@ -466,7 +466,7 @@
                    }
                    return;
                }
                // 构建区域地址
                let areaAddress = formData.areaAddress || '';
                // 如果 areaAddress 为空,尝试从省市区名称构建
@@ -489,7 +489,7 @@
                    }
                    areaAddress = areaParts.join('');
                }
                if (!areaAddress || areaAddress.trim() === '') {
                    vc.toast('请选择所在城市');
                    if (!vc.component.selectProv) {
@@ -503,7 +503,7 @@
                    }
                    return;
                }
                // 验证区域编码(必须选择到区县级别)
                const cityCode = formData.cityCode || vc.component.selectArea || '';
                if (!cityCode || cityCode.trim() === '') {
@@ -519,7 +519,7 @@
                    }
                    return;
                }
                // 验证联系电话(使用物业联系人电话或报修电话)
                const tel = formData.propertyManagerPhone || formData.dayRepairPhone || '';
                if (!tel || tel.trim() === '') {
@@ -529,13 +529,13 @@
                        vc.component.addError('input-phone');
                    }
                    // 如果物业联系人电话为空,且日间电话也为空,则也标记日间电话
                    if ((!formData.propertyManagerPhone || formData.propertyManagerPhone.trim() === '') &&
                    if ((!formData.propertyManagerPhone || formData.propertyManagerPhone.trim() === '') &&
                        (!formData.dayRepairPhone || formData.dayRepairPhone.trim() === '')) {
                        vc.component.addError('input-day-phone');
                    }
                    return;
                }
                // 状态映射:statusCd (1=正常, 2=暂停, 3=注销) -> state (状态编码)
                let state = '1100'; // 默认正常状态
                if (formData.statusCd === '1') {
@@ -545,7 +545,7 @@
                } else if (formData.statusCd === '3') {
                    state = '1300'; // 注销(假设编码)
                }
                // 构建提交数据
                const submitData = {
                    // 基础参数 - 必填
@@ -555,7 +555,7 @@
                    tel: tel,
                    cityCode: cityCode,
                    state: state,
                    // 基础参数 - 可选
                    tmpAddress: formData.tmpAddress || '',
                    nearbyLandmarks: formData.nearbyLandmarks || '',
@@ -568,7 +568,7 @@
                    communityId: formData.communityId || '',
                    communityCode: formData.communityCode || '',
                    communityArea: formData.communityArea || '',
                    // 项目扩展参数
                    projectAddressProvince: formData.projectAddressProvince || '',
                    projectAddressCity: formData.projectAddressCity || '',
@@ -622,7 +622,6 @@
                    groundNonMotorVehicleArea: formData.groundNonMotorVehicleArea || '',
                    undergroundNonMotorVehicleArea: formData.undergroundNonMotorVehicleArea || '',
                    clubhouseArea: formData.clubhouseArea || '',
                    hasDecorationRubbishPoint: formData.hasDecorationRubbishPoint || '',
                    securityEntranceCount: formData.securityEntranceCount || '',
                    elevatorCount: formData.elevatorCount || '',
                    elevatorType: formData.elevatorType || '',
@@ -650,11 +649,11 @@
                    multilayerVillaBuildingCount: formData.multilayerVillaBuildingCount || '',
                    residentialHouseholdCount: formData.residentialHouseholdCount || '',
                    shopHouseholdCount: formData.shopHouseholdCount || '',
                    // 扩展属性
                    attrs: formData.attrs || []
                };
                // 转换数字字段
                const numberFields = [
                    'fireHydrantCount', 'fireChannelCount', 'waterTankCount', 'reservoirCount',
@@ -665,23 +664,22 @@
                    'barrierGateCount', 'waterPumpCount', 'groundParkingSpaces', 'undergroundParkingSpaces',
                    'totalBuildingCount', 'buildingUnitCount', 'highRiseBuildingCount',
                    'multilayerVillaBuildingCount', 'residentialHouseholdCount', 'shopHouseholdCount',
                    'payFeeMonth', 'hasManagerCertificate', 'hasDecorationRubbishPoint'
                    'payFeeMonth', 'hasManagerCertificate'
                ];
                numberFields.forEach(field => {
                    if (submitData[field] !== '' && submitData[field] !== null && submitData[field] !== undefined) {
                        submitData[field] = Number(submitData[field]);
                    } else if (field === 'hasManagerCertificate' || field === 'hasDecorationRubbishPoint') {
                    } else if (field === 'hasManagerCertificate') {
                        submitData[field] = 0;
                    }
                });
                // 转换Decimal字段
                const decimalFields = [
                    'feePrice', 'projectLandArea', 'totalConstructionArea', 'chargeableTotalArea',
                    'chargeableAreaMultilayer', 'chargeableAreaHighRise1', 'chargeableAreaHighRiseUp',
                    'chargeableAreaShop', 'chargeableAreaVilla', 'chargeableAreaOffice',
                    'chargeableAreaCommercialHouse', 'greenArea', 'groundNonMechanicalFee',
                    'garageNonMechanicalFee', 'temporaryHourlyFee', 'temporaryDailyFee',
                    'garageNonMechanicalFee', 'temporaryHourlyFee', 'temporaryDailyFee',
                    'temporaryPerTimeFee', 'communityArea'
                ];
                decimalFields.forEach(field => {
@@ -691,7 +689,7 @@
                        submitData[field] = 0;
                    }
                });
                // 清理空字符串字段,转换为null或删除
                Object.keys(submitData).forEach(key => {
                    if (submitData[key] === '') {
public/pages/common/communityManage/detail/detail.html
@@ -71,7 +71,7 @@
            <p>{{communityDetailInfo.publicArea || '--'}} ㎡</p>
        </div>
        <div class="detail-note">
            面积明细:{{communityDetailInfo.areaDetails || ('总:' + communityDetailInfo.totalArea + ' 包括:(住宅:' + communityDetailInfo.residentialArea + ' 非住宅:' + communityDetailInfo.nonResidentialArea + ')') || '--'}}
            <label style="color: #404357; font-weight: 800;"> 面积明细:</label>{{communityDetailInfo.areaDetails || ('总:' + communityDetailInfo.totalArea + ' 包括:(住宅:' + communityDetailInfo.residentialArea + ' 非住宅:' + communityDetailInfo.nonResidentialArea + ')') || '--'}}
        </div>
    </div>
@@ -82,7 +82,7 @@
            <label>物业管理处地址:</label>
            <p>{{communityDetailInfo.managementAddress || '--'}}</p>
        </div>
        <div class="sub-title">管理处联系人:</div>
        <div class="sub-title" style="color: #404357;">管理处联系人:</div>
        <div class="form-group">
            <label>姓名:</label>
            <p>{{communityDetailInfo.managementContactName || '--'}}</p>
@@ -94,7 +94,7 @@
            <label>夜间电话:</label>
            <p>{{communityDetailInfo.managementContactNightTel || '--'}}</p>
        </div>
        <div class="sub-title">小区经理/负责人</div>
        <div class="sub-title" style="color: #404357;">小区经理/负责人</div>
        <div class="form-group">
            <label>姓名:</label>
            <p>{{communityDetailInfo.managerName || '--'}}</p>
@@ -198,7 +198,7 @@
            <p>{{communityDetailInfo.pumpTotal || '--'}}</p>
            <label>是否有固定的装修垃圾堆放点:</label>
            <div class="radio-group">
                <p>{{communityDetailInfo.hasDecorationRubbishPoint === true ? '有' : '无'}}</p>
                <p>{{communityDetailInfo.hasDecorationRubbishPoint}}</p>
            </div>
            <label>需保安值守出入口(个):</label>
            <p>{{communityDetailInfo.gateGuardTotal || '--'}}</p>
public/pages/common/communityManage/detail/detail.js
@@ -234,7 +234,7 @@
                    gateSupplierContactName: info.barrierSupplierContact || info.gateSupplierContactName || '',
                    gateSupplierContactTel: info.barrierSupplierPhone || info.gateSupplierContactTel || '',
                    pumpTotal: info.waterPumpCount || info.pumpTotal || '',
                    hasDecorationRubbishPoint: info.hasDecorationRubbishPoint || info.hasDecorationRubbishPoint,
                    hasDecorationRubbishPoint: info.hasDecorationRubbishPoint,
                    gateGuardTotal: info.securityEntranceCount || info.gateGuardTotal || '',
                    carTotal: info.totalMotorVehicleSpaces || info.carTotal || '',
                    carGroundTotal: info.groundMotorVehicleSpaces || info.groundParkingSpaces || info.carGroundTotal || '',
public/pages/common/communityManage/edit/edit.html
@@ -12,13 +12,13 @@
        </div>
        <div class="form-group">
            <label>所在城市</label>
            省<select id="province" v-model="selectProv" @change="chooseProvince($event); removeError('province')">
            省<select id="province" name="projectAddressProvince" v-model="selectProv" @change="chooseProvince($event); removeError('province')">
                <option value="">请选择省</option>
            </select>
            市<select id="city" v-model="selectCity" @change="chooseCity($event); removeError('city')">
            市<select id="city" name="projectAddressCity" v-model="selectCity" @change="chooseCity($event); removeError('city')">
                <option value="">请选择市</option>
            </select>
            区<select id="area" v-model="selectArea" @change="chooseArea($event); removeError('area')">
            区<select id="area" name="projectAddressDistrict" v-model="selectArea" @change="chooseArea($event); removeError('area')">
                <option value="">请选择区</option>
            </select>
            <label>详细地址</label>
@@ -238,10 +238,15 @@
            
            <div class="radio-group" style="width: 153px; margin-right: 90px;">
                <label>是否有固定的装修垃圾堆放点</label>
                <label style="margin-left: -40px;"><input type="radio" name="garbage" value=true v-model="formData.hasDecorationRubbishPoint"> 有</label>
                <label style="margin-left: -40px;"><input type="radio" name="garbage" value=false v-model="formData.hasDecorationRubbishPoint"> 无</label>
                <!-- 使用“是 / 否”,与接口字段保持一致 -->
                <label>
                    <input type="radio" name="garbage" value="是" v-model="formData.hasDecorationRubbishPoint"> 有
                </label>
                <label>
                    <input type="radio" name="garbage" value="否" v-model="formData.hasDecorationRubbishPoint"> 无
                </label>
            </div>
            <label>需保安值守出入口(个)</label>
            <label style="margin-left: 100px;">需保安值守出入口(个)</label>
            <input type="text" placeholder="请输入" style="width: 153px;" v-model.number="formData.securityEntranceCount">
        </div>
    </div>
public/pages/common/communityManage/edit/edit.js
@@ -367,7 +367,7 @@
                if (!detail) {
                    return;
                }
                // 处理行政区编码(如310115 -> 省:310000,市:310100,区:310115)
                // 优先使用 cityCode(行政区编码,如310115 -> 省:310000,市:310100,区:310115)
                const areaCode = detail.cityCode || '';
                if (areaCode && areaCode.length >= 6) {
                    const provCode = areaCode.substring(0, 2) + '0000';
@@ -378,8 +378,62 @@
                    // 先加载市,再加载区
                    vc.component._initArea('202', provCode);
                    vc.component._initArea('303', cityCode);
                } else {
                    // 如果没有 cityCode,则根据接口返回的省市区名称匹配下拉选项
                    // 这里地区数据是异步加载的,因此采用重试方式,直到匹配成功或达到最大次数
                    let retry = 0;
                    const maxRetry = 20;
                    const matchAreaByName = function() {
                        const provName = detail.projectAddressProvince || '';
                        const cityName = detail.projectAddressCity || '';
                        const districtName = detail.projectAddressDistrict || '';
                        // 1. 匹配省
                        if (provName && !vc.component.selectProv && vc.component.provs && vc.component.provs.length > 0) {
                            const prov = vc.component.provs.find(p => p.areaName === provName);
                            if (prov) {
                                vc.component.selectProv = prov.areaCode;
                                vc.component.selectProvName = prov.areaName;
                                vc.component.formData.projectAddressProvince = prov.areaName;
                                // 加载市列表
                                vc.component._initArea('202', prov.areaCode);
                            }
                        }
                        // 2. 匹配市
                        if (cityName && vc.component.selectProv && !vc.component.selectCity &&
                            vc.component.citys && vc.component.citys.length > 0) {
                            const city = vc.component.citys.find(c => c.areaName === cityName);
                            if (city) {
                                vc.component.selectCity = city.areaCode;
                                vc.component.selectCityName = city.areaName;
                                vc.component.formData.projectAddressCity = city.areaName;
                                // 加载区列表
                                vc.component._initArea('303', city.areaCode);
                            }
                        }
                        // 3. 匹配区
                        if (districtName && vc.component.selectCity && !vc.component.selectArea &&
                            vc.component.areas && vc.component.areas.length > 0) {
                            const area = vc.component.areas.find(a => a.areaName === districtName);
                            if (area) {
                                vc.component.selectArea = area.areaCode;
                                vc.component.selectAreaName = area.areaName;
                                vc.component.formData.projectAddressDistrict = area.areaName;
                                vc.component.formData.cityCode = area.areaCode;
                            }
                        }
                        // 如果还没有完整匹配到区,并且未超过重试次数,则继续重试
                        if ((!vc.component.selectArea || !vc.component.formData.cityCode) && retry < maxRetry) {
                            retry++;
                            setTimeout(matchAreaByName, 100);
                        }
                    };
                    matchAreaByName();
                }
                // 补齐名称(用于提交)
                // 补齐名称(用于提交,防止接口有值但上面未覆盖)
                vc.component.formData.projectAddressProvince = detail.projectAddressProvince || vc.component.formData.projectAddressProvince;
                vc.component.formData.projectAddressCity = detail.projectAddressCity || vc.component.formData.projectAddressCity;
                vc.component.formData.projectAddressDistrict = detail.projectAddressDistrict || vc.component.formData.projectAddressDistrict;
@@ -399,11 +453,11 @@
                    return fallback;
                };
                return {
                    communityId: info.communityId || info.communityId || '',
                    communityId: info.communityId || '',
                    newBId: info.newBId || '',
                    feePrice: info.feePrice || '',
                    projectAddressProvince: info.projectAddressProvince || info.provinceName || '',
                    projectAddressCity: info.projectAddressCity || info.cityName || '',
                    projectAddressProvince: info.projectAddressProvince || '',
                    projectAddressCity: info.projectAddressCity || '',
                    projectAddressDistrict: info.projectAddressDistrict || info.areaName || '',
                    projectAddressTown: info.projectAddressTown || '',
                    projectAddressRoad: info.projectAddressRoad || '',
@@ -456,7 +510,7 @@
                    groundNonMotorVehicleArea: info.groundNonMotorVehicleArea || info.nonElectricCarGroundArea || '',
                    undergroundNonMotorVehicleArea: info.undergroundNonMotorVehicleArea || info.nonElectricCarUndergroundArea || '',
                    clubhouseArea: info.clubhouseArea || info.clubArea || '',
                    hasDecorationRubbishPoint: toBoolString(info.hasDecorationRubbishPoint, info.garbageFixed ? 'true' : 'false'),
                    hasDecorationRubbishPoint: info.hasDecorationRubbishPoint === '是' || info.garbageFixed == 1 ? '是' : '否',
                    securityEntranceCount: info.securityEntranceCount || info.gateGuardTotal || '',
                    elevatorCount: info.elevatorCount || info.elevatorTotal || '',
                    elevatorType: info.elevatorType || '',
@@ -626,18 +680,19 @@
                        submitData[field] = Number(submitData[field]);
                    }
                });
                // 确保Integer字段为整数类型
                // 确保Integer字段为整数类型(仅用于需要传 0/1 的布尔字段)
                const normalizeBoolToNumber = function(val) {
                    if (val === true || val === 'true' || val === 1 || val === '1') {
                    if (val === true || val === 'true' || val === 1 || val === '1' || val === '是') {
                        return 1;
                    }
                    if (val === false || val === 'false' || val === 0 || val === '0') {
                    if (val === false || val === 'false' || val === 0 || val === '0' || val === '否') {
                        return 0;
                    }
                    return val;
                };
                // 上岗证仍然按 0/1 提交
                submitData.hasManagerCertificate = normalizeBoolToNumber(submitData.hasManagerCertificate);
                submitData.hasDecorationRubbishPoint = normalizeBoolToNumber(submitData.hasDecorationRubbishPoint);
                // hasDecorationRubbishPoint 保持为“是 / 否”,直接随表单提交
                // 提交数据
                vc.http.apiPost(
                    '/community.updateCommunity',
public/pages/property/costDetail/costDetail.html
@@ -1,132 +1,115 @@
<div class="container">
<div class="cost-detail-container">
    <h2>费用明细表</h2>
    <!-- 搜索栏 -->
    <div class="search-bar">
        <div>
            <label>日期</label>
            <input type="datetime-local" value="2023-08-08T12:12:12">
            <label>日期:</label>
            <input type="text" class="form-control queryDate" placeholder="请选择日期" v-model="costDetailInfo.conditions.date" />
        </div>
        <div>
            <label>小区</label>
            <select>
                <option>鱼塘花园A区</option>
            <label>小区:</label>
            <select class="form-control" v-model="costDetailInfo.conditions.communityName" style="text-align: center;line-height: 0px;">
                <option value="">请选择</option>
                <option value="鱼塘花园A区">鱼塘花园A区</option>
            </select>
        </div>
        <div>
            <label>小区编码</label>
            <input type="text" placeholder="请输入">
            <label>小区编码:</label>
            <input type="text" class="form-control" placeholder="请输入" v-model="costDetailInfo.conditions.communityCode" />
        </div>
        <button>查询</button>
        <button>重置</button>
        <div style="margin-left: auto;">
            <button class="add-btn">添加</button>
            <button class="import-btn">费用导入</button>
        <button type="button" class="query-btn" v-on:click="_queryCostDetails()" style="line-height: 0px;">查询</button>
        <button type="button" class="reset-btn" v-on:click="_resetQuery()" style="line-height: 0px;">重置</button>
        <div class="action-buttons">
            <button type="button" class="add-btn" v-on:click="_addCostDetail()" style="line-height: 0px;">
                添加
            </button>
            <button type="button" class="import-btn" v-on:click="_importCostDetail()" style="line-height: 0px;">费用导入</button>
        </div>
    </div>
    <!-- 费用表格 -->
    <table>
        <thead>
            <tr>
            <tr id="costDetailTableHead">
                <th>序号</th>
                <th>流转编码</th>
                <th>小区编码</th>
                <th>小区名称</th>
                <th>日期</th>
                <th>工程内容</th>
                <th>管理处金额(元)</th>
                <th>管理处金额 (元)</th>
                <th>是否盖章</th>
                <th>业委会金额(元)</th>
                <th>审价金额(元)</th>
                <th>业委会金额 (元)</th>
                <th>审价金额 (元)</th>
                <th>是否盖章</th>
                <th>签报部门</th>
                <th>基金类型一级分类</th>
                <th>基金类型二级分类</th>
                <th>基金类型-一级分类</th>
                <th>基金类型-二级分类</th>
                <th>幢/全体</th>
                <th>维修类型</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>1</td>
                <td>118652</td>
                <td>A-15-1-6</td>
                <td>鱼塘花园</td>
                <td>2025-10-10</td>
                <td>路面道牙、墙面大理石</td>
                <td>50000.00</td>
                <td>是</td>
                <td>50000.00</td>
                <td>50000.00</td>
                <td>是</td>
                <td>工程部</td>
                <td>维修基金</td>
                <td>防水</td>
                <td>全体</td>
                <td>道路</td>
                <td><a href="#">更多</a> <a href="#">编辑</a> <a href="#">删除</a></td>
            <tr v-for="(item, index) in costDetailInfo.costDetails">
                <td>{{(costDetailInfo.paginationInfo.currentPage - 1) * costDetailInfo.paginationInfo.rows + index + 1}}</td>
                <td>{{item.flowCode || '-'}}</td>
                <td>{{item.communityCode || '-'}}</td>
                <td>{{item.communityName || '-'}}</td>
                <td>{{item.date || '-'}}</td>
                <td>{{item.projectContent || '-'}}</td>
                <td>{{item.managementAmount || '-'}}</td>
                <td>{{item.managementStamped == '1' ? '是' : '否'}}</td>
                <td>{{item.committeeAmount || '-'}}</td>
                <td>{{item.appraisalAmount || '-'}}</td>
                <td>{{item.committeeStamped == '1' ? '是' : '否'}}</td>
                <td>{{item.approvalDepartment || '-'}}</td>
                <td>{{item.fundTypeLevel1 || '-'}}</td>
                <td>{{item.fundTypeLevel2 || '-'}}</td>
                <td>{{item.buildingType || '-'}}</td>
                <td>{{item.maintenanceType || '-'}}</td>
                <td>
                    <a href="javascript:void(0)" v-on:click="_viewMore(item)">更多</a>
                    <a href="javascript:void(0)" v-on:click="_editCostDetail(item)">编辑</a>
                    <a href="javascript:void(0)" v-on:click="_deleteCostDetail(item)">删除</a>
                </td>
            </tr>
            <tr>
                <td>2</td>
                <td>118407</td>
                <td>A-15-1-5</td>
                <td>鱼塘花园</td>
                <td>2025-10-10</td>
                <td>路面道牙、墙面大理石</td>
                <td>50000.00</td>
                <td>是</td>
                <td>50000.00</td>
                <td>50000.00</td>
                <td>是</td>
                <td>工程部</td>
                <td>维修基金</td>
                <td>房屋维修</td>
                <td>全体</td>
                <td>道路</td>
                <td><a href="#">更多</a> <a href="#">编辑</a> <a href="#">删除</a></td>
            <tr v-if="costDetailInfo.costDetails.length == 0">
                <td colspan="17" style="text-align: center; color: #999;">暂无数据</td>
            </tr>
            <tr>
                <td>3</td>
                <td>118652</td>
                <td>A-15-1-4</td>
                <td>鱼塘花园</td>
                <td>2025-10-10</td>
                <td>路面道牙、墙面大理石</td>
                <td>50000.00</td>
                <td>否</td>
                <td>50000.00</td>
                <td>50000.00</td>
                <td>否</td>
                <td>工程部</td>
                <td>公共收益金</td>
                <td>系统外</td>
                <td>全体</td>
                <td>道路</td>
                <td><a href="#">更多</a> <a href="#">编辑</a> <a href="#">删除</a></td>
            </tr>
            <!-- 可继续添加其他行(示例仅展示前3行) -->
        </tbody>
    </table>
    <!-- 分页栏 -->
    <div class="pagination">
        <span>共100条记录</span>
        <div style="margin-left: auto;">
            <span>45/页</span>
            <button>&lt;</button>
            <button>1</button>
            <button class="active">2</button>
            <button>3</button>
            <button>4</button>
            <button>5</button>
            <span>...</span>
            <button>99</button>
            <button>&gt;</button>
            <span>跳转至</span>
            <input type="text" value="2">
            <span>页</span>
        <span class="pagination-info">共{{costDetailInfo.paginationInfo.dataCount || 0}}条记录</span>
        <div class="pagination-controls">
            <select class="page-size-select" v-model="costDetailInfo.paginationInfo.rows" v-on:change="_changePageSize()">
                <option value="15">15</option>
                <option value="30">30</option>
                <option value="50">50</option>
                <option value="100">100</option>
            </select>
            <span class="page-size-label">/页</span>
            <button class="page-btn" v-on:click="_goToPage(costDetailInfo.paginationInfo.currentPage - 1)"
                    :disabled="costDetailInfo.paginationInfo.currentPage == 1">‹</button>
            <button class="page-btn" v-for="page in costDetailInfo.paginationInfo.pageList"
                    :class="{active: page.currentPage}"
                    v-on:click="_goToPage(page.page)"
                    v-if="page.pageView != '...'">
                {{page.pageView}}
            </button>
            <span v-for="page in costDetailInfo.paginationInfo.pageList"
                  v-if="page.pageView == '...'"
                  class="page-ellipsis">...</span>
            <button class="page-btn" v-on:click="_goToPage(costDetailInfo.paginationInfo.currentPage + 1)"
                    :disabled="costDetailInfo.paginationInfo.currentPage == costDetailInfo.paginationInfo.total">›</button>
            <span class="jump-label">跳转至</span>
            <input type="number" class="jump-input" v-model="costDetailInfo.jumpPage" min="1" :max="costDetailInfo.paginationInfo.total" />
            <span class="page-label">页</span>
            <button class="page-btn" v-on:click="_jumpToPage()">确定</button>
        </div>
    </div>
</div>
</div>
public/pages/property/costDetail/costDetail.js
@@ -0,0 +1,244 @@
/**
 费用明细表
 **/
(function (vc) {
    var DEFAULT_PAGE = 1;
    var DEFAULT_ROWS = 15;
    var $that = {};
    vc.extends({
        data: {
            costDetailInfo: {
                costDetails: [],
                paginationInfo: {
                    currentPage: 1,
                    rows: DEFAULT_ROWS,
                    total: 1,
                    dataCount: 0,
                    pageList: []
                },
                jumpPage: 1,
                conditions: {
                    date: '',
                    communityName: '',
                    communityCode: ''
                }
            }
        },
        _initMethod: function () {
            $that = vc.component;
            $that._injectStyles();
            $that._listCostDetails(DEFAULT_PAGE, DEFAULT_ROWS);
            $that._initDate();
        },
        _initEvent: function () {
            vc.on('costDetail', 'listCostDetail', function (_param) {
                $that._listCostDetails(DEFAULT_PAGE, DEFAULT_ROWS);
            });
        },
        methods: {
            _initDate: function () {
                $(".queryDate").datetimepicker({
                    language: 'zh-CN',
                    fontAwesome: 'fa',
                    format: 'yyyy-mm-dd hh:ii:ss',
                    initTime: true,
                    initialDate: new Date(),
                    autoClose: 1,
                    todayBtn: true
                });
                $('.queryDate').datetimepicker()
                    .on('changeDate', function (ev) {
                        var value = $(".queryDate").val();
                        $that.costDetailInfo.conditions.date = value;
                    });
                //防止多次点击时间插件失去焦点
                var queryDateElements = document.getElementsByClassName('form-control queryDate');
                if (queryDateElements.length > 0) {
                    queryDateElements[0].addEventListener('click', function(e) {
                        e.currentTarget.blur();
                    });
                }
            },
            _listCostDetails: function (_page, _rows) {
                $that.costDetailInfo.conditions.page = _page;
                $that.costDetailInfo.conditions.row = _rows;
                $that.costDetailInfo.conditions.communityId = vc.getCurrentCommunity().communityId;
                var param = {
                    params: $that.costDetailInfo.conditions
                };
                //发送get请求
                vc.http.apiGet('/costDetail/queryCostDetail',
                    param,
                    function (json, res) {
                        var _json = JSON.parse(json);
                        $that.costDetailInfo.paginationInfo.dataCount = _json.total || 0;
                        $that.costDetailInfo.paginationInfo.total = _json.records || 1;
                        $that.costDetailInfo.costDetails = _json.data || [];
                        $that.costDetailInfo.paginationInfo.currentPage = _page;
                        $that._freshPageList();
                    },
                    function (errInfo, error) {
                        console.log('请求失败处理');
                        $that.costDetailInfo.costDetails = [];
                        $that.costDetailInfo.paginationInfo.dataCount = 0;
                        $that.costDetailInfo.paginationInfo.total = 1;
                        $that._freshPageList();
                    }
                );
            },
            _freshPageList: function () {
                var currentPage = $that.costDetailInfo.paginationInfo.currentPage;
                var total = $that.costDetailInfo.paginationInfo.total;
                var pageList = [];
                if (total <= 7) {
                    // 总页数小于等于7,显示所有页码
                    for (var i = 1; i <= total; i++) {
                        pageList.push({
                            page: i,
                            pageView: i,
                            currentPage: i == currentPage
                        });
                    }
                } else {
                    // 总页数大于7,显示部分页码
                    if (currentPage <= 4) {
                        // 当前页在前4页
                        for (var i = 1; i <= 5; i++) {
                            pageList.push({
                                page: i,
                                pageView: i,
                                currentPage: i == currentPage
                            });
                        }
                        pageList.push({
                            page: 0,
                            pageView: '...',
                            currentPage: false
                        });
                        pageList.push({
                            page: total,
                            pageView: total,
                            currentPage: false
                        });
                    } else if (currentPage >= total - 3) {
                        // 当前页在后4页
                        pageList.push({
                            page: 1,
                            pageView: 1,
                            currentPage: false
                        });
                        pageList.push({
                            page: 0,
                            pageView: '...',
                            currentPage: false
                        });
                        for (var i = total - 4; i <= total; i++) {
                            pageList.push({
                                page: i,
                                pageView: i,
                                currentPage: i == currentPage
                            });
                        }
                    } else {
                        // 当前页在中间
                        pageList.push({
                            page: 1,
                            pageView: 1,
                            currentPage: false
                        });
                        pageList.push({
                            page: 0,
                            pageView: '...',
                            currentPage: false
                        });
                        for (var i = currentPage - 1; i <= currentPage + 1; i++) {
                            pageList.push({
                                page: i,
                                pageView: i,
                                currentPage: i == currentPage
                            });
                        }
                        pageList.push({
                            page: 0,
                            pageView: '...',
                            currentPage: false
                        });
                        pageList.push({
                            page: total,
                            pageView: total,
                            currentPage: false
                        });
                    }
                }
                $that.costDetailInfo.paginationInfo.pageList = pageList;
            },
            _queryCostDetails: function () {
                $that._listCostDetails(DEFAULT_PAGE, $that.costDetailInfo.paginationInfo.rows);
            },
            _resetQuery: function () {
                $that.costDetailInfo.conditions.date = '';
                $that.costDetailInfo.conditions.communityName = '';
                $that.costDetailInfo.conditions.communityCode = '';
                $('.queryDate').val('');
                $that._listCostDetails(DEFAULT_PAGE, $that.costDetailInfo.paginationInfo.rows);
            },
            _changePageSize: function () {
                $that._listCostDetails(DEFAULT_PAGE, $that.costDetailInfo.paginationInfo.rows);
            },
            _goToPage: function (_page) {
                if (!_page || _page < 1 || _page > $that.costDetailInfo.paginationInfo.total) {
                    return;
                }
                $that._listCostDetails(_page, $that.costDetailInfo.paginationInfo.rows);
            },
            _jumpToPage: function () {
                var page = parseInt($that.costDetailInfo.jumpPage);
                if (isNaN(page) || page < 1) {
                    page = 1;
                }
                if (page > $that.costDetailInfo.paginationInfo.total) {
                    page = $that.costDetailInfo.paginationInfo.total;
                }
                $that._listCostDetails(page, $that.costDetailInfo.paginationInfo.rows);
            },
            _addCostDetail: function () {
                // 跳转到添加页面或打开添加弹窗
                vc.jumpToPage('/#/pages/property/costDetail/add');
            },
            _importCostDetail: function () {
                // 打开导入弹窗或跳转到导入页面
                vc.toast('费用导入功能');
            },
            _viewMore: function (_item) {
                // 查看详情
                vc.jumpToPage('/#/pages/property/costDetail/detail?costDetailId=' + _item.costDetailId);
            },
            _editCostDetail: function (_item) {
                // 编辑
                vc.jumpToPage('/#/pages/property/costDetail/edit?costDetailId=' + _item.costDetailId);
            },
            _deleteCostDetail: function (_item) {
                vc.confirm('确定要删除这条费用明细吗?', function () {
                    var param = {
                        params: {
                            costDetailId: _item.costDetailId
                        }
                    };
                    vc.http.apiPost('/costDetail/deleteCostDetail',
                        param,
                        function (json, res) {
                            vc.toast('删除成功');
                            $that._listCostDetails($that.costDetailInfo.paginationInfo.currentPage, $that.costDetailInfo.paginationInfo.rows);
                        },
                        function (errInfo, error) {
                            vc.message(errInfo);
                        }
                    );
                });
            }
        }
    });
})(window.vc);