liukangdong
2024-11-29 0527684883bc620febe0a1360f661cc2a7f16e00
Merge branch 'master' of http://139.186.142.91:10010/r/productDev/funingyunwei
已添加10个文件
已修改31个文件
4335 ■■■■ 文件已修改
admin/.env.test 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/api/bill.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/api/company.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/api/contract.js 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/api/customer.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/api/house.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/api/project/ywProject.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/api/ywContractRevenue.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/components/common/MemberSearch/src/index.vue 143 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/contract/components/addCollectionBill.vue 315 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/contract/components/addPaymentBill.vue 297 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/contract/components/config.js 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/contract/components/contractDetail.vue 330 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/contract/components/contractEdit.vue 714 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/contract/components/terminateLease.vue 442 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/contract/contractList.vue 107 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/finance/bull.vue 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/finance/components/bullDetail.vue 203 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/finance/components/bullEdit.vue 331 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/finance/components/bullEditFu.vue 383 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/finance/components/config.js 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/finance/components/flowingWater.vue 286 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/finance/components/selectHouse.vue 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/src/views/finance/payments.vue 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/system_gateway/src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/system_service/src/main/java/com/doumee/config/cloudfilter/LoginHandlerInterceptor.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/system_service/src/main/java/com/doumee/core/utils/DateCompare.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/YwAccountCloudController.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/YwCustomerCloudController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_admin/src/main/resources/application.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/YwContractBill.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/YwContractRevenue.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/YwWorkorder.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/CompanyServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/SmsEmailServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwContractBillServiceImpl.java 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwContractRevenueServiceImpl.java 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwContractRoomServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwContractServiceImpl.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwCustomerServiceImpl.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwWorkorderServiceImpl.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin/.env.test
@@ -4,3 +4,5 @@
# VUE_APP_API_URL  = 'http://192.168.5.13/gateway_interface'
VUE_APP_API_URL  = 'http://192.168.0.162:10010/'
# VUE_APP_API_URL  = 'http://192.168.0.136:10010/'
admin/src/api/bill.js
@@ -11,3 +11,9 @@
export function create (data) {
  return request.post('/visitsAdmin/cloudService/business/ywContractBill/create', data)
}
// è¿ç»´æ”¶æ”¯è´¦å·ä¿¡æ¯è¡¨ -- åˆ—表
export function ywAccountList (data) {
  return request.post('/visitsAdmin/cloudService/business/ywAccount/list', data)
}
admin/src/api/company.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
import request from '@/utils/request'
// æŸ¥è¯¢
export function fetchList (data) {
  return request.post('/visitsAdmin/cloudService/business/ywContractBill/page', data, {
    trim: true
  })
}
// åˆ—表
export function companyList (data) {
  return request.post('/visitsAdmin/cloudService/business/company/list', data)
}
admin/src/api/contract.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
import request from '@/utils/request'
// æŸ¥è¯¢
export function fetchList (data) {
  return request.post('/visitsAdmin/cloudService/business/ywContract/page', data, {
    trim: true
  })
}
// åˆ—表
export function list (data) {
  return request.post('/visitsAdmin/cloudService/business/ywContract/list', data)
}
// åˆ›å»º
export function create (data) {
  return request.post('/visitsAdmin/cloudService/business/ywContract/create', data)
}
// æ ¹æ®å‚数预生成账单信息
export function getBillList (data) {
  return request.post('/visitsAdmin/cloudService/business/ywContract/getBillList', data)
}
// æ ¹æ®ID查询
export function getById (id) {
  return request.get(`/visitsAdmin/cloudService/business/ywContract/${id}`)
}
// é€€ç§Ÿ
export function backRent (data) {
  return request.post('/visitsAdmin/cloudService/business/ywContract/backRent', data)
}
// æ ¹æ®ID查询
export function getYwContractBillById (id) {
  return request.get(`/visitsAdmin/cloudService/business/ywContractBill/${id}`)
}
admin/src/api/customer.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
import request from '@/utils/request'
// æŸ¥è¯¢
export function fetchList (data) {
  return request.post('/visitsAdmin/cloudService/business/ywCustomer/page', data, {
    trim: true
  })
}
// åˆ—表
export function list (data) {
  return request.post('/visitsAdmin/cloudService/business/ywCustomer/list', data)
}
admin/src/api/house.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
import request from '@/utils/request'
// æŸ¥è¯¢
export function fetchList (data) {
  return request.post('/visitsAdmin/cloudService/business/ywContractBill/page', data, {
    trim: true
  })
}
// åˆ—表
export function houseList (data) {
  return request.post('/visitsAdmin/cloudService/business/ywContractRoom/list', data)
}
// åˆ—表
export function getContractRoom (data) {
  return request.post('/visitsAdmin/cloudService/business/ywContractRoom/getContractRoom', data)
}
admin/src/api/project/ywProject.js
@@ -12,6 +12,12 @@
    trim: true
  })
}
// é¡¹ç›®æ ‘
export function tree (data) {
  return request.post('/visitsAdmin/cloudService/business/ywProject/tree', data, {
    trim: true
  })
}
// å¯¼å‡ºExcel
export function exportExcel (data) {
  return request.post('/visitsAdmin/cloudService/business/ywProject/exportExcel', data, {
admin/src/api/ywContractRevenue.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
import request from '@/utils/request'
// æŸ¥è¯¢
export function fetchList (data) {
  return request.post('/visitsAdmin/cloudService/business/ywContractRevenue/page', data, {
    trim: true
  })
}
// åˆ›å»º
export function create (data) {
  return request.post('/visitsAdmin/cloudService/business/ywContractRevenue/create', data)
}
// å…³é—­æµæ°´
export function close (id) {
  return request.get(`/visitsAdmin/cloudService/business/ywContractRevenue/close?id=${id}`)
}
admin/src/components/common/MemberSearch/src/index.vue
@@ -1,23 +1,57 @@
<template>
  <GlobalWindow title="选择客户" width="1000px" @close="close" :visible.sync="isShowMemberList">
  <GlobalWindow title="选择客户" width="80%" :withFooter="false" @close="close" :visible.sync="isShowMemberList">
    <div>
      <div class="df_ac mb20">
        <el-input v-model="modalSearchValue" placeholder="请输入客户名称" class="w400" @keyup.enter.native="queryList">
          <!-- <el-button slot="append" icon="el-icon-search" @click="queryList()" /> -->
        </el-input>
        <el-button class="ml10" type="primary" @click="queryList()">查询</el-button>
        <el-button class="ml10" @click="clear()">重置</el-button>
      </div>
      <el-table ref="table" v-loading="listLoading" :data="list" element-loading-text="Loading" border fit
        :header-row-class-name="'table-header'" class="doumee-element-table doumee-element-tableb"
        @row-click="rowClick">
        <el-table-column align="center" label="客户类型" prop="cardName" show-overflow-tooltip min-width="80" />
        <el-table-column align="center" label="客户名称" show-overflow-tooltip prop="remainingMoney" min-width="80" />
        <el-table-column align="center" label="联系人" show-overflow-tooltip prop="remainingGiveMoney" min-width="80" />
        <el-table-column label="联系电话" prop="createTime" min-width="100" align="center" />
        <el-table-column label="统一信用代码" prop="createTime" min-width="120" align="center" />
        <el-table-column label="营业期限" prop="createTime" min-width="100" align="center" />
        <el-table-column label="默认发票类型" prop="createTime" min-width="100" align="center" />
        <el-table-column align="center" label="客户类型" show-overflow-tooltip min-width="80">
          <template slot-scope="{row}">
            <span v-if="row.type === 0">个人</span>
            <span v-if="row.type === 1">企业</span>
          </template>
        </el-table-column>
        <el-table-column align="center" label="客户名称" show-overflow-tooltip prop="name" min-width="80" />
        <el-table-column align="center" label="联系人" show-overflow-tooltip prop="memberName" min-width="80" />
        <el-table-column label="联系电话" prop="memberPhone" min-width="100" align="center" />
        <el-table-column label="统一信用代码" prop="creditCard" min-width="120" align="center">
          <template slot-scope="{row}">
            <div v-if="row.type === 1">
              <span v-if="row.fpType === 0">增值税普通发票</span>
              <span v-else-if="row.fpType === 1">增值税专用发票</span>
              <span v-else>-</span>
            </div>
            <div v-else>-</div>
          </template>
        </el-table-column>
        <el-table-column label="营业期限" prop="validity" min-width="100" align="center">
          <template slot-scope="{row}">
            <div v-if="row.type === 1">
              <span>{{row.validity || '-'}}</span>
            </div>
            <div v-else>-</div>
          </template>
        </el-table-column>
        <el-table-column label="默认发票类型" min-width="100" align="center">
          <template slot-scope="{row}">
            <div v-if="row.type === 1">
              <span v-if="row.fpType === 0">增值税普通发票</span>
              <span v-else-if="row.fpType === 1">增值税专用发票</span>
              <span v-else>-</span>
            </div>
            <div v-else>-</div>
          </template>
        </el-table-column>
        <el-table-column label="操作" min-width="100" align="center">
          <template slot-scope="{row}">
            <span class="primaryColor cu" @click="selectItem(row)">选择</span>
          </template>
        </el-table-column>
      </el-table>
      <Pagination @size-change="handleSizeChange" @current-change="getList" :pagination="pagination" />
    </div>
@@ -25,11 +59,8 @@
</template>
<script>
import { memberList, memberDetailInfo } from '@/api'
import { fetchList } from '@/api/customer'
import GlobalWindow from '@/components/common/GlobalWindow'
import dayjs from 'dayjs'
// import { debounce } from '@/utils/debounce'
import Pagination from '@/components/common/Pagination'
export default {
  components: {
@@ -40,104 +71,70 @@
    isShowChooseBtn: {
      type: Boolean,
      default: () => true
    },
    type: { // (10: å•†å“æŠ˜æ‰£  20: è®¢åœºæŠ˜æ‰£ 30: é—¨ç¥¨æŠ˜æ‰£ 40: å¥—餐折扣 50:活动折扣 60:课程折扣)
      type: String,
      default: 'default'
    }
  },
  data() {
  data () {
    return {
      searchValue: '',
      isShowMemberList: false,
      modalSearchValue: '',
      list: [],
      totalCount: 0,
      pagination: {
        pageSize: 10,
        page: 1,
        total: 0
      },
      listLoading: false,
      listLoading: false
    }
  },
  created() {
    // (10: å•†å“æŠ˜æ‰£  20: è®¢åœºæŠ˜æ‰£ 30: é—¨ç¥¨æŠ˜æ‰£ 40: å¥—餐折扣 50:活动折扣 60:课程折扣)
  },
  methods: {
    clearSearch() {
      this.searchValue = ''
    open () {
      this.modalSearchValue = ''
      this.filters = {}
      this.pagination.page = 1
      this.pagination.pageSize = 10
      this.isShowMemberList = true
      this.getList()
    },
    handleMemberSelect(item) {
      memberDetailInfo({ param: { memberId: item.id } }).then((res) => {
        if (res.errorCode !== '000000') return
        const obj = res.record || {}
        obj.searchValue = this.searchValue
        this.$emit('select', obj)
      })
    },
    clear() {
      this.searchValue = ''
      setTimeout(() => {
        this.$refs.searchValueRef.focus()
      })
      this.$emit('clear')
    },
    rowClick(item) {
      memberDetailInfo({ param: { memberId: item.id } }).then((res) => {
        if (res.errorCode !== '000000') return
        const obj = res.record || {}
        this.searchValue = obj.nickName
        obj.searchValue = this.modalSearchValue
        if (item.phone) {
          this.searchValue += '-' + item.phone
        }
        if (item.number) {
          this.searchValue += '(' + item.number + ')'
        }
        this.$emit('select', obj)
      })
      this.isShowMemberList = false
    },
    getList() {
    getList () {
      const { pagination, modalSearchValue } = this
      this.listLoading = true
      memberList({ pagination, param: { keyword: modalSearchValue } }).then((res) => {
      fetchList({
        capacity: pagination.pageSize,
        page: pagination.page,
        model: {
          name: modalSearchValue
        }
      }).then((res) => {
        this.listLoading = false
        if (res.errorCode !== '000000') return
        this.list = res.recordList
        this.list = res.records
        this.pagination.total = res.total || 0
        this.totalCount = res.totalCount
      }, () => {
        this.listLoading = false
      })
    },
    openModal() {
      this.modalSearchValue = ''
      // this.queryList()
      this.isShowMemberList = true
    selectItem (row) {
      this.$emit('select', row)
      this.isShowMemberList = false
    },
    queryList() {
    queryList () {
      this.pagination.page = 1
      this.getList()
    },
    currentChange(val) {
    currentChange (val) {
      this.pagination.page = val
      this.getList()
    },
    clear() {
    clear () {
      this.filters = {}
      this.pagination.pageSize = 10
      this.pagination.page = 1
      this.getList()
    },
    handleSizeChange(capacity) {
    handleSizeChange (capacity) {
      this.pagination.pageSize = capacity
      this.getList()
    },
    close() {
    close () {
      this.isShowMemberList = false
    }
  }
admin/src/views/contract/components/addCollectionBill.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,315 @@
<template>
    <GlobalWindow
        width="100%"
        :title="title"
        :visible.sync="visible"
        :confirm-working="isWorking"
        @close="close"
        @confirm="confirm">
        <div class="main">
            <div class="main_content">
                <el-form :model="form" label-position="top" ref="form" :rules="rules">
                    <div class="head">
                        <div class="m_title">基础信息</div>
                        <div class="tabs">
                            <div class="tab" :class="{ active: form.feeType === 0 }" @click="timeTabClick(0)">周期费用</div>
                            <div class="tab" :class="{ active: form.feeType === 1 }" @click="timeTabClick(1)">一次性费用</div>
                        </div>
                    </div>
                    <div class="list">
                        <el-form-item label="关联合同" prop="contractCode">
                            <el-input v-model="form.contractCode" disabled placeholder="请输入应收金额" v-trim />
                        </el-form-item>
                        <el-form-item label="付款方" prop="renterName">
                            <el-input v-model="form.renterName" disabled placeholder="请输入应收金额" v-trim />
                        </el-form-item>
                        <el-form-item label="费用类型" prop="costType">
                            <el-select v-model="form.costType" placeholder="请选择">
                                <el-option :value="0" label="租赁费"></el-option>
                                <el-option :value="1" label="物业费"></el-option>
                                <el-option :value="4" label="水电费"></el-option>
                                <el-option :value="5" label="杂项费"></el-option>
                                <el-option :value="6" label="其他"></el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="计费周期" prop="date" v-if="form.feeType !== 1">
                            <el-date-picker
                                type="daterange"
                                range-separator="至"
                                v-model="form.date"
                                @change="changeDate"
                                start-placeholder="开始日期"
                                end-placeholder="结束日期"
                                value-format="yyyy-MM-dd"
                                placeholder="请选择" />
                        </el-form-item>
                        <el-form-item label="应收金额" prop="receivableFee">
                            <el-input v-model="form.receivableFee" placeholder="请输入应收金额" v-trim />
                        </el-form-item>
                        <el-form-item label="应收日期" prop="planPayDate">
                            <el-date-picker type="date" v-model="form.planPayDate" value-format="yyyy-MM-dd" placeholder="请选择" />
                        </el-form-item>
                        <el-form-item label="所属公司" prop="companyId">
                            <el-select v-model="form.companyId" placeholder="请选择" clearable>
                                <el-option
                                    v-for="(item, index) in comparyList"
                                    :key="index"
                                    :value="item.id"
                                    :label="item.name" />
                            </el-select>
                        </el-form-item>
                        <el-form-item style="width: 100%;" label="账单备注" prop="remark">
                            <el-input type="textarea" :rows="5" v-model="form.remark" placeholder="请输入" />
                        </el-form-item>
                    </div>
                </el-form>
            </div>
        </div>
    </GlobalWindow>
</template>
<script>
  import GlobalWindow from '@/components/common/GlobalWindow'
  import BaseOpera from '@/components/base/BaseOpera'
  import { companyList } from '@/api/company'
  import { mapState } from 'vuex'
  export default {
    name: 'addCollectionBill',
    components: {
      GlobalWindow
    },
    computed: {
      ...mapState(['userInfo'])
    },
    extends: BaseOpera,
    data () {
      const validateArr = (rule, value, callback) => {
        if (value.length === 0 || !value) {
          callback(new Error('请选择'));
        } else {
          callback();
        }
      };
      return {
        form: {
          contractCode: '',
          contractId: '',
          costType: '',
          renterName: '',
          renterId: '',
          remark: '',
          startDate: '',
          endDate: '',
          price: 0,
          receivableFeeCopy: '',
          receivableFee: '',
          feeType: 0,
          planPayDate: '',
          billType: 0,
          billTypeCopy: 0,
          date: []
        },
        rules: {
          contractCode: [
            { required: true, message: '请输入', trigger: 'blur' }
          ],
          renterName: [
            { required: true, message: '请输入', trigger: 'blur' }
          ],
          costType: [
            { required: true, message: '请选择', trigger: 'blur' }
          ],
          date: [
            { validator: validateArr, trigger: 'blur' }
          ],
          receivableFee: [
            { required: true, message: '请输入', trigger: 'blur' }
          ],
          planPayDate: [
            { required: true, message: '请选择', trigger: 'blur' }
          ],
          companyId: [
            { required: true, message: '请选择', trigger: 'blur' }
          ]
        },
        comparyList: []
      }
    },
    methods: {
      open (title, target) {
        this.title = title
        this.getCompany()
        this.visible = true
        // æ–°å»º
        if (target == null) {
          this.$nextTick(() => {
            this.$refs.form.resetFields()
            this.form[this.configData['field.id']] = null
          })
          return
        }
        // ç¼–辑
        this.$nextTick(() => {
          for (const key in this.form) {
            this.form[key] = target[key]
          }
        })
      },
      getCompany () {
        companyList({ type: 2 })
          .then(res => {
            this.comparyList = res
          })
      },
      timeTabClick (val) {
        this.form.feeType = val
        if (val === 1) {
          this.form.startDate = ''
          this.form.endDate = ''
          this.date = []
        }
      },
      changeDate (e) {
        if (!e || e.length === 0) {
          this.form.startDate = ''
          this.form.endDate = ''
        } else {
          this.form.startDate = e[0]
          this.form.endDate = e[1]
        }
      },
      confirm () {
        this.$refs.form.validate((valid) => {
          if (!valid) return
          let obj = JSON.parse(JSON.stringify(this.form))
          obj.receivableFeeCopy = Number(obj.receivableFee)
          if (obj.feeType === 0) {
            obj.startDate = obj.startDate + ' 00:00:00'
            obj.endDate = obj.endDate + ' 00:00:00'
          } else {
            obj.startDate = ''
            obj.endDate = ''
          }
          obj.price = Number(obj.receivableFee)
          obj.rowType = 1
          obj.actReceivableFee = 0
          this.$emit('getVal', obj)
          this.visible = false
        })
      },
      close () {
        this.$emit('close')
      }
    }
  }
</script>
<style lang="scss" scoped>
    @import '@/assets/style/variables.scss';
    .cost_tabs {
        justify-content: flex-start;
        border: none;
        .tab {
            height: 36px;
            line-height: 36px;
            font-size: 14px;
        }
    }
    .main {
        display: flex;
        margin-bottom: 20px;
        .main_content {
            flex: 1;
            margin-right: 20px;
            .head {
                display: flex;
                align-items: center;
                justify-content: space-between;
                .tabs {
                    display: flex;
                    margin-bottom: 20px;
                    align-items: center;
                    justify-content: center;
                    .tab {
                        height: 14px;
                        line-height: 14px;
                        cursor: pointer;
                        border: 1px solid #ebebeb;
                        padding: 12px 24px;
                    }
                    .active {
                        font-weight: 500;
                        color: $primary-color;
                        border: 1px solid $primary-color;
                    }
                }
            }
            .list {
                display: flex;
                flex-wrap: wrap;
                .el-form-item {
                    width: 33.33%;
                    box-sizing: border-box;
                    padding: 0 12px;
                }
            }
        }
        .main_house {
            width: 320px;
            padding: 24px 12px;
            border: 1px solid #c3c6cd;
            border-radius: 2px;
            .title {
                font-size: 16px;
                font-weight: 500;
                margin-bottom: 30px;
            }
        }
    }
    .total {
        display: flex;
        justify-content: space-between;
        align-items: center;
        height: 32px;
        background-color: #e7e9f5;
        span {
            width: 160px;
            text-align: center;
        }
    }
    .file_wrap {
        padding: 20px 16px;
        border: 1px solid #c3c6cd;
        border-radius: 2px;
        .head {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
    }
    .m_title {
        font-weight: 500;
        font-size: 14px;
        margin-bottom: 15px;
        margin-top: 10px;
    }
</style>
admin/src/views/contract/components/addPaymentBill.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,297 @@
<template>
    <GlobalWindow
        width="100%"
        :title="title"
        :visible.sync="visible"
        :confirm-working="isWorking"
        @close="close"
        @confirm="confirm">
        <div class="main">
            <div class="main_content">
                <el-form :model="form" label-position="top" ref="form" :rules="rules">
                    <div class="head">
                        <div class="m_title">基础信息</div>
                    </div>
                    <div class="list">
                        <el-form-item label="关联合同" prop="contractCode">
                            <el-input v-model="form.contractCode" disabled placeholder="请输入" v-trim />
                        </el-form-item>
                        <el-form-item label="收款方" prop="customerName">
                            <el-input v-model="form.renterName" disabled placeholder="请输入" v-trim />
                        </el-form-item>
                        <el-form-item label="费用类型" prop="costType">
                            <el-select v-model="form.costType" placeholder="请选择">
                                <el-option :value="0" label="租赁费"></el-option>
                                <el-option :value="1" label="物业费"></el-option>
                                <el-option :value="4" label="水电费"></el-option>
                                <el-option :value="5" label="杂项费"></el-option>
                                <el-option :value="6" label="其他"></el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="计费周期" prop="date">
                            <el-date-picker
                                type="daterange"
                                range-separator="至"
                                v-model="form.date"
                                @change="changeDate"
                                start-placeholder="开始日期"
                                end-placeholder="结束日期"
                                value-format="yyyy-MM-dd"
                                placeholder="请选择" />
                        </el-form-item>
                        <el-form-item label="应付金额" prop="receivableFee">
                            <el-input v-model="form.receivableFee" placeholder="请输入应收金额" v-trim />
                        </el-form-item>
                        <el-form-item label="应付日期" prop="planPayDate">
                            <el-date-picker type="date" v-model="form.planPayDate" value-format="yyyy-MM-dd" placeholder="请选择" />
                        </el-form-item>
                        <el-form-item label="所属公司" prop="companyId">
                            <el-select v-model="form.companyId" placeholder="请选择" clearable>
                                <el-option
                                    v-for="(item, index) in comparyList"
                                    :key="index"
                                    :value="item.id"
                                    :label="item.name" />
                            </el-select>
                        </el-form-item>
                        <el-form-item style="width: 100%;" label="账单备注" prop="remark">
                            <el-input type="textarea" :rows="5" v-model="form.remark" placeholder="请输入" />
                        </el-form-item>
                    </div>
                </el-form>
            </div>
        </div>
    </GlobalWindow>
</template>
<script>
  import GlobalWindow from '@/components/common/GlobalWindow'
  import BaseOpera from '@/components/base/BaseOpera'
  import { companyList } from '@/api/company'
  import { mapState } from 'vuex'
  export default {
    name: 'addPaymentBill',
    components: {
      GlobalWindow
    },
    computed: {
      ...mapState(['userInfo'])
    },
    extends: BaseOpera,
    data () {
      const validateArr = (rule, value, callback) => {
        if (value.length === 0 || !value) {
          callback(new Error('请选择'));
        } else {
          callback();
        }
      };
      return {
        form: {
          contractCode: '',
          contractId: '',
          costType: '',
          renterName: '',
          renterId: '',
          remark: '',
          startDate: '',
          endDate: '',
          price: 0,
          receivableFeeCopy: '',
          receivableFee: '',
          planPayDate: '',
          billType: 1,
          billTypeCopy: 1,
          date: []
        },
        rules: {
          contractCode: [
            { required: true, message: '请输入', trigger: 'blur' }
          ],
          renterName: [
            { required: true, message: '请输入', trigger: 'blur' }
          ],
          costType: [
            { required: true, message: '请选择', trigger: 'blur' }
          ],
          date: [
            { validator: validateArr, trigger: 'blur' }
          ],
          receivableFee: [
            { required: true, message: '请输入', trigger: 'blur' }
          ],
          planPayDate: [
            { required: true, message: '请选择', trigger: 'blur' }
          ],
          companyId: [
            { required: true, message: '请选择', trigger: 'blur' }
          ]
        },
        comparyList: []
      }
    },
    methods: {
      open (title, target) {
        this.title = title
        this.getCompanyList()
        this.visible = true
        // æ–°å»º
        if (target == null) {
          this.$nextTick(() => {
            this.$refs.form.resetFields()
            this.form[this.configData['field.id']] = null
          })
          return
        }
        // ç¼–辑
        this.$nextTick(() => {
          for (const key in this.form) {
            this.form[key] = target[key]
          }
        })
      },
      getCompanyList () {
        companyList({ type: 2 })
          .then(res => {
            this.comparyList = res
          })
      },
      changeDate (e) {
        if (!e || e.length === 0) {
          this.form.startDate = ''
          this.form.endDate = ''
        } else {
          this.form.startDate = e[0]
          this.form.endDate = e[1]
        }
      },
      confirm () {
        this.$refs.form.validate((valid) => {
          if (!valid) return
          let obj = JSON.parse(JSON.stringify(this.form))
          obj.receivableFeeCopy = Number(obj.receivableFee)
          obj.startDate = obj.startDate + ' 00:00:00'
          obj.endDate = obj.endDate + ' 00:00:00'
          obj.price = Number(obj.receivableFee)
          obj.rowType = 1
          obj.actReceivableFee = 0
          this.$emit('getVal', obj)
          this.visible = false
        })
      },
      close () {
        this.$emit('close')
      }
    }
  }
</script>
<style lang="scss" scoped>
    @import '@/assets/style/variables.scss';
    .cost_tabs {
        justify-content: flex-start;
        border: none;
        .tab {
            height: 36px;
            line-height: 36px;
            font-size: 14px;
        }
    }
    .main {
        display: flex;
        margin-bottom: 20px;
        .main_content {
            flex: 1;
            margin-right: 20px;
            .head {
                display: flex;
                align-items: center;
                justify-content: space-between;
                .tabs {
                    display: flex;
                    margin-bottom: 20px;
                    align-items: center;
                    justify-content: center;
                    .tab {
                        height: 14px;
                        line-height: 14px;
                        cursor: pointer;
                        border: 1px solid #ebebeb;
                        padding: 12px 24px;
                    }
                    .active {
                        font-weight: 500;
                        color: $primary-color;
                        border: 1px solid $primary-color;
                    }
                }
            }
            .list {
                display: flex;
                flex-wrap: wrap;
                .el-form-item {
                    width: 33.33%;
                    box-sizing: border-box;
                    padding: 0 12px;
                }
            }
        }
        .main_house {
            width: 320px;
            padding: 24px 12px;
            border: 1px solid #c3c6cd;
            border-radius: 2px;
            .title {
                font-size: 16px;
                font-weight: 500;
                margin-bottom: 30px;
            }
        }
    }
    .total {
        display: flex;
        justify-content: space-between;
        align-items: center;
        height: 32px;
        background-color: #e7e9f5;
        span {
            width: 160px;
            text-align: center;
        }
    }
    .file_wrap {
        padding: 20px 16px;
        border: 1px solid #c3c6cd;
        border-radius: 2px;
        .head {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
    }
    .m_title {
        font-weight: 500;
        font-size: 14px;
        margin-bottom: 15px;
        margin-top: 10px;
    }
</style>
admin/src/views/contract/components/config.js
@@ -1,3 +1,19 @@
export const rules = {
  name: [{ required: true, message: '请输入' }]
}
  type: [{ required: true, message: '请选择' }],
  code: [{ required: true, message: '请输入' }],
  userId: [{ required: true, message: '请选择' }],
  signDate: [{ required: true, message: '请选择' }],
  startDate: [{ required: true, message: '请选择' }],
  endDate: [{ required: true, message: '请选择' }],
  projectId: [{ required: true, message: '请选择' }],
  roundedUp: [{ required: true, message: '请选择' }],
  companyId: [{ required: true, message: '请选择' }],
  renterName: [{ required: true, message: '请选择' }],
  memberName: [{ required: true, message: '请选择' }],
  zlDeposit: [{ required: true, message: '请输入' }],
  zlPayType: [{ required: true, message: '请选择' }],
  zlDate: [{ required: true, message: '请选择' }],
  wyDeposit: [{ required: true, message: '请输入' }],
  wyPayType: [{ required: true, message: '请选择' }],
  wyDate: [{ required: true, message: '请选择' }]
}
admin/src/views/contract/components/contractDetail.vue
@@ -1,140 +1,362 @@
<template>
  <GlobalWindow :title="title" :visible.sync="visible" :confirm-working="isWorking" @close="close"
  <GlobalWindow
    :title="title"
    :visible.sync="visible"
    :confirm-working="isWorking"
    @close="close"
    @confirm="confirm">
    <div class="home_title">
    <div class="home_title" v-if="info">
      <div class="left">
        <span class="mr10">单位名称:xxx</span>
        <span class="status">status</span>
        <span class="mr10">单位名称:{{info.renterName}}</span>
        <el-tag type="success" v-if="info.status === 0">待执行</el-tag>
        <el-tag type="success" v-if="info.status === 1">执行中</el-tag>
        <el-tag type="success" v-if="info.status === 2">已到期</el-tag>
        <el-tag type="success" v-if="info.status === 3">已退租</el-tag>
      </div>
      <el-button plain type="danger">退租</el-button>
      <el-button plain type="danger" v-if="[0, 1, 2].includes(info.status)" @click="refund">退租</el-button>
    </div>
    <div class="remark">合同摘要:xxxx</div>
    <div class="remark" v-if="info">{{info.remark}}</div>
    <div class="tabs">
      <div class="tab" :class="{ active: activeTabs == 0 }" @click="tabsClick(0)">合同信息</div>
      <div class="tab" :class="{ active: activeTabs == 1 }" @click="tabsClick(1)">关联账单</div>
      <div class="tab" :class="{ active: activeTabs == 2 }" @click="tabsClick(2)">操作记录</div>
      <div class="tab" :class="{ active: activeTabs === 0 }" @click="tabsClick(0)">合同信息</div>
      <div class="tab" :class="{ active: activeTabs === 1 }" @click="tabsClick(1)">关联账单</div>
      <div class="tab" :class="{ active: activeTabs === 2 }" @click="tabsClick(2)">操作记录</div>
    </div>
    <div class="main">
    <div class="main" v-if="activeTabs === 0 && info">
      <div class="title">基础信息</div>
      <div class="list">
        <div class="item">
          <div class="la">合同编号</div>
          <div class="val">{{ info.aaa }}</div>
          <div class="val">{{ info.code }}</div>
        </div>
        <div class="item">
          <div class="la">经办人</div>
          <div class="val">{{ info.aaa }}</div>
          <div class="val">{{ info.userName }}</div>
        </div>
        <div class="item">
          <div class="la">创建人</div>
          <div class="val">{{ info.aaa }}</div>
          <div class="val">{{ info.creatorName }}</div>
        </div>
        <div class="item">
          <div class="la">合同租赁数</div>
          <div class="val">{{ info.aaa }}</div>
          <div class="val">{{ info.totalArea }}</div>
        </div>
        <div class="item">
          <div class="la">所属公司</div>
          <div class="val">{{ info.aaa }}</div>
          <div class="val">{{ info.companyName }}</div>
        </div>
        <div class="item">
          <div class="la">签订日期</div>
          <div class="val">{{ info.aaa }}</div>
          <div class="val">{{ info.signDate }}</div>
        </div>
        <div class="item">
          <div class="la">开始日期</div>
          <div class="val">{{ info.aaa }}</div>
          <div class="val">{{ info.startDate }}</div>
        </div>
        <div class="item">
          <div class="la">结束日期</div>
          <div class="val">{{ info.aaa }}</div>
          <div class="val">{{ info.endDate }}</div>
        </div>
        <div class="item">
          <div class="la">所属项目</div>
          <div class="val">{{ info.aaa }}</div>
          <div class="val">{{ info.projectName }}</div>
        </div>
        <div class="item">
          <div class="la">结果取整(四舍五入)</div>
          <div class="val">{{ info.aaa }}</div>
          <div class="val">{{ info.roundedUp === 1 ? '是' : '否' }}</div>
        </div>
      </div>
      <div class="title">房源信息</div>
      <div class="list">
        <div class="item">
          <div class="la">项目名称</div>
          <div class="val">{{ info.aaa }}</div>
        </div>
        <div class="item">
          <div class="la">楼宇名称</div>
          <div class="val">{{ info.aaa }}</div>
        </div>
        <div class="item">
          <div class="la">楼层/房号</div>
          <div class="val">{{ info.aaa }}</div>
        </div>
        <div class="item">
          <div class="la">面积</div>
          <div class="val">{{ info.aaa }}</div>
        </div>
        <el-table :data="info.roomList" stripe>
          <el-table-column prop="projectName" label="项目名称" show-overflow-tooltip />
          <el-table-column prop="buildingName" label="楼宇名称" show-overflow-tooltip />
          <el-table-column prop="" label="楼层/房号" show-overflow-tooltip>
            <template slot-scope="{row}">
              {{row.floorName}}/{{row.code}}
            </template>
          </el-table-column>
          <el-table-column prop="area" label="面积" show-overflow-tooltip>
            <template slot-scope="{row}">
              {{row.area}}㎡
            </template>
          </el-table-column>
        </el-table>
      </div>
      <div class="title">租客信息</div>
      <div class="list">
        <div class="item">
          <div class="la">租客</div>
          <div class="val">{{ info.aaa }}</div>
          <div class="val">{{ info.renterName }}</div>
        </div>
        <div class="item">
          <div class="la">经办人</div>
          <div class="val">{{ info.aaa }}</div>
          <div class="val">{{ info.userName }}</div>
        </div>
      </div>
      <div class="title">租赁条款</div>
      <div class="list">
      <div class="title" v-if="info.type === 2 || info.type === 0">租赁条款</div>
      <div class="list" style="background: #F7F7F7; padding: 15px 20px;" v-if="info.type === 2 || info.type === 0">
        <div class="item">
          <div class="la">押金金额</div>
          <div class="val">{{ info.aaa }}</div>
          <div class="val">{{ info.zlDeposit }}</div>
        </div>
        <div class="item">
          <div class="la">付款方式</div>
          <div class="val">{{ info.aaa }}</div>
          <div class="val" v-if="info.zlPayType === 0">一次性付款</div>
          <div class="val" v-if="info.zlPayType === 1">每三个月一付</div>
          <div class="val" v-if="info.zlPayType === 2">六个月一付</div>
          <div class="val" v-if="info.zlPayType === 3">一年一付</div>
        </div>
        <div class="item">
          <div class="la">免租期</div>
          <div class="val">{{ info.aaa }}</div>
          <div class="val">{{ info.zlFreeStartDate }} ~ {{ info.zlFreeEndDate }}</div>
        </div>
      </div>
      <el-table :data="info.list" stripe>
        <el-table-column prop="" label="开始日期" min-width="100" show-overflow-tooltip />
        <el-table-column prop="" label="结束日期" min-width="100" show-overflow-tooltip />
        <el-table-column prop="" label="合同单价" min-width="100" show-overflow-tooltip />
        <el-table-column prop="" label="付款提前天数" min-width="100" show-overflow-tooltip />
      <el-table :data="info.zlDetailList" stripe style="margin-bottom: 20px;" v-if="info.type === 2 || info.type === 0">
        <el-table-column prop="startDate" label="开始日期" min-width="100" show-overflow-tooltip />
        <el-table-column prop="endDate" label="结束日期" min-width="100" show-overflow-tooltip />
        <el-table-column prop="price" label="合同单价" min-width="100" show-overflow-tooltip />
        <el-table-column prop="advanceDays" label="付款提前天数" min-width="100" show-overflow-tooltip />
      </el-table>
      <div class="title" v-if="info.type === 1 || info.type === 0">物业费条款</div>
      <div class="list" style="background: #F7F7F7; padding: 15px 20px;" v-if="info.type === 1 || info.type === 0">
        <div class="item">
          <div class="la">押金金额</div>
          <div class="val">{{ info.wyDeposit }}</div>
        </div>
        <div class="item">
          <div class="la">付款方式</div>
          <div class="val" v-if="info.wyPayType === 0">一次性付款</div>
          <div class="val" v-if="info.wyPayType === 1">每三个月一付</div>
          <div class="val" v-if="info.wyPayType === 2">六个月一付</div>
          <div class="val" v-if="info.wyPayType === 3">一年一付</div>
        </div>
        <div class="item">
          <div class="la">免租期</div>
          <div class="val">{{ info.wyFreeStartDate }} ~ {{ info.wyFreeEndDate }}</div>
        </div>
      </div>
      <el-table :data="info.wyDetailList" stripe style="margin-bottom: 20px;" v-if="info.type === 1 || info.type === 0">
        <el-table-column prop="startDate" label="开始日期" min-width="100" show-overflow-tooltip />
        <el-table-column prop="endDate" label="结束日期" min-width="100" show-overflow-tooltip />
        <el-table-column prop="price" label="合同单价" min-width="100" show-overflow-tooltip />
        <el-table-column prop="advanceDays" label="付款提前天数" min-width="100" show-overflow-tooltip />
      </el-table>
      <div class="title">合同附件</div>
      <div class="list">
        <el-table :data="info.fileList" stripe>
          <el-table-column prop="name" label="附件名称" show-overflow-tooltip />
          <el-table-column prop="userName" label="操作人" show-overflow-tooltip />
          <el-table-column prop="createDate" label="操作时间" show-overflow-tooltip />
        </el-table>
      </div>
    </div>
    <div class="main" v-if="activeTabs === 1 && info">
      <el-radio-group v-model="type" @change="changeType" style="margin-bottom: 20px;">
        <el-radio-button :label="0">收款账单</el-radio-button>
        <el-radio-button :label="1">付款账单</el-radio-button>
      </el-radio-group>
      <el-table
        :data="tableData"
        border
        v-loading="loading"
        style="width: 100%">
        <el-table-column
          label="费用类型">
          <template slot-scope="{row}">
            <span v-if="row.costType === 0">租赁费</span>
            <span v-if="row.costType === 1">物业费</span>
            <span v-if="row.costType === 2">租赁押金</span>
            <span v-if="row.costType === 3">物业押金</span>
            <span v-if="row.costType === 4">水电费</span>
            <span v-if="row.costType === 5">杂项费</span>
            <span v-if="row.costType === 6">其他</span>
            <span v-if="row.costType === 7">保证金</span>
          </template>
        </el-table-column>
        <el-table-column
          prop="totleFee"
          label="账单金额">
        </el-table-column>
        <el-table-column
          prop="receivableFee"
          label="应收金额">
        </el-table-column>
        <el-table-column
          prop="actReceivableFee"
          label="实收金额">
        </el-table-column>
        <el-table-column
          prop="needReceivableFee"
          label="需收金额">
        </el-table-column>
        <el-table-column
          label="账单来源">
          <template slot-scope="{row}">
            <span v-if="row.type === 0">合同账单</span>
            <span v-if="row.type === 1">自建账单</span>
          </template>
        </el-table-column>
        <el-table-column
          label="计费周期">
          <template slot-scope="{row}">
            {{ row.startDate }} ~ {{ row.endDate }}
          </template>
        </el-table-column>
        <el-table-column
          prop="planPayDate"
          label="应收日期">
        </el-table-column>
        <el-table-column
          label="是否逾期">
          <template slot-scope="{row}">
            <span v-if="row.isOverdue === 0">否</span>
            <span v-if="row.isOverdue === 1">是</span>
          </template>
        </el-table-column>
        <el-table-column
          fixed="right"
          label="状态">
          <template slot-scope="{row}">
            <span v-if="row.payStatus === 0">待收款</span>
            <span v-if="row.payStatus === 1">已结清</span>
            <span v-if="row.payStatus === 2">部分结清</span>
            <span v-if="row.payStatus === 3">待付款</span>
            <span v-if="row.payStatus === 4">待退款</span>
            <span v-if="row.payStatus === 5">已关闭</span>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="page"
        :page-sizes="[10, 15, 20, 25]"
        :page-size="pageSize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total">
      </el-pagination>
    </div>
    <div class="main" v-if="activeTabs === 2 && info">
      <div class="title">操作记录</div>
      <el-table
        :data="info.logList"
        border
        style="width: 100%">
        <el-table-column
          prop="param1"
          label="操作人">
        </el-table-column>
        <el-table-column
          prop="createDate"
          label="操作时间">
        </el-table-column>
        <el-table-column
          label="操作">
          <template slot-scope="{row}">
            <span v-if="row.objType === 0">工单创建</span>
            <span v-if="row.objType === 1">指派</span>
            <span v-if="row.objType === 2">处理</span>
            <span v-if="row.objType === 3">合同创建</span>
            <span v-if="row.objType === 4">合同变更</span>
            <span v-if="row.objType === 5">合同退租</span>
          </template>
        </el-table-column>
        <el-table-column
          prop="content"
          label="操作内容">
        </el-table-column>
      </el-table>
    </div>
    <!--  é€€ç§Ÿ  -->
    <TerminateLease ref="terminateLease" @success="getData" />
  </GlobalWindow>
</template>
<script>
import GlobalWindow from '@/components/common/GlobalWindow'
import BaseOpera from '@/components/base/BaseOpera'
import TerminateLease from './terminateLease'
import { getById } from '@/api/contract'
import { fetchList } from '@/api/bill'
export default {
  components: {
    GlobalWindow
    GlobalWindow,
    TerminateLease
  },
  extends: BaseOpera,
  data() {
    return {
      id: '',
      visible: false,
      activeTabs: '',
      info: {}
      activeTabs: 0,
      type: 0,
      info: null,
      pageSize: 10,
      page: 1,
      total: 0,
      tableData: [],
      loading: false
    }
  },
  methods: {
    open (title, id) {
      this.title = title
      this.activeTabs = 0
      this.type = 0
      this.page = 1
      this.pageSize = 10
      this.tableData = []
      this.id = id
      this.getData()
    },
    getData () {
      getById(this.id)
        .then(res => {
          this.info = res
          this.getList()
          this.visible = true
        })
    },
    refund () {
      this.$refs.terminateLease.open('新建退租协议', JSON.parse(JSON.stringify(this.info)))
    },
    getList () {
      this.loading = true
      fetchList({
        capacity: this.pageSize,
        page: this.page,
        model: {
          billType: this.type,
          contractId: this.info.id
        }
      }).then(res => {
        this.loading = false
        this.tableData = res.records
        this.total = res.total
      })
    },
    changeType (e) {
      console.log(e)
      this.type = e
      this.page = 1
      this.pageSize = 10
      this.tableData = []
      this.getList()
    },
    tabsClick(val) {
      this.activeTabs = val
    },
    getDetail() {
    },
    handleSizeChange (e) {
      this.pageSize = e
      this.getList()
    },
    handleCurrentChange (e) {
      this.page = e
      this.getList()
    }
  }
}
@@ -207,9 +429,9 @@
  .list {
    display: flex;
    flex-wrap: wrap;
    background: #F7F7F7;
    /*background: #F7F7F7;*/
    border-radius: 2px;
    padding: 15px 20px;
    /*padding: 15px 20px;*/
    margin-bottom: 20px;
    .item {
@@ -218,7 +440,7 @@
      .la {
        color: #7f7f7f;
        margin-top: 2px;
        margin-bottom: 10px;
      }
    }
  }
admin/src/views/contract/components/contractEdit.vue
@@ -1,75 +1,79 @@
<template>
  <GlobalWindow width="1000px" :title="title" :visible.sync="showModal" :confirm-working="isWorking" @close="close"
  <GlobalWindow width="100%" :title="title" :visible.sync="visible" :confirm-working="isWorking" @close="close"
    @confirm="confirm">
    <div class="tabs">
      <div class="tab" :class="{ active: activeTabs == 0 }" @click="tabsClick(0)">1、基本信息</div>
      <div class="tab" :class="{ active: activeTabs == 1 }" @click="tabsClick(1)">2、费用条款</div>
      <div class="tab" :class="{ active: activeTabs === 0 }" @click="tabsClick(0)">1、基本信息</div>
      <div class="tab" :class="{ active: activeTabs === 1 }" @click="tabsClick(1)">2、费用条款</div>
    </div>
    <template v-if="activeTabs == 0">
    <div v-show="activeTabs === 0">
      <div class="main">
        <div class="main_content">
          <el-form :model="param" ref="paramRef" :rules="rules">
          <el-form :model="form" ref="form" :rules="rules">
            <div class="m_title">基础信息</div>
            <div class="list">
              <el-form-item label="合同类型" prop="type">
                <el-select v-model="param.type" placeholder="请选择" clearable>
                  <el-option v-for="item in types" :value="item.value" :label="item.name"></el-option>
                <el-select v-model="form.type" placeholder="请选择" @change="changeType">
                  <el-option v-for="(item, index) in types" :key="index" :value="item.value" :label="item.name"></el-option>
                </el-select>
              </el-form-item>
              <el-form-item label="合同编号" prop="code">
                <el-input v-model="param.code" placeholder="请输入合同编号" v-trim />
                <el-input v-model="form.code" placeholder="请输入合同编号" v-trim />
              </el-form-item>
              <el-form-item label="经办人" prop="aaa">
                <el-select v-model="param.aaa" placeholder="请选择" clearable>
                  <el-option v-for="item in agentList" :value="item.id" :label="item.name"></el-option>
              <el-form-item label="经办人" prop="userId">
                <el-select v-model="form.userId" filterable placeholder="请选择">
                  <el-option v-for="(item, index) in agentList" :key="index" :value="item.id" :label="item.realname"></el-option>
                </el-select>
              </el-form-item>
              <el-form-item label="合同签订日期" prop="">
                <el-date-picker type="date" v-model="param.getDate" value-format="yyyy-MM-dd" placeholder="请选择" />
              <el-form-item label="合同签订日期" prop="signDate">
                <el-date-picker type="date" v-model="form.signDate" value-format="yyyy-MM-dd" placeholder="请选择" />
              </el-form-item>
              <el-form-item label="合同开始日期" prop="">
                <el-date-picker type="date" v-model="param.getDate" value-format="yyyy-MM-dd" placeholder="请选择" />
              <el-form-item label="合同开始日期" prop="startDate">
                <el-date-picker type="date" v-model="form.startDate" value-format="yyyy-MM-dd" placeholder="请选择" />
              </el-form-item>
              <el-form-item label="合同结束日期" prop="">
                <el-date-picker type="date" v-model="param.getDate" value-format="yyyy-MM-dd" placeholder="请选择" />
              <el-form-item label="合同结束日期" prop="endDate">
                <el-date-picker type="date" v-model="form.endDate" value-format="yyyy-MM-dd" placeholder="请选择" />
              </el-form-item>
              <el-form-item label="归属项目" prop="">
                <el-select v-model="param.aaa" placeholder="请选择" clearable>
                  <el-option v-for="item in projectList" :value="item.id" :label="item.name"></el-option>
              <el-form-item label="归属项目" prop="projectId">
                <el-select v-model="form.projectId" placeholder="请选择">
                  <el-option v-for="(item, index) in projectList" :key="index" :value="item.id" :label="item.name"></el-option>
                </el-select>
              </el-form-item>
              <el-form-item label="结果取整(四舍五入)" prop="">
                <el-select v-model="param.aaa" placeholder="请选择" clearable>
              <el-form-item label="结果取整(四舍五入)" prop="roundedUp">
                <el-select v-model="form.roundedUp" placeholder="请选择">
                  <el-option :value="0" label="否"></el-option>
                  <el-option :value="1" label="是"></el-option>
                </el-select>
              </el-form-item>
              <el-form-item label="所属公司" prop="">
                <el-select v-model="param.aaa" placeholder="请选择" clearable>
                  <el-option v-for="item in comparyList" :value="item.id" :label="item.name"></el-option>
              <el-form-item label="所属公司" prop="companyId">
                <el-select v-model="form.companyId" placeholder="请选择">
                  <el-option v-for="(item, index) in comparyList" :key="index" :value="item.id" :label="item.name"></el-option>
                </el-select>
              </el-form-item>
            </div>
            <div class="m_title">租客信息</div>
            <div class="list">
              <el-form-item label="租客" prop="">
                <el-button @click="handleRent" type="primary">选择租客</el-button>
                <el-select v-model="param.aaa" placeholder="请选择" clearable>
                  <el-option v-for="item in renterList" :value="item.id" :label="item.name"></el-option>
                </el-select>
              <el-form-item label="租客" prop="renterName">
                <div @click="handleRent">
                  <el-input v-model="form.renterName" readonly placeholder="请点击选择租客" />
                </div>
              </el-form-item>
              <el-form-item label="联系人" prop="">
                <el-select v-model="param.aaa" placeholder="请选择" clearable>
                  <el-option v-for="item in contacts" :value="item.id" :label="item.name"></el-option>
                </el-select>
              <el-form-item label="联系人" prop="memberName">
                <el-input v-model="form.memberName" readonly placeholder="请点击选择租客" />
              </el-form-item>
            </div>
          </el-form>
        </div>
        <div class="main_house">
          <div class="title">请选择房源</div>
          <el-cascader style="width: 300px" v-model="value" @change="houseChange" :options="options"
            :props="{ multiple: true }" collapse-tags clearable />
          <el-tree
            :data="houseList"
            show-checkbox
            node-key="idd"
            @check="checkHouseRoom"
            :default-expanded-keys="ids"
            :default-checked-keys="ids"
            :props="{ children: 'projectDataVOList', label: 'name' }">
          </el-tree>
        </div>
      </div>
      <div class="file_wrap">
@@ -80,75 +84,184 @@
            <el-button icon="el-icon-plus" plain>添加附件</el-button>
          </el-upload>
        </div>
        <el-table :data="param.list" stripe>
          <el-table-column prop="" label="附件名称" align="center" min-width="100" show-overflow-tooltip />
          <el-table-column prop="" label="操作人" align="center" min-width="100" show-overflow-tooltip />
          <el-table-column prop="" label="操作时间" align="center" min-width="100" show-overflow-tooltip />
          <el-table-column prop="" label="操作" align="center" min-width="100">
            <template v-slot="scope">
              <span class="cu red">删除</span>
        <el-table :data="form.fileList" stripe>
          <el-table-column prop="originname" label="附件名称" align="center" min-width="100" show-overflow-tooltip />
          <el-table-column prop="userName" label="操作人" align="center" min-width="100" show-overflow-tooltip />
          <el-table-column prop="createTime" label="操作时间" align="center" min-width="100" show-overflow-tooltip />
          <el-table-column label="操作" align="center" min-width="100">
            <template slot-scope="{ row }">
              <span class="cu red" @click="dele(row.imgaddr)">删除</span>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </template>
    <template v-if="activeTabs == 1">
    </div>
    <div v-show="activeTabs === 1">
      <div class="tabs cost_tabs">
        <div class="tab" :class="{ active: cactiveTabs == 0 }" @click="ctabsClick(0)">租赁条款</div>
        <div class="tab" :class="{ active: cactiveTabs == 1 }" @click="ctabsClick(1)">物业条款</div>
        <div class="tab" :class="{ active: cactiveTabs === 0 }" @click="ctabsClick(0)" v-if="[0,2].includes(form.type)">租赁条款</div>
        <div class="tab" :class="{ active: cactiveTabs === 1 }" @click="ctabsClick(1)" v-if="[0,1].includes(form.type)">物业条款</div>
      </div>
      <div class="main">
        <div class="main_content">
          <el-form :model="paramCost" ref="paramCostRef" :rules="rules">
            <div class="m_title">租赁信息</div>
            <div class="list">
              <el-form-item label="押金金额(元)" prop="type">
                <el-input v-model="paramCost.code" placeholder="请输入" v-trim />
              </el-form-item>
              <el-form-item label="付款方式" prop="code">
                <el-select v-model="paramCost.type" placeholder="请选择" clearable>
                  <el-option v-for="item in payMethods" :value="item.value" :label="item.name"></el-option>
                </el-select>
              </el-form-item>
              <el-form-item label="免租期" prop="aaa">
                <el-date-picker type="daterange" v-model="paramCost.getDate" value-format="yyyy-MM-dd"
                  placeholder="请选择" />
              </el-form-item>
            </div>
            <div class="m_title">租赁条款</div>
            <div class="list">
              <el-form-item label="起始日期" prop="">
                <el-date-picker type="date" v-model="paramCost.getDate" value-format="yyyy-MM-dd" placeholder="请选择" />
              </el-form-item>
              <el-form-item label="合同单价" prop="">
                <el-input placeholder="请输入内容" v-model="paramCost.aaa">
                  <el-select v-model="paramCost.ddd" slot="append" placeholder="请选择" clearable>
                    <el-option v-for="item in unitOps" :value="item.value" :label="item.name"></el-option>
      <!--   ç§Ÿèµæ¡æ¬¾   -->
      <div v-show="cactiveTabs === 0">
        <div class="main">
          <div class="main_content">
            <el-form :model="form" ref="paramCostRef" :rules="rules">
              <div class="m_title">租赁信息</div>
              <div class="list">
                <el-form-item label="押金金额(元)" prop="zlDeposit">
                  <el-input v-model="form.zlDeposit" placeholder="请输入" v-trim />
                </el-form-item>
                <el-form-item label="付款方式" prop="zlPayType">
                  <el-select v-model="form.zlPayType" placeholder="请选择">
                    <el-option v-for="(item, index) in payMethods" :key="index" :value="item.value" :label="item.name"></el-option>
                  </el-select>
                </el-input>
              </el-form-item>
              <el-form-item label="付款提前天数" prop="">
                <el-input v-model="paramCost.aaa" placeholder="请输入" v-trim />
              </el-form-item>
            </div>
          </el-form>
                </el-form-item>
                <el-form-item label="免租期" prop="zlDate">
                  <el-date-picker type="daterange" v-model="form.zlDate" @change="getZLDate" value-format="yyyy-MM-dd"
                    placeholder="请选择" />
                </el-form-item>
              </div>
              <div class="m_title">
                <span>租赁条款</span>
                <el-button type="text" size="medium" @click="addZl">增加</el-button>
              </div>
              <div class="list">
                <template v-for="(item, index) in form.zlDetailList" :key="index">
                  <el-form-item label="起始日期" prop="time">
                    <el-date-picker type="daterange" v-model="item.time" @change="getDate1($event, index)" value-format="yyyy-MM-dd" placeholder="请选择" />
                  </el-form-item>
                  <el-form-item label="合同单价" prop="price">
                    <el-input placeholder="请输入" v-model="item.price">
                      <el-select v-model="item.circleType" slot="append" placeholder="请选择">
                        <el-option v-for="(item, index) in unitOps" :key="index" :value="item.value" :label="item.name"></el-option>
                      </el-select>
                    </el-input>
                  </el-form-item>
                  <el-form-item label="付款提前天数" prop="advanceDays">
                    <div style="display: flex; align-items: center; justify-content: space-between;">
                      <el-input v-model="item.advanceDays" placeholder="请输入" v-trim />
                      <el-link :underline="false" type="danger" @click="deleZl(index)" style="margin-left: 20px; flex-shrink: 0;">删除</el-link>
                    </div>
                  </el-form-item>
                </template>
              </div>
            </el-form>
          </div>
        </div>
        <el-button style="width: 100%;height: 48px;" type="primary" plain @click="generateZL">生成账单明细</el-button>
        <el-table :data="zlList" class="mt20" stripe>
          <el-table-column label="费用类型" align="center" show-overflow-tooltip>
            <template slot-scope="{row}">
              <span v-if="row.costType === 0">租赁费</span>
              <span v-if="row.costType === 1">物业费</span>
              <span v-if="row.costType === 2">租赁押金</span>
              <span v-if="row.costType === 3">物业押金</span>
              <span v-if="row.costType === 4">水电费</span>
              <span v-if="row.costType === 5">杂项费</span>
              <span v-if="row.costType === 6">其他</span>
              <span v-if="row.costType === 7">保证金</span>
            </template>
          </el-table-column>
          <el-table-column label="期数" align="center" show-overflow-tooltip>
            <template slot-scope="{row}">
              <el-tag type="success">{{row.sortnum}}</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="区间" align="center" show-overflow-tooltip>
            <template slot-scope="{row}">
              {{row.startDate}} ~ {{row.endDate}}
            </template>
          </el-table-column>
          <el-table-column prop="planPayDate" label="付款日" align="center" show-overflow-tooltip />
          <el-table-column prop="receivableFee" label="应收" align="center" show-overflow-tooltip />
        </el-table>
        <div class="total">
          <span>总计</span>
          <div>费用应收总计:{{zlPrice}},押金应收总计:{{form.zlDeposit}}</div>
        </div>
      </div>
      <el-button style="width: 100%;height: 48px;" type="primary" plain>生成账单明细</el-button>
      <el-table :data="paramCost.list" class="mt20" stripe>
        <el-table-column prop="" label="费用类型" align="center" width="160px" show-overflow-tooltip />
        <el-table-column prop="" label="指数" align="center" min-width="100" show-overflow-tooltip />
        <el-table-column prop="" label="区间" align="center" min-width="100" show-overflow-tooltip />
        <el-table-column prop="" label="付款日" align="center" min-width="100" show-overflow-tooltip />
        <el-table-column prop="" label="应收" align="center" min-width="100" show-overflow-tooltip />
      </el-table>
      <div class="total">
        <span>总计</span>
        <div>费用应收总计:,押金应收总计:</div>
      <!--   ç‰©ä¸šæ¡æ¬¾   -->
      <div v-show="cactiveTabs === 1">
        <div class="main">
          <div class="main_content">
            <el-form :model="form" ref="paramCostRef1" :rules="rules">
              <div class="m_title">物业信息</div>
              <div class="list">
                <el-form-item label="物业押金" prop="wyDeposit">
                  <el-input v-model="form.wyDeposit" placeholder="请输入" v-trim />
                </el-form-item>
                <el-form-item label="付款方式" prop="wyPayType">
                  <el-select v-model="form.wyPayType" placeholder="请选择">
                    <el-option v-for="(item, index) in payMethods" :key="index" :value="item.value" :label="item.name"></el-option>
                  </el-select>
                </el-form-item>
                <el-form-item label="免租期" prop="wyDate">
                  <el-date-picker type="daterange" v-model="form.wyDate" @change="getWYDate" value-format="yyyy-MM-dd"
                    placeholder="请选择" />
                </el-form-item>
              </div>
              <div class="m_title">
                <span>物业条款</span>
                <el-button type="text" size="medium" @click="addWy">增加</el-button>
              </div>
              <div class="list">
                <template v-for="(item, index) in form.wyDetailList" :key="index">
                  <el-form-item label="起始日期" prop="time">
                    <el-date-picker type="daterange" v-model="item.time" @change="getDate2($event, index)" value-format="yyyy-MM-dd" placeholder="请选择" />
                  </el-form-item>
                  <el-form-item label="合同单价" prop="price">
                    <el-input placeholder="请输入" v-model="item.price">
                      <el-select v-model="item.circleType" slot="append" placeholder="请选择">
                        <el-option v-for="(item, index) in unitOps" :key="index" :value="item.value" :label="item.name"></el-option>
                      </el-select>
                    </el-input>
                  </el-form-item>
                  <el-form-item label="付款提前天数" prop="advanceDays">
                    <div style="display: flex; align-items: center; justify-content: space-between;">
                      <el-input v-model="item.advanceDays" placeholder="请输入" v-trim />
                      <el-link :underline="false" type="danger" @click="deleWy(index)" style="margin-left: 20px; flex-shrink: 0;">删除</el-link>
                    </div>
                  </el-form-item>
                </template>
              </div>
            </el-form>
          </div>
        </div>
        <el-button style="width: 100%;height: 48px;" type="primary" plain @click="generateWY">生成账单明细</el-button>
        <el-table :data="wyList" class="mt20" stripe>
          <el-table-column label="费用类型" align="center" show-overflow-tooltip>
            <template slot-scope="{row}">
              <span v-if="row.costType === 0">租赁费</span>
              <span v-if="row.costType === 1">物业费</span>
              <span v-if="row.costType === 2">租赁押金</span>
              <span v-if="row.costType === 3">物业押金</span>
              <span v-if="row.costType === 4">水电费</span>
              <span v-if="row.costType === 5">杂项费</span>
              <span v-if="row.costType === 6">其他</span>
              <span v-if="row.costType === 7">保证金</span>
            </template>
          </el-table-column>
          <el-table-column label="期数" align="center" show-overflow-tooltip>
            <template slot-scope="{row}">
              <el-tag type="success">{{row.sortnum}}</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="区间" align="center" show-overflow-tooltip>
            <template slot-scope="{row}">
              {{row.startDate}} ~ {{row.endDate}}
            </template>
          </el-table-column>
          <el-table-column prop="planPayDate" label="付款日" align="center" show-overflow-tooltip />
          <el-table-column prop="receivableFee" label="应收" align="center" show-overflow-tooltip />
        </el-table>
        <div class="total">
          <span>总计</span>
          <div>费用应收总计:{{wyPrice}},押金应收总计:{{form.wyDeposit}}</div>
        </div>
      </div>
    </template>
    <!--  -->
    <MemberSearch ref="MemberSearchRef" />
    </div>
    <!-- é€‰æ‹©ç§Ÿå®¢ -->
    <MemberSearch ref="MemberSearchRef" @select="getTenant" />
  </GlobalWindow>
</template>
@@ -157,91 +270,97 @@
import BaseOpera from '@/components/base/BaseOpera'
import MemberSearch from '@/components/common/MemberSearch'
import { rules } from './config'
import { create, getBillList } from '@/api/contract'
import { getUserList } from '@/api/system/user'
import { getProjectList, tree } from '@/api/project/ywProject'
import { companyList } from '@/api/company'
import { Message, Loading } from 'element-ui'
import { mapState } from 'vuex'
export default {
  components: {
    GlobalWindow,
    MemberSearch
  },
  extends: BaseOpera,
  data() {
  computed: {
    ...mapState(['userInfo'])
  },
  data () {
    return {
      showModal: false,
      title: '创建合同',
      activeTabs: '0',
      param: {},
      activeTabs: 0,
      form: {
        type: '',
        code: '',
        userId: '',
        signDate: '',
        startDate: '',
        endDate: '',
        projectId: '',
        roundedUp: '',
        companyId: '',
        renterId: '',
        renterName: '',
        memberId: '',
        memberName: '',
        fileList: [],
        zlDeposit: '',
        zlPayType: '',
        zlFreeStartDate: '',
        zlFreeEndDate: '',
        zlDate: [],
        zlDetailList: [
          {
            startDate: '',
            endDate: '',
            time: [],
            price: '',
            advanceDays: ''
          }
        ],
        wyDeposit: '',
        wyPayType: '',
        wyFreeStartDate: '',
        wyFreeEndDate: '',
        wyDate: [],
        wyDetailList: [
          {
            startDate: '',
            endDate: '',
            time: [],
            price: '',
            advanceDays: ''
          }
        ],
        roomIds: []
      },
      ids: [],
      zlList: [],
      wyList: [],
      rules,
      loadingInstance: null,
      uploadImgUrl: process.env.VUE_APP_API_PREFIX + '/visitsAdmin/cloudService/public/uploadBatch',
      fileList: [],
      uploadData: {
        folder: 'HIDDEN_DANGER_FILE'
        folder: 'YW_CONTRACT_FILE'
      },
      types: [
        { name: '物业+租赁合同', value: 0 },
        { name: '租赁合同', value: 1 },
        { name: '物业合同', value: 2 },
        { name: '租赁合同', value: 2 },
        { name: '物业合同', value: 1 }
      ],
      agentList: [], //经办人
      agentList: [], // ç»åŠžäºº
      projectList: [],
      comparyList: [], // å…¬å¸
      renterList: [], // ç§Ÿå®¢
      contacts: [], // è”系人
      value: [],
      options: [
        {
          value: 1,
          label: '东南',
          children: [{
            value: 2,
            label: '上海',
            children: [
              { value: 3, label: '普陀' },
              { value: 4, label: '黄埔' },
              { value: 5, label: '徐汇' }
            ]
          }, {
            value: 7,
            label: '江苏',
            children: [
              { value: 8, label: '南京' },
              { value: 9, label: '苏州' },
              { value: 10, label: '无锡' }
            ]
          }, {
            value: 12,
            label: '浙江',
            children: [
              { value: 13, label: '杭州' },
              { value: 14, label: '宁波' },
              { value: 15, label: '嘉兴' }
            ]
          }]
        },
        {
          value: 17,
          label: '西北',
          children: [{
            value: 18,
            label: '陕西',
            children: [
              { value: 19, label: '西安' },
              { value: 20, label: '延安' }
            ]
          }, {
            value: 21,
            label: '新疆维吾尔族自治区',
            children: [
              { value: 22, label: '乌鲁木齐' },
              { value: 23, label: '克拉玛依' }
            ]
          }]
        }
      ],
      houseList: [],
      cactiveTabs: 0,
      paramCost: {},
      payMethods: [
        { name: '一次性付款', value: 0 },
        { name: '3个月一付', value: 1 },
@@ -251,37 +370,233 @@
      unitOps: [
        { name: '元/m²·天', value: 0 },
        { name: '元/m²·月', value: 1 },
        { name: '元/天', value: 2 },
        { name: '元/月', value: 3 },
        { name: '元/å¹´', value: 4 },
        { name: '元/m²·年', value: 5 },
        { name: '元/天', value: 3 },
        { name: '元/月', value: 4 },
        { name: '元/å¹´', value: 5 },
        { name: '元/m²·年', value: 2 },
        { name: '元/场', value: 6 },
      ],
      houseLvThree: []
    }
  },
  methods: {
    tabsClick(val) {
    open (title, target) {
      this.title = title
      this.ids = []
      this.getUser()
      this.getProject()
      this.getCompany()
      this.getHouseTree()
      this.visible = true
      this.$nextTick(() => {
        for (const key in this.form) {
          if (['roomIds', 'fileList', 'wyDate', 'zlDate'].includes(key)) {
            this.form[key] = []
          } else {
            this.form[key] = target[key]
          }
        }
      })
    },
    changeType (e) {
      if (e === 0 || e === 2) {
        this.cactiveTabs = 0
      } else if (e === 0 || e === 1) {
        this.cactiveTabs = 1
      }
    },
    confirm () {
      this.$refs.form.validate((valid) => {
        if (!valid) {
          return
        }
        if (this.form.type === 0) {
          this.$refs.paramCostRef.validate((valid1) => {
            if (!valid1) {
              return
            }
            this.$refs.paramCostRef1.validate((valid2) => {
              if (!valid2) {
                return
              }
              this.submit()
            })
          })
        } else if (this.form.type === 2) {
          this.$refs.paramCostRef.validate((valid1) => {
            if (!valid1) {
              return
            }
            this.submit()
          })
        } else if (this.form.type === 1) {
          this.$refs.paramCostRef1.validate((valid2) => {
            if (!valid2) {
              return
            }
            this.submit()
          })
        }
      })
    },
    submit () {
      // è°ƒç”¨æ–°å»ºæŽ¥å£
      this.isWorking = true
      create({ ...this.form })
        .then(res => {
          this.visible = false
          this.$tip.apiSuccess('创建成功')
          this.$emit('success')
        })
        .finally(() => {
          this.isWorking = false
        })
    },
    getDate1 (e, index) {
      this.form.zlDetailList[index].startDate = e[0]
      this.form.zlDetailList[index].endDate = e[1]
    },
    getDate2 (e, index) {
      this.form.wyDetailList[index].startDate = e[0]
      this.form.wyDetailList[index].endDate = e[1]
    },
    checkHouseRoom (a, b) {
      this.ids = b.checkedKeys
      let arr = b.checkedKeys.map(item => {
        if (item.split('-')[0] == 3) {
          return Number(item.split('-')[1])
        }
      })
      this.form.roomIds = arr.filter(item => item !== undefined);
    },
    getHouseTree () {
      tree({})
        .then(res => {
          res.forEach(item => {
            item.disabled = true
          })
          this.addParamToArray(res)
          this.houseList = res
        })
    },
    addParamToArray(arr) {
      for (let i = 0; i < arr.length; i++) {
        const currentItem = arr[i].projectDataVOList;
        arr[i].idd = arr[i].lv + '-' + arr[i].id
        if (currentItem.length > 0) {
          this.addParamToArray(currentItem);
        }
      }
    },
    generateZL () {
      getBillList({ ...this.form })
        .then(res => {
          let zlPrice = 0
          let arr = []
          res.forEach(item => {
            if (item.costType === 0) {
              zlPrice += item.receivableFee
              arr.push(item)
            }
          })
          this.zlPrice = zlPrice
          this.zlList = arr
        })
    },
    generateWY () {
      getBillList({ ...this.form })
        .then(res => {
          let zlPrice = 0
          let arr = []
          res.forEach(item => {
            if (item.costType === 1) {
              zlPrice += item.receivableFee
              arr.push(item)
            }
          })
          this.wyPrice = zlPrice
          this.wyList = arr
        })
    },
    addZl () {
      this.form.zlDetailList.push({
        startDate: '',
        endDate: '',
        time: [],
        price: '',
        advanceDays: ''
      })
    },
    addWy () {
      this.form.wyDetailList.push({
        startDate: '',
        endDate: '',
        time: [],
        price: '',
        advanceDays: ''
      })
    },
    deleZl(index) {
      if (this.form.zlDetailList.length === 1) return Message.warning('至少保留一条!')
      this.form.zlDetailList.splice(index, 1)
    },
    deleWy(index) {
      if (this.form.wyDetailList.length === 1) return Message.warning('至少保留一条!')
      this.form.wyDetailList.splice(index, 1)
    },
    getZLDate (e) {
      this.form.zlFreeStartDate = e[0]
      this.form.zlFreeEndDate = e[1]
    },
    getWYDate (e) {
      this.form.wyFreeStartDate = e[0]
      this.form.wyFreeEndDate = e[1]
    },
    getTenant (row) {
      this.form.renterId = row.id
      this.form.renterName = row.name
      this.form.memberId = row.memberId
      this.form.memberName = row.memberName
    },
    dele (imgaddr) {
      this.form.fileList.forEach((item, index) => {
        if (imgaddr === item.imgaddr) {
          this.form.fileList.splice(index, 1)
        }
      })
    },
    getUser () {
      getUserList({})
        .then(res => {
          this.agentList = res
        })
    },
    getProject () {
      getProjectList({})
        .then(res => {
          this.projectList = res
        })
    },
    getCompany () {
      companyList({ type: 2 })
        .then(res => {
          this.comparyList = res
        })
    },
    tabsClick (val) {
      this.activeTabs = val
    },
    ctabsClick(val) {
    ctabsClick (val) {
      this.cactiveTabs = val
    },
    getDetail() {
    handleRent () {
      this.$refs.MemberSearchRef.open()
    },
    handleRent() {
      this.$refs.MemberSearchRef.openModal()
    },
    houseChange(e) {
    houseChange (e) {
      console.log(e)
      console.log(this.value)
    },
    beforeUpload(file) {
      // if (['video/mp4', 'video/ogg', 'video/flv', 'video/avi', 'video/wmv', 'video/rmvb', 'image/jpeg', 'image/jpg', 'image/png', 'image/gif'].indexOf(file.type) == -1) {
      //   this.$message.error('请上传正确的视频/图片格式')
      //   return false
      // }
    beforeUpload (file) {
      this.loadingInstance = Loading.service({
        lock: true,
        text: 'Loading',
@@ -289,40 +604,33 @@
        background: 'rgba(0, 0, 0, 0.7)'
      })
    },
    uploadError() {
    uploadError () {
      this.$nextTick(() => { // ä»¥æœåŠ¡çš„æ–¹å¼è°ƒç”¨çš„ Loading éœ€è¦å¼‚步关闭
        if (this.loadingInstance) {
          this.loadingInstance.close()
        }
      })
    },
    uploadAvatarSuccess(file) {
      this.$nextTick(() => { // ä»¥æœåŠ¡çš„æ–¹å¼è°ƒç”¨çš„ Loading éœ€è¦å¼‚步关闭
    getDay () {
      const now = new Date()
      const year = now.getFullYear()
      const month = now.getMonth() + 1 // åŠ 1使其从1开始
      const day = now.getDate()
      const hours = now.getHours()
      const minutes = now.getMinutes()
      const seconds = now.getSeconds()
      return `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')} ${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
    },
    uploadAvatarSuccess (file) {
      this.$nextTick(() => {
        if (this.loadingInstance) {
          this.loadingInstance.close()
        }
      })
      console.log('file', file)
      const item = file.data[0]
      if (['.mp4', '.avi', '.flv', '.wmv'].some(char => item.imgaddr.includes(char))) {
        this.fileList.push({
          type: 1,
          fileurl: item.imgaddr,
          fileurlFull: item.url
        })
      } else {
        this.fileList.push({
          type: 0,
          fileurl: item.imgaddr,
          fileurlFull: item.url
        })
      }
      console.log('file', this.fileList)
      // this.$set(this.param, 'faceImg', file.imgurl)
      // this.$set(this.param, 'faceImgUrl', file.imgurlfull)
      this.form.fileList.push({ ...item, fileurl: item.imgaddr, name: item.originname, userName: this.userInfo.realname, createTime: this.getDay() })
    },
    close() {
      this.showModal = false
    close () {
      this.$emit('close')
    }
  }
@@ -431,5 +739,13 @@
  font-size: 14px;
  margin-bottom: 15px;
  margin-top: 10px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  span {
    font-weight: 500;
    font-size: 14px;
    margin-bottom: 15px;
  }
}
</style>
admin/src/views/contract/components/terminateLease.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,442 @@
<template>
    <GlobalWindow
        :title="title"
        width="100%"
        :visible.sync="visible"
        :confirm-working="isWorking"
        @close="close"
        @confirm="confirm">
        <div class="main">
            <div class="main_head">
                <span>租客:{{ info.renterName }}</span>
                <span>合同编号:{{ info.code }}</span>
            </div>
            <div class="title">退租信息</div>
            <div class="main_box">
                <div class="main_box_form">
                    <el-form :inline="true" label-position="top" :model="form" ref="form" :rules="rules" class="demo-form-inline">
                        <el-form-item label="退租类型" prop="btType" style="width: 33%;">
                            <el-select v-model="form.btType" placeholder="请选择">
                                <el-option label="到期退租" :value="0"></el-option>
                                <el-option label="换房退租" :value="1"></el-option>
                                <el-option label="违约退租" :value="2"></el-option>
                                <el-option label="协商退租" :value="3"></el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="退租日期" prop="btDate" style="width: 33%;">
                            <el-date-picker
                                v-model="form.btDate"
                                type="date"
                                value-format="yyyy-MM-dd"
                                placeholder="请选择">
                            </el-date-picker>
                        </el-form-item>
                        <el-form-item label="经办人" prop="btUserId" style="width: 30%;">
                            <el-select v-model="form.btUserId" placeholder="请选择">
                                <el-option v-for="(item, index) in agentList" :key="index" :value="item.id" :label="item.realname"></el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="协议签订日期" prop="btSignDate" style="width: 33%;">
                            <el-date-picker
                                v-model="form.btSignDate"
                                type="date"
                                value-format="yyyy-MM-dd"
                                placeholder="请选择">
                            </el-date-picker>
                        </el-form-item>
                        <el-form-item label="退租原因" prop="btInfo" style="width: 60%;">
                            <el-input v-model="form.btInfo" placeholder="请输入"></el-input>
                        </el-form-item>
                    </el-form>
                </div>
                <div class="main_box_list">
                    <div class="main_box_list_title">已选房源</div>
                    <el-table :data="info.roomList" stripe>
                        <el-table-column prop="projectName" label="项目名称" show-overflow-tooltip />
                        <el-table-column label="房源名称" show-overflow-tooltip>
                            <template slot-scope="{row}">
                                {{row.buildingName}}/{{row.code}}
                            </template>
                        </el-table-column>
                        <el-table-column label="租赁面积(㎡)" show-overflow-tooltip>
                            <template slot-scope="{row}">
                                {{row.area}}㎡
                            </template>
                        </el-table-column>
                    </el-table>
                </div>
            </div>
            <div class="title">
                <span>退租信息</span>
                <div style="display: flex; align-items: center;">
                    <el-button type="primary" @click="$refs.addCollectionBill.open('创建收款账单', { contractCode: info.code, contractId: info.id, renterName: info.renterName, renterId: info.renterId, billType: 0, billTypeCopy: 0, feeType: 0 })">添加收款</el-button>
                    <el-button type="primary" @click="$refs.AddPaymentBill.open('创建付款账单', { contractCode: info.code, contractId: info.id, renterName: info.renterName, renterId: info.renterId, billType: 1, billTypeCopy: 1 })">添加付款</el-button>
                </div>
            </div>
            <el-table
                :data="info.terminateList"
                border
                style="width: 100%; margin-bottom: 15px;">
                <el-table-column
                    prop="code"
                    label="账单编号">
                </el-table-column>
                <el-table-column
                    label="费用类型">
                    <template slot-scope="{row}">
                        <span v-if="row.costType === 0">租赁费</span>
                        <span v-if="row.costType === 1">物业费</span>
                        <span v-if="row.costType === 4">水电费</span>
                        <span v-if="row.costType === 5">杂项费</span>
                        <span v-if="row.costType === 6">其他</span>
                    </template>
                </el-table-column>
                <el-table-column
                    label="计费周期">
                    <template slot-scope="{row}">
                        {{row.startDate}} ~ {{row.endDate}}
                    </template>
                </el-table-column>
                <el-table-column
                    label="应收付金额/原始应收付">
                    <template v-slot="{row}">
                        <div style="display: flex; align-items: center;">
                            <el-input v-model="row.receivableFee" @input="changeReceivableFee($event, row)" placeholder="请输入内容" style="width: 90px;"></el-input>
                            <span style="margin: 0 10px;">/</span>
                            {{row.receivableFeeCopy}}
                        </div>
                    </template>
                </el-table-column>
                <el-table-column
                    prop="actReceivableFee"
                    label="实收/付金额">
                </el-table-column>
                <el-table-column
                    label="需收/付金额">
                    <template slot-scope="{row}">
                        <div style="display: flex; align-items: center;">
                            <el-tag type="success" v-if="row.billType === 0">收</el-tag>
                            <el-tag type="warning" v-if="row.billType === 1">付</el-tag>
                            <span style="margin-left: 10px;">{{row.price}}</span>
                        </div>
                    </template>
                </el-table-column>
                <el-table-column
                    label="应收/付日期">
                    <template slot-scope="{row}">
                        <el-date-picker v-model="row.planPayDate" value-format="yyyy-MM-dd" type="date" placeholder="选择日期"></el-date-picker>
                    </template>
                </el-table-column>
            </el-table>
            <div class="title">押金</div>
            <el-table
                :data="info.depositList"
                border
                style="width: 100%; margin-bottom: 15px;">
                <el-table-column
                    prop="code"
                    label="账单编号">
                </el-table-column>
                <el-table-column
                    label="费用类型">
                    <template slot-scope="{row}">
                        <span v-if="row.costType === 2">租赁押金</span>
                        <span v-if="row.costType === 3">物业押金</span>
                        <span v-if="row.costType === 7">保证金</span>
                    </template>
                </el-table-column>
                <el-table-column
                    label="计费周期">
                    <template slot-scope="{row}">
                        {{row.startDate}} ~ {{row.endDate}}
                    </template>
                </el-table-column>
                <el-table-column
                    prop="receivableFee"
                    label="应收金额">
                </el-table-column>
                <el-table-column
                    prop="actReceivableFee"
                    label="实收/付金额">
                </el-table-column>
                <el-table-column
                    label="应退金额">
                    <template slot-scope="{row}">
                        <div style="display: flex; align-items: center;">
                            <el-tag type="success" v-if="row.billType === 0">收</el-tag>
                            <el-tag type="warning" v-if="row.billType === 1">付</el-tag>
                            <span style="margin-left: 10px;">{{row.price}}</span>
                        </div>
                    </template>
                </el-table-column>
                <el-table-column
                    label="应退日期">
                    <template slot-scope="{row}">
                        <el-date-picker v-model="row.planPayDate" value-format="yyyy-MM-dd" type="date" placeholder="选择日期"></el-date-picker>
                    </template>
                </el-table-column>
            </el-table>
            <div class="footer">
                åˆè®¡åº”收:<span>{{receivable}}</span>元, åˆè®¡åº”付:<span>{{meet}}</span>元
            </div>
        </div>
        <!--    åˆ›å»ºæ”¶æ¬¾è´¦å•    -->
        <AddCollectionBill ref="addCollectionBill" @getVal="getObjS" />
        <!--    åˆ›å»ºä»˜æ¬¾è´¦å•    -->
        <AddPaymentBill ref="AddPaymentBill" @getVal="getObjS" />
    </GlobalWindow>
</template>
<script>
  import GlobalWindow from '@/components/common/GlobalWindow'
  import BaseOpera from '@/components/base/BaseOpera'
  import AddCollectionBill from './addCollectionBill'
  import AddPaymentBill from './addPaymentBill'
  import { getUserList } from '@/api/system/user'
  import { backRent } from '@/api/contract'
  export default {
    name: "terminateLease",
    components: {
      GlobalWindow,
      AddCollectionBill,
      AddPaymentBill
    },
    extends: BaseOpera,
    data() {
      return {
        info: {},
        form: {
          id: null,
          btType: '',
          btDate: '',
          btUserId: '',
          btSignDate: '',
          btInfo: ''
        },
        rules: {
          btType: [
            { required: true, message: '请选择', trigger: 'blur' }
          ],
          btDate: [
            { required: true, message: '请选择', trigger: 'blur' }
          ],
          btUserId: [
            { required: true, message: '请选择', trigger: 'blur' }
          ],
          signDate: [
            { required: true, message: '请选择', trigger: 'blur' }
          ],
          btInfo: [
            { required: true, message: '请输入', trigger: 'blur' }
          ]
        },
        list: [],
        agentList: [],
        receivable: '',
        meet: ''
      }
    },
    watch: {
      info: {
        deep: true,
        immediate: true,
        handler(news, olds) {
          const arr = [...this.info.terminateList, ...this.info.depositList]
          let total1 = 0
          let total2 = 0
          arr.forEach(item => {
            if (item.billType === 0) {
              total1 += Number(item.price)
            } else if (item.billType === 1) {
              total2 += Number(item.price)
            }
          })
          this.receivable = total1
          this.meet = total2
        }
      }
    },
    methods: {
      open (title, info) {
        this.title = title
        this.info = info
        this.form.id = info.id
        this.info.billList.forEach(item => {
          this.$set(item, 'receivableFeeCopy', item.receivableFee)
          if ([2,3,7].includes(item.costType)) {
            this.$set(item, 'price', item.actReceivableFee)
          } else {
            this.$set(item, 'price', item.receivableFee)
          }
        })
        this.info.terminateList = this.info.canBackRentBills.filter(item => {
          if ([0,1,4,5,6].includes(item.costType)) {
            item.billTypeCopy = item.billType
            return item
          }
        })
        this.info.depositList = this.info.canBackRentBills.filter(item => {
          if ([2,3,7].includes(item.costType)) {
            item.billTypeCopy = item.billType
            return item
          }
        })
        this.getUser()
        this.visible = true
      },
      getObjS (obj) {
        this.info.terminateList.push(obj)
        this.info.terminateList.forEach(item => {
          item.receivableFee = Number(item.receivableFee) + 1
          item.receivableFee = Number(item.receivableFee) - 1
        })
      },
      confirm () {
        this.$refs.form.validate((valid) => {
          if (!valid) {
            return
          }
          this.isWorking = true
          let canBackRentBills = []
          let addBillList = []
          this.info.terminateList.forEach(item => {
            if (item.rowType && item.rowType === 1) {
              addBillList.push(item)
            } else {
              canBackRentBills.push(item)
            }
          })
          backRent({
            ...this.form,
            canBackRentBills: [...canBackRentBills, ...this.info.depositList],
            addBillList
          })
            .then(res => {
              this.visible = false
              this.$tip.apiSuccess('操作成功')
              this.$emit('success')
            })
            .finally(() => {
              this.isWorking = false
            })
        })
      },
      getUser () {
        getUserList({})
          .then(res => {
            this.agentList = res
          })
      },
      changeReceivableFee (num, row) {
        if (Number(num) > row.receivableFeeCopy) {
          row.receivableFee = ''
          row.price = 0
          this.$message.warning('不能大于原始应收付金额')
        } else {
          row.price = Number(num) - row.actReceivableFee
          // æ”¶
          if (row.billTypeCopy === 0) {
            if (row.price > 0) {
              row.billType = 0
            } else if (row.price < 0) {
              row.billType = 1
            } else {
              row.billType = 0
            }
          } else {
            if (row.price > 0) {
              row.billType = 1
            } else if (row.price < 0) {
              row.billType = 0
            } else {
              row.billType = 1
            }
          }
          // if (row.price > 0) {
          //   row.billType = 0
          // } else if (row.price < 0) {
          //   row.billType = 1
          // }
          row.price = String(row.price)
          if (row.price.indexOf('-') > 0) {
            row.price = row.price.substring(0, row.price.length)
          }
        }
      }
    }
  }
</script>
<style lang="scss" scoped>
    @import '@/assets/style/variables.scss';
    .main {
        width: 100%;
        .footer {
            width: 100%;
            display: flex;
            align-items: center;
            font-size: 14px;
            color: black;
            span {
                font-size: 14px;
                color: $primary-color;
            }
        }
        .main_head {
            width: 100%;
            padding: 10px 5px;
            box-sizing: border-box;
            display: flex;
            flex-direction: column;
            border-bottom: 1px solid #ececec;
            margin-bottom: 15px;
            span {
                color: black;
                font-size: 16px;
                font-weight: 500;
                margin-bottom: 8px;
                &:last-child {
                    margin: 0 !important;
                }
            }
        }
        .title {
            font-weight: 500;
            font-size: 16px;
            color: $primary-color;
            margin-bottom: 15px;
            display: flex;
            align-items: center;
            justify-content: space-between;
            span {
                font-weight: 500;
                font-size: 16px;
                color: $primary-color;
            }
        }
        .main_box {
            width: 100%;
            display: flex;
            align-items: start;
            margin-bottom: 15px;
            justify-content: space-between;
            .main_box_form {
                flex: 1;
                margin-right: 20px;
            }
            .main_box_list {
                width: 500px;
                flex-shrink: 0;
                .main_box_list_title {
                    font-size: 16px;
                    font-weight: 500;
                    color: $primary-color;
                    margin-bottom: 15px;
                }
            }
        }
    }
</style>
admin/src/views/contract/contractList.vue
@@ -6,27 +6,28 @@
      </template>
    </QueryForm>
    <div class="mt10">
      <el-button @click="handleEdit()" icon="el-icon-plus" type="primary">新建</el-button>
      <el-button @click="$refs.ContractEditRef.open('创建合同')" icon="el-icon-plus" type="primary">新建</el-button>
    </div>
    <el-table v-loading="loading" :data="list" stripe>
      <el-table-column prop="" label="客户名称" min-width="100" show-overflow-tooltip />
      <el-table-column prop="" label="开始日期" min-width="100" show-overflow-tooltip />
      <el-table-column prop="" label="结束日期" min-width="100" show-overflow-tooltip />
      <el-table-column prop="" label="租赁单价" min-width="100" show-overflow-tooltip />
      <el-table-column prop="" label="租赁面积" min-width="100" show-overflow-tooltip />
      <el-table-column prop="" label="签订日" min-width="100" show-overflow-tooltip />
      <el-table-column prop="" label="合同编号" min-width="100" show-overflow-tooltip />
      <el-table-column prop="" label="合同状态" min-width="100" show-overflow-tooltip>
        <template v-slot="scope">
          <span class="primaryColor">待执行</span>
          <span class="green">正常执行中</span>
          <span class="gary">已退租</span>
      <el-table-column prop="renterName" label="客户名称" min-width="100" show-overflow-tooltip />
      <el-table-column prop="startDate" label="开始日期" min-width="100" show-overflow-tooltip />
      <el-table-column prop="endDate" label="结束日期" min-width="100" show-overflow-tooltip />
<!--      <el-table-column label="租赁单价" min-width="100" show-overflow-tooltip></el-table-column>-->
      <el-table-column prop="totalArea" label="租赁面积" min-width="100" show-overflow-tooltip />
      <el-table-column prop="signDate" label="签订日" min-width="100" show-overflow-tooltip />
      <el-table-column prop="code" label="合同编号" min-width="100" show-overflow-tooltip />
      <el-table-column label="合同状态" min-width="90" fixed="right" show-overflow-tooltip>
        <template slot-scope="{row}">
          <span class="primaryColor" v-if="row.status === 0">待执行</span>
          <span class="green" v-if="row.status === 1">正常执行中</span>
          <span class="gary" v-if="row.status === 2">已到期</span>
          <span class="gary" v-if="row.status === 3">退租结算中</span>
          <span class="gary" v-if="row.status === 4">已退租</span>
        </template>
      </el-table-column>
      <el-table-column prop="" label="操作" min-width="100" show-overflow-tooltip>
      <el-table-column label="操作" min-width="90" fixed="right" show-overflow-tooltip>
        <template v-slot="scope">
          <span class="primaryColor cu" @click="handleDetail(scope.row)">查看详情</span>
          <span class="primaryColor cu" @click="handleDetail(scope.row.id)">查看详情</span>
        </template>
      </el-table-column>
    </el-table>
@@ -34,7 +35,7 @@
      <Pagination @size-change="handleSizeChange" @current-change="getList" :pagination="pagination" />
    </div>
    <ContractDetail ref="ContractDetailRef" />
    <ContractEdit ref="ContractEditRef" v-if="showEdit" />
    <ContractEdit ref="ContractEditRef" @success="getList(1)" />
  </div>
</template>
@@ -43,10 +44,11 @@
import QueryForm from '@/components/common/QueryForm'
import ContractDetail from './components/contractDetail'
import ContractEdit from './components/contractEdit.vue'
import { fetchList } from '@/api/contract'
import dayjs from 'dayjs'
import duration from 'dayjs/plugin/duration'
dayjs.extend(duration)
import { platformLogPage, getPlatformGroupList } from '@/api'
export default {
  components: {
    Pagination,
@@ -54,9 +56,8 @@
    ContractEdit,
    ContractDetail
  },
  data() {
  data () {
    return {
      showEdit: false,
      loading: false,
      pagination: {
        pageSize: 10,
@@ -69,74 +70,70 @@
      queryFormConfig: {
        formItems: [
          {
            filed: 'name',
            filed: 'renterName',
            type: 'input',
            label: '合同名称'
            label: '客户名称'
          },
          {
            filed: 'code',
            type: 'input',
            label: '合同编号'
          },
          {
            filed: 'status',
            type: 'select',
            label: '合同状态',
            options: [
              { value: 0, label: '待执行' },
              { value: 1, label: '正常执行中' },
              { value: 2, label: '已到期' },
              { value: 3, label: '退租结算中' },
              { value: 4, label: '已退租' },
            ]
          },
          {
            filed: 'selDate',
            type: 'datetimerange',
            placeholder: '应开始时间'
            label: '合同日期',
            placeholder: '合同日期'
          }
        ],
        online: true
      }
    }
  },
  created() {
    // this.getList()
    // this.getGroupList()
  created () {
    this.getList()
  },
  methods: {
    handleEdit(row) {
      this.showEdit = true
      this.$nextTick(() => {
        this.$refs.ContractEditRef.showModal = true
      })
      if(row && row.id){
      }else{
      }
    handleDetail (id) {
      this.$refs.ContractDetailRef.open('合同详情', id)
    },
    handleDetail(row) {
      this.$refs.ContractDetailRef.visible = true
      this.$refs.ContractDetailRef.getDetail(row.id)
    },
    getList(page) {
    getList (page) {
      const { pagination, filters } = this
      this.loading = true
      platformLogPage({
      fetchList({
        model: {
          ...filters,
          queryStatus: '6,7,8',
          beginWorkDateStart: filters.selDate && filters.selDate.length > 0 ? filters.selDate[0] : null,
          beginWorkDateEnd: filters.selDate && filters.selDate.length > 0 ? filters.selDate[1] : null,
          ...filters
        },
        sorts: [{ direction: 'DESC', property: 'param1' }],
        capacity: pagination.pageSize,
        page: page || pagination.page,
        page: page || pagination.page
      }).then(res => {
        this.loading = false
        this.list = res.records || []
        this.list.forEach(item => {
          item.inTypeTemp = item.inType == 0 ? '整托盘' : '件烟'
          item.taskOrigin = 'WMS获取'
          item.workTime = dayjs.duration(item.param3, 'seconds').format('H时m分s秒')
        })
        this.pagination.total = res.total || 0
      }, () => {
        this.loading = false
      })
    },
    clear() {
    clear () {
      this.filters = {}
      this.pagination.pageSize = 10
      this.pagination.page = 1
      this.getList()
    },
    handleSizeChange(capacity) {
    handleSizeChange (capacity) {
      this.pagination.pageSize = capacity
    }
  }
admin/src/views/finance/bull.vue
@@ -3,29 +3,57 @@
    <QueryForm v-model="filters" :query-form-config="queryFormConfig" @handleQuery="getList(1)" @clear="clear" />
    <div class="df_sb mt20">
      <div class="tabs">
        <div class="tab" :class="{ active: activeTabs == 0 }" @click="tabsClick(0)">收款账单</div>
        <div class="tab" :class="{ active: activeTabs == 1 }" @click="tabsClick(1)">付款账单</div>
        <div class="tab" :class="{ active: billType === 0 }" @click="tabsClick(0)">收款账单</div>
        <div class="tab" :class="{ active: billType === 1 }" @click="tabsClick(1)">付款账单</div>
      </div>
      <div class="btns">
        <el-button type="primary" @click="$refs.EditRef.open('创建收款账单')" icon="el-icon-plus"
        <el-button type="primary" @click="addOpen" icon="el-icon-plus"
          v-permissions="['business:ywpatrolline:create']">新建</el-button>
        <el-button @click="handleDetail" v-permissions="['business:ywpatrolline:create']">导出</el-button>
      </div>
    </div>
    <el-table v-loading="loading" :data="list" stripe>
      <el-table-column prop="" label="客户名称" min-width="100" show-overflow-tooltip />
      <el-table-column prop="code" label="楼宇名称" min-width="100" show-overflow-tooltip />
      <el-table-column prop="name" label="房间号" min-width="100" show-overflow-tooltip />
      <el-table-column prop="stautsName" label="合同编号" min-width="100" show-overflow-tooltip />
      <el-table-column prop="remark" label="结清状态" min-width="100" show-overflow-tooltip />
      <el-table-column prop="createTime" label="账单金额" min-width="100" show-overflow-tooltip />
      <el-table-column prop="createTime" label="应收金额" min-width="100" show-overflow-tooltip />
      <el-table-column prop="createTime" label="实收金额" min-width="100" show-overflow-tooltip />
      <el-table-column prop="createTime" label="需收金额" min-width="100" show-overflow-tooltip />
      <el-table-column prop="createTime" label="费用类型" min-width="100" show-overflow-tooltip />
      <el-table-column prop="createTime" label="是否逾期" min-width="100" show-overflow-tooltip />
      <el-table-column prop="createTime" label="计费周期" min-width="100" show-overflow-tooltip />
      <el-table-column prop="createTime" label="应收日期" min-width="100" show-overflow-tooltip />
      <el-table-column prop="customerName" label="客户名称" min-width="100" show-overflow-tooltip />
      <el-table-column label="房间" min-width="170" show-overflow-tooltip>
        <template slot-scope="{row}">
          <div style="display: flex; flex-direction: column;" v-if="row.roomPathName">
            <span v-for="(item, index) in row.roomPathName.split(';')" :key="index">{{item}}</span>
          </div>
        </template>
      </el-table-column>
      <el-table-column prop="contractCode" label="合同编号" min-width="100" show-overflow-tooltip />
      <el-table-column label="结清状态" min-width="100" show-overflow-tooltip>
        <template slot-scope="{row}">
          <span v-if="row.payStatus === 0">待收款</span>
          <span v-if="row.payStatus === 1">已结清</span>
          <span v-if="row.payStatus === 2">部分结清</span>
          <span v-if="row.payStatus === 3">待付款</span>
          <span v-if="row.payStatus === 4">待退款</span>
          <span v-if="row.payStatus === 5">已关闭</span>
        </template>
      </el-table-column>
      <el-table-column prop="totleFee" label="账单金额" min-width="100" show-overflow-tooltip />
      <el-table-column prop="receivableFee" label="应收金额" min-width="100" show-overflow-tooltip />
      <el-table-column prop="actReceivableFee" label="实收金额" min-width="100" show-overflow-tooltip />
      <el-table-column prop="needReceivableFee" label="需收金额" min-width="100" show-overflow-tooltip />
      <el-table-column label="费用类型" min-width="100" show-overflow-tooltip>
        <template slot-scope="{row}">
          <span v-if="row.feeType === 0">周期费用</span>
          <span v-if="row.feeType === 1">一次性费用</span>
        </template>
      </el-table-column>
      <el-table-column label="是否逾期" min-width="100" show-overflow-tooltip>
        <template slot-scope="{row}">
          <span v-if="row.isOverdue === 0">否</span>
          <span v-if="row.isOverdue === 1">是</span>
        </template>
      </el-table-column>
      <el-table-column label="计费周期" min-width="100" show-overflow-tooltip>
        <template slot-scope="{row}">
          {{ row.startDate }} ~ {{ row.endDate }}
        </template>
      </el-table-column>
      <el-table-column prop="planPayDate" label="应收日期" min-width="100" show-overflow-tooltip />
      <el-table-column prop="createTime" label="账单来源" min-width="100" show-overflow-tooltip />
      <el-table-column prop="statusName" label="合同状态" min-width="100" fixed="right" show-overflow-tooltip />
      <el-table-column label="操作" min-width="120" fixed="right">
@@ -39,6 +67,7 @@
    </div>
    <Edit ref="EditRef" @success="getList" />
    <Detail ref="DetailRef" @success="getList" />
    <BullEditFu ref="BullEditFu" @success="getList" />
  </div>
</template>
@@ -46,6 +75,7 @@
import Pagination from '@/components/common/Pagination'
import QueryForm from '@/components/common/QueryForm'
import Edit from './components/bullEdit.vue'
import BullEditFu from './components/bullEditFu.vue'
import Detail from './components/bullDetail.vue'
import { fetchList } from '@/api/bill'
export default {
@@ -53,9 +83,10 @@
    Pagination,
    QueryForm,
    Edit,
    Detail
    Detail,
    BullEditFu
  },
  data() {
  data () {
    return {
      loading: false,
      pagination: {
@@ -63,64 +94,71 @@
        page: 1,
        total: 0
      },
      activeTabs: 0,
      filters: {},
      billType: 0,
      filters: {
        status: 0
      },
      list: [],
      total: 0,
      statusMap: [
        { value: 0, label: '待收款' },
        { value: 1, label: '已结算' },
        { value: 2, label: '部分结清' },
        { value: 3, label: '待退款' },
        { value: 4, label: '待付款' },
      ],
      queryFormConfig: {
        formItems: [
          {
            filed: 'name',
            filed: 'customerName',
            type: 'input',
            label: '客户名称',
            label: '客户名称'
          },
          {
            filed: 'status',
            type: 'select',
            label: '账单状态',
            options: [
              { value: '0', label: '开启' },
              { value: '1', label: '关闭' },
              { value: 0, label: '开启' },
              { value: 1, label: '关闭' }
            ]
          },
          {
            filed: 'status',
            filed: 'payStatus',
            type: 'select',
            label: '结清状态',
            options: this.statusMap
            options: [
              { value: 0, label: '待收款' },
              { value: 1, label: '已结算' },
              { value: 2, label: '部分结清' },
              { value: 3, label: '待退款' },
              { value: 4, label: '待付款' }
            ]
          },
          {
            filed: 'selDate',
            type: 'daterange',
            label: '应收/付日期'
          },
        ],
        online: true
          }
        ]
      }
    }
  },
  created() {
  created () {
    this.getList()
  },
  methods: {
    addOpen () {
      if (this.billType === 0) {
        this.$refs.EditRef.open('创建收款账单')
      } else {
        this.$refs.BullEditFu.open('创建付款账单')
      }
    },
    getList (page) {
      const { pagination, filters } = this
      this.loading = true
      fetchList({
        model: {
          ...filters
          ...filters,
          billType: this.billType
        },
        capacity: pagination.pageSize,
        page: page || pagination.page
      }).then(res => {
        console.log(res)
        this.loading = false
        this.list = res.records || []
        this.list.forEach(item => {
@@ -131,19 +169,20 @@
        this.loading = false
      })
    },
    tabsClick(val) {
      this.activeTabs = val
    tabsClick (val) {
      this.billType = val
      this.getList()
    },
    handleDetail(row) {
      this.$refs.DetailRef.open()
    handleDetail (row) {
      this.$refs.DetailRef.open('账单详情', row.id)
    },
    clear() {
    clear () {
      this.filters = {}
      this.pagination.pageSize = 10
      this.pagination.page = 1
      this.getList()
    },
    handleSizeChange(capacity) {
    handleSizeChange (capacity) {
      this.pagination.pageSize = capacity
      this.getList()
    }
@@ -157,7 +196,6 @@
.tabs {
  display: flex;
  margin-bottom: 20px;
  display: flex;
  justify-content: center;
  .tab {
admin/src/views/finance/components/bullDetail.vue
@@ -3,39 +3,59 @@
    @confirm="confirm">
    <div class="home_title">
      <div class="left">
        <span class="mr10">付款方:xxx</span>
        <el-tag type="success">status</el-tag>
        <span class="mr10">付款方:{{info.customerName}}</span>
        <el-tag type="success" v-if="info.status === 0">开启</el-tag>
        <el-tag type="success" v-if="info.status === 1">关闭</el-tag>
      </div>
      <el-button plain type="primary" @click="$refs.flowingWater.open('创建收支流水')">新建收支流水</el-button>
      <el-button plain type="primary" @click="$refs.flowingWater.open(info.billType === 0 ? '创建收款账单' : '创建付款账单', {
        billType: info.billType,
        billId: info.id,
        costType: info.costType,
        costTypeName: returnText(info.costType),
        contractCode: info.contractCode,
        contractId: info.contractId,
        startDate: info.startDate,
        endDate: info.endDate,
        multifileList: [],
        date: `${info.startDate} ~ ${info.endDate}`,
        companyId: info.companyId,
        companyName: info.companyName,
        actReceivableFee: info.actReceivableFee
      })">新建收支流水</el-button>
    </div>
    <div class="line"></div>
    <div class="main">
      <div class="list" style="background: rgba(0,0,0,0); padding: 0; margin-bottom: 0;">
        <div class="item" style="flex: 1;">
          <div class="la">结清状态</div>
          <div class="val" style="margin-top: 10px;">已结清</div>
          <div class="val" style="margin-top: 10px;" v-if="info.payStatus === 0">待收款</div>
          <div class="val" style="margin-top: 10px;" v-if="info.payStatus === 1">已结清</div>
          <div class="val" style="margin-top: 10px;" v-if="info.payStatus === 2">部分结清</div>
          <div class="val" style="margin-top: 10px;" v-if="info.payStatus === 3">待付款</div>
          <div class="val" style="margin-top: 10px;" v-if="info.payStatus === 4">待退款</div>
          <div class="val" style="margin-top: 10px;" v-if="info.payStatus === 5">已关闭</div>
        </div>
        <div class="item" style="flex: 1;">
          <div class="la">应收金额(元)</div>
          <div class="val" style="margin-top: 10px;">1,000.00</div>
          <div class="val" style="margin-top: 10px;">{{info.receivableFee}}</div>
        </div>
        <div class="item" style="flex: 1;">
          <div class="la">实收金额(元)</div>
          <div class="val" style="margin-top: 10px;">1,000.00</div>
          <div class="val" style="margin-top: 10px;">{{info.actReceivableFee}}</div>
        </div>
        <div class="item" style="flex: 1;">
          <div class="la">需付金额(元)</div>
          <div class="val" style="margin-top: 10px;">1,000.00</div>
          <div class="val" style="margin-top: 10px;">{{info.needReceivableFee}}</div>
        </div>
        <div class="item" style="flex: 1;">
          <div class="la">应收日期</div>
          <div class="val" style="margin-top: 10px;">2024-11-16</div>
          <div class="val" style="margin-top: 10px;">{{info.planPayDate}}</div>
        </div>
      </div>
    </div>
    <div class="tabs">
      <div class="tab" :class="{ active: activeTabs == 0 }" @click="tabsClick(0)">基础信息</div>
      <div class="tab" :class="{ active: activeTabs == 1 }" @click="tabsClick(1)">账单明细</div>
<!--      <div class="tab" :class="{ active: activeTabs == 1 }" @click="tabsClick(1)">账单明细</div>-->
      <div class="tab" :class="{ active: activeTabs == 2 }" @click="tabsClick(2)">收支流水</div>
    </div>
    <div class="main">
@@ -43,31 +63,32 @@
      <div class="list" style="background: rgba(0,0,0,0); padding: 0;">
        <div class="item">
          <div class="la">账单类型</div>
          <div class="val">租金</div>
          <div class="val" v-if="info.billType === 0">收款</div>
          <div class="val" v-if="info.billType === 1">付款</div>
        </div>
        <div class="item">
          <div class="la">计费周期</div>
          <div class="val">2024-11-17 ~ 2025-11-17</div>
          <div class="val">{{info.startDate}} ~ {{info.endDate}}</div>
        </div>
        <div class="item">
          <div class="la">账单金额(元)</div>
          <div class="val">10000.00</div>
          <div class="val">{{info.totleFee}}</div>
        </div>
        <div class="item">
          <div class="la">账单编号</div>
          <div class="val">ZD20241117-0002</div>
          <div class="val">{{info.code}}</div>
        </div>
        <div class="item">
          <div class="la">合同编号</div>
          <div class="val">202411-0017</div>
          <div class="val">{{info.contractCode}}</div>
        </div>
        <div class="item">
          <div class="la">创建时间</div>
          <div class="val">2024-11-16 15:17:01</div>
          <div class="val">{{info.createDate}}</div>
        </div>
        <div class="item">
          <div class="la">付款方</div>
          <div class="val">XX公司</div>
          <div class="val">{{info.customerName}}</div>
        </div>
        <div class="item">
          <div class="la">经办人</div>
@@ -75,11 +96,11 @@
        </div>
        <div class="item">
          <div class="la">所属公司</div>
          <div class="val">XXX有限公司</div>
          <div class="val">{{info.companyName}}</div>
        </div>
        <div class="item">
          <div class="la">账单备注</div>
          <div class="val">这是备注内容</div>
          <div class="val">{{info.remark}}</div>
        </div>
        <div class="item"></div>
        <div class="item"></div>
@@ -87,102 +108,115 @@
      <div class="title">房源信息</div>
      <div class="list" style="background: rgba(0,0,0,0); padding: 0;">
        <el-table
          :data="tableData"
          :data="info.ywContractRoomList"
          border
          style="width: 100%">
          <el-table-column
            prop="date"
            prop="projectName"
            label="项目名称">
          </el-table-column>
          <el-table-column
            prop="name"
            prop="floorName"
            label="楼宇名称">
          </el-table-column>
          <el-table-column
            prop="address"
            label="楼层/房号">
            <template slot-scope="{row}">
              {{row.buildingName}}/{{row.roomName}}
            </template>
          </el-table-column>
          <el-table-column
            prop="address"
            prop="area"
            label="面积">
          </el-table-column>
        </el-table>
      </div>
      <div class="title">账单明细</div>
      <div class="list" style="background: rgba(0,0,0,0); padding: 0;">
        <el-table
          :data="tableData"
          border
          style="width: 100%">
          <el-table-column
            prop="date"
            label="费用类型">
          </el-table-column>
          <el-table-column
            prop="name"
            label="应收/付金额">
          </el-table-column>
          <el-table-column
            prop="address"
            label="实收金额">
          </el-table-column>
          <el-table-column
            prop="address"
            label="需收金额">
          </el-table-column>
          <el-table-column
            prop="address"
            label="计费周期">
          </el-table-column>
          <el-table-column
            prop="address"
            label="应收/付日期">
          </el-table-column>
          <el-table-column
            prop="address"
            label="备注">
          </el-table-column>
        </el-table>
      </div>
<!--      <div class="title">账单明细</div>-->
<!--      <div class="list" style="background: rgba(0,0,0,0); padding: 0;">-->
<!--        <el-table-->
<!--          :data="tableData"-->
<!--          border-->
<!--          style="width: 100%">-->
<!--          <el-table-column-->
<!--            prop="date"-->
<!--            label="费用类型">-->
<!--          </el-table-column>-->
<!--          <el-table-column-->
<!--            prop="name"-->
<!--            label="应收/付金额">-->
<!--          </el-table-column>-->
<!--          <el-table-column-->
<!--            prop="address"-->
<!--            label="实收金额">-->
<!--          </el-table-column>-->
<!--          <el-table-column-->
<!--            prop="address"-->
<!--            label="需收金额">-->
<!--          </el-table-column>-->
<!--          <el-table-column-->
<!--            prop="address"-->
<!--            label="计费周期">-->
<!--          </el-table-column>-->
<!--          <el-table-column-->
<!--            prop="address"-->
<!--            label="应收/付日期">-->
<!--          </el-table-column>-->
<!--          <el-table-column-->
<!--            prop="address"-->
<!--            label="备注">-->
<!--          </el-table-column>-->
<!--        </el-table>-->
<!--      </div>-->
      <div class="title">收支流水</div>
      <div class="list" style="background: rgba(0,0,0,0); padding: 0;">
        <el-table
          :data="tableData"
          :data="info.ywContractRevenueList"
          border
          style="width: 100%">
          <el-table-column
            prop="date"
            label="流水类型">
            <template slot-scope="{row}">
              <span v-if="row.revenueType === 0">收入</span>
              <span v-if="row.revenueType === 1">支出</span>
            </template>
          </el-table-column>
          <el-table-column
            prop="name"
            prop="customerName"
            label="对方单位名称">
          </el-table-column>
          <el-table-column
            prop="address"
            label="费用类型">
            <template slot-scope="{row}">
              <span v-if="row.payType === 0">现金</span>
              <span v-if="row.payType === 1">网银转账</span>
              <span v-if="row.payType === 2">POS机</span>
              <span v-if="row.payType === 3">支付宝</span>
              <span v-if="row.payType === 4">微信</span>
              <span v-if="row.payType === 5">转账支票</span>
              <span v-if="row.payType === 6">其他</span>
            </template>
          </el-table-column>
          <el-table-column
            prop="address"
            prop="payDateEnd"
            label="入账日期">
          </el-table-column>
          <el-table-column
            prop="address"
            prop="actReceivableFee"
            label="发生额">
          </el-table-column>
          <el-table-column
            prop="address"
            prop="createDate"
            label="创建时间">
          </el-table-column>
          <el-table-column
            prop="address"
            prop="remark"
            label="备注">
          </el-table-column>
        </el-table>
      </div>
    </div>
    <!--  åˆ›å»ºæµæ°´  -->
    <FlowingWater ref="flowingWater" />
    <FlowingWater ref="flowingWater" @success="getDetails" />
  </GlobalWindow>
</template>
@@ -190,6 +224,7 @@
import GlobalWindow from '@/components/common/GlobalWindow'
import BaseOpera from '@/components/base/BaseOpera'
import FlowingWater from './flowingWater'
import { getYwContractBillById } from '@/api/contract'
export default {
  components: {
    GlobalWindow,
@@ -206,11 +241,39 @@
    }
  },
  methods: {
    open (title, id) {
      this.title = title
      this.id = id
      this.getDetails()
    },
    getDetails () {
      getYwContractBillById(this.id)
        .then(res => {
          this.info = res
          this.visible = true
        })
    },
    tabsClick(val) {
      this.activeTabs = val
    },
    getDetail() {
    returnText (e) {
      if (e === 0) {
        return '租赁费'
      } else if (e === 1) {
        return '物业费'
      } else if (e === 2) {
        return '租赁押金'
      } else if (e === 3) {
        return '物业押金'
      } else if (e === 4) {
        return '水电费'
      } else if (e === 5) {
        return '杂项费'
      } else if (e === 6) {
        return '其他'
      } else if (e === 7) {
        return '保证金'
      }
    }
  }
}
admin/src/views/finance/components/bullEdit.vue
@@ -3,7 +3,7 @@
    @confirm="confirm">
    <div class="main">
      <div class="main_content">
        <el-form :model="param" label-position="top" ref="form" :rules="rules">
        <el-form :model="form" label-position="top" ref="form" :rules="rules">
          <div class="head">
            <div class="m_title">基础信息</div>
            <div class="tabs">
@@ -13,18 +13,20 @@
          </div>
          <div class="list">
            <el-form-item label="关联合同" prop="contractId">
              <el-select v-model="form.contractId" placeholder="请选择" clearable>
                <el-option v-for="(item, index) in contract" :key="index" :value="item.value" :label="item.name"></el-option>
              <el-select v-model="form.contractId" @change="changeContract" placeholder="请选择">
                <el-option v-for="(item, index) in contract" :key="index" :value="item.id" :label="item.code"></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="付款方" prop="customerName">
              <el-select v-model="form.customerName" filterable placeholder="请选择">
            <el-form-item label="付款方" prop="renterName">
                <el-input v-model="form.renterName" disabled placeholder="请输入应收金额" v-trim />
            </el-form-item>
            <el-form-item label="房源" prop="ywContractRoomList">
              <el-select v-model="form.ywContractRoomList" multiple placeholder="请选择">
                <el-option
                  v-for="(item, index) in payerList"
                  v-for="(item, index) in houseList"
                  :key="index"
                  :label="item.label"
                  :value="item.value">
                </el-option>
                  :value="item.id"
                  :label="item.projectName + item.buildingName + item.floorName + item.roomName" />
              </el-select>
            </el-form-item>
            <el-form-item label="费用类型" prop="costType">
@@ -38,25 +40,25 @@
                <el-option :value="6" label="其他"></el-option>
              </el-select>
            </el-form-item>
            <el-form-item label="计费周期" prop="startDate" v-if="form.feeType !== 1">
            <el-form-item label="计费周期" prop="date" v-if="form.feeType !== 1">
              <el-date-picker
                type="daterange"
                range-separator="至"
                v-model="date"
                v-model="form.date"
                @change="changeDate"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                value-format="yyyy-MM-dd"
                placeholder="请选择" />
            </el-form-item>
            <el-form-item label="应收金额" prop="receivableFee">
              <el-input v-model="form.receivableFee" placeholder="请输入应收金额" v-trim />
            <el-form-item label="应收金额" prop="totleFee">
              <el-input v-model="form.totleFee" placeholder="请输入应收金额" v-trim />
            </el-form-item>
            <el-form-item label="应收日期" prop="planPayDate">
              <el-date-picker type="date" v-model="form.planPayDate" value-format="yyyy-MM-dd" placeholder="请选择" />
            </el-form-item>
            <el-form-item label="所属公司" prop="companyId">
              <el-select v-model="form.companyId" placeholder="请选择" clearable>
              <el-select v-model="form.companyId" placeholder="请选择">
                <el-option
                  v-for="(item, index) in comparyList"
                  :key="index"
@@ -65,21 +67,10 @@
              </el-select>
            </el-form-item>
            <el-form-item style="width: 100%;" label="账单备注" prop="remark">
              <el-input type="textarea" :rows="5" v-model="param.remark" placeholder="请输入" />
              <el-input type="textarea" :rows="5" v-model="form.remark" placeholder="请输入" />
            </el-form-item>
          </div>
        </el-form>
      </div>
      <div class="main_house">
        <div class="title">请选择房源</div>
        <el-tree
          :data="houseList"
          show-checkbox
          node-key="id"
          :default-expanded-keys="[2, 3]"
          :default-checked-keys="[5]"
          :props="defaultProps">
        </el-tree>
      </div>
    </div>
    <div class="file_wrap">
@@ -90,187 +81,159 @@
          <el-button icon="el-icon-plus" plain>添加附件</el-button>
        </el-upload>
      </div>
      <el-table :data="param.list" stripe>
        <el-table-column prop="" label="附件名称" align="center" min-width="100" show-overflow-tooltip />
        <el-table-column prop="" label="操作人" align="center" min-width="100" show-overflow-tooltip />
        <el-table-column prop="" label="操作时间" align="center" min-width="100" show-overflow-tooltip />
        <el-table-column prop="" label="操作" align="center" min-width="100">
          <template v-slot="{ scope }">
            <span class="cu red">删除</span>
      <el-table :data="form.multifileList" stripe>
        <el-table-column prop="originname" label="附件名称" align="center" min-width="100" show-overflow-tooltip />
        <el-table-column prop="userName" label="操作人" align="center" min-width="100" show-overflow-tooltip />
        <el-table-column prop="createTime" label="操作时间" align="center" min-width="100" show-overflow-tooltip />
        <el-table-column label="操作" align="center" min-width="100">
          <template slot-scope="{row}">
            <span class="cu red" @click="dele(row.imgaddr)">删除</span>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <!--  -->
    <MemberSearch ref="MemberSearchRef" />
  </GlobalWindow>
</template>
<script>
import GlobalWindow from '@/components/common/GlobalWindow'
import BaseOpera from '@/components/base/BaseOpera'
import MemberSearch from '@/components/common/MemberSearch'
import { rules } from './config'
import { create } from '@/api/bill'
import { list as listAll } from '@/api/contract'
import { companyList } from '@/api/company'
import { Message, Loading } from 'element-ui'
import { getContractRoom } from '@/api/house'
import { mapState } from 'vuex'
export default {
  components: {
    GlobalWindow,
    MemberSearch
    GlobalWindow
  },
  computed: {
    ...mapState(['userInfo'])
  },
  extends: BaseOpera,
  data() {
  data () {
    return {
      form: {
        contractId: '',
        customerName: '',
        renterName: '',
        renterId: '',
        costType: '',
        type: '',
        companyId: '',
        remark: '',
        startDate: '',
        endDate: '',
        receivableFee: '',
        totleFee: '',
        feeType: 0,
        planPayDate: ''
        planPayDate: '',
        multifileList: [],
        ywContractRoomList: [],
        date: [],
        RoomName: ''
      },
      date: [],
      param: {},
      rules,
      timeTab: '0',
      loadingInstance: null,
      uploadImgUrl: process.env.VUE_APP_API_PREFIX + '/visitsAdmin/cloudService/public/uploadBatch',
      fileList: [],
      uploadData: {
        folder: 'HIDDEN_DANGER_FILE'
        folder: 'YW_CONTRACT_BILL'
      },
      contract: [],
      payerList: [],
      projectList: [],
      comparyList: [], // å…¬å¸
      renterList: [], // ç§Ÿå®¢
      contacts: [], // è”系人
      value: [],
      options: [
        {
          value: 1,
          label: '东南',
          children: [{
            value: 2,
            label: '上海',
            children: [
              { value: 3, label: '普陀' },
              { value: 4, label: '黄埔' },
              { value: 5, label: '徐汇' }
            ]
          }, {
            value: 7,
            label: '江苏',
            children: [
              { value: 8, label: '南京' },
              { value: 9, label: '苏州' },
              { value: 10, label: '无锡' }
            ]
          }, {
            value: 12,
            label: '浙江',
            children: [
              { value: 13, label: '杭州' },
              { value: 14, label: '宁波' },
              { value: 15, label: '嘉兴' }
            ]
          }]
        },
        {
          value: 17,
          label: '西北',
          children: [{
            value: 18,
            label: '陕西',
            children: [
              { value: 19, label: '西安' },
              { value: 20, label: '延安' }
            ]
          }, {
            value: 21,
            label: '新疆维吾尔族自治区',
            children: [
              { value: 22, label: '乌鲁木齐' },
              { value: 23, label: '克拉玛依' }
            ]
          }]
        }
      ],
      cactiveTabs: 0,
      paramCost: {},
      payMethods: [
        { name: '一次性付款', value: 0 },
        { name: '3个月一付', value: 1 },
        { name: '6个月一付', value: 2 },
        { name: '1年一付', value: 2 },
      ],
      unitOps: [
        { name: '元/m²·天', value: 0 },
        { name: '元/m²·月', value: 1 },
        { name: '元/天', value: 2 },
        { name: '元/月', value: 3 },
        { name: '元/å¹´', value: 4 },
        { name: '元/m²·年', value: 5 },
        { name: '元/场', value: 6 },
      ],
      houseList: [{
        id: 1,
        label: '一级 1',
        children: [{
          id: 4,
          label: '二级 1-1',
          children: [{
            id: 9,
            label: '三级 1-1-1'
          }, {
            id: 10,
            label: '三级 1-1-2'
          }]
        }]
      }, {
        id: 2,
        label: '一级 2',
        children: [{
          id: 5,
          label: '二级 2-1'
        }, {
          id: 6,
          label: '二级 2-2'
        }]
      }, {
        id: 3,
        label: '一级 3',
        children: [{
          id: 7,
          label: '二级 3-1'
        }, {
          id: 8,
          label: '二级 3-2'
        }]
      }],
      defaultProps: {
        children: 'children',
        label: 'label'
      }
      comparyList: [],
      houseList: []
    }
  },
  methods: {
    timeTabClick(val) {
    open (title, target) {
      this.title = title
      this.form.multifileList = []
      this.getListAll()
      this.getCompanyList()
      this.visible = true
      // æ–°å»º
      if (target == null) {
        this.$nextTick(() => {
          this.$refs.form.resetFields()
          this.form[this.configData['field.id']] = null
        })
        return
      }
      // ç¼–辑
      this.$nextTick(() => {
        for (const key in this.form) {
          this.form[key] = target[key]
        }
      })
    },
    changeContract (e) {
      this.form.renterName = this.contract.filter(item => {
        if (item.id === e) {
          return item
        }
      })[0].renterName
      this.getHouseDate()
    },
    getHouseDate () {
      getContractRoom({ contractId: this.form.contractId, type: 0 })
        .then(res => {
          this.houseList = res
        })
    },
    confirm () {
      this.$refs.form.validate((valid) => {
        if (!valid) return
        this.isWorking = true
        let obj = JSON.parse(JSON.stringify(this.form))
        obj.ywContractRoomList = obj.ywContractRoomList.map(id => {
          return { roomId: id }
        })
        obj.billType = 0
        create(obj)
          .then(() => {
            this.visible = false
            this.$tip.apiSuccess('新建成功')
            this.$emit('success')
          })
          .finally(() => {
            this.isWorking = false
          })
      })
    },
    dele (imgaddr) {
      this.form.multifileList.forEach((item, index) => {
        if (imgaddr === item.imgaddr) {
          this.form.multifileList.splice(index, 1)
        }
      })
    },
    openHouse () {
      this.$refs.selectHouse.open('选择房源', { contractId: this.form.contractId, type: 0 })
    },
    getCompanyList () {
      companyList({})
        .then(res => {
          this.comparyList = res
        })
    },
    getListAll () {
      listAll({})
        .then(res => {
          console.log(res)
          this.contract = res
        })
    },
    timeTabClick (val) {
      this.form.feeType = val
      if (val === 1) {
        this.form.startDate = ''
        this.form.endDate = ''
        this.form.date = []
      }
    },
    changeDate(e) {
    changeDate (e) {
      if (!e || e.length === 0) {
        this.form.startDate = ''
        this.form.endDate = ''
@@ -279,10 +242,7 @@
        this.form.endDate = e[1]
      }
    },
    handleRent() {
      this.$refs.MemberSearchRef.openModal()
    },
    beforeUpload(file) {
    beforeUpload (file) {
      this.loadingInstance = Loading.service({
        lock: true,
        text: 'Loading',
@@ -290,40 +250,33 @@
        background: 'rgba(0, 0, 0, 0.7)'
      })
    },
    uploadError() {
    uploadError () {
      this.$nextTick(() => { // ä»¥æœåŠ¡çš„æ–¹å¼è°ƒç”¨çš„ Loading éœ€è¦å¼‚步关闭
        if (this.loadingInstance) {
          this.loadingInstance.close()
        }
      })
    },
    uploadAvatarSuccess(file) {
      this.$nextTick(() => { // ä»¥æœåŠ¡çš„æ–¹å¼è°ƒç”¨çš„ Loading éœ€è¦å¼‚步关闭
    getDay () {
      const now = new Date();
      const year = now.getFullYear();
      const month = now.getMonth() + 1; // åŠ 1使其从1开始
      const day = now.getDate();
      const hours = now.getHours();
      const minutes = now.getMinutes();
      const seconds = now.getSeconds();
      return `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')} ${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
    },
    uploadAvatarSuccess (file) {
      this.$nextTick(() => {
        if (this.loadingInstance) {
          this.loadingInstance.close()
        }
      })
      console.log('file', file)
      const item = file.data[0]
      if (['.mp4', '.avi', '.flv', '.wmv'].some(char => item.imgaddr.includes(char))) {
        this.fileList.push({
          type: 1,
          fileurl: item.imgaddr,
          fileurlFull: item.url
        })
      } else {
        this.fileList.push({
          type: 0,
          fileurl: item.imgaddr,
          fileurlFull: item.url
        })
      }
      console.log('file', this.fileList)
      // this.$set(this.param, 'faceImg', file.imgurl)
      // this.$set(this.param, 'faceImgUrl', file.imgurlfull)
      this.form.multifileList.push({ ...item, fileurl: item.imgaddr, name: item.originname, userName: this.userInfo.realname, createTime: this.getDay() })
    },
    close() {
      this.isShowModal = false
    close () {
      this.$emit('close')
    }
  }
@@ -361,7 +314,7 @@
      .tabs {
        display: flex;
        margin-bottom: 20px;
        display: flex;
        align-items: center;
        justify-content: center;
        .tab {
admin/src/views/finance/components/bullEditFu.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,383 @@
<template>
    <GlobalWindow width="100%" :title="title" :visible.sync="visible" :confirm-working="isWorking" @close="close"
                  @confirm="confirm">
        <div class="main">
            <div class="main_content">
                <el-form :model="form" label-position="top" ref="form" :rules="rules">
                    <div class="head">
                        <div class="m_title">基础信息</div>
                    </div>
                    <div class="list">
                        <el-form-item label="关联合同" prop="contractId">
                            <el-select v-model="form.contractId" @change="changeContract" placeholder="请选择">
                                <el-option v-for="(item, index) in contract" :key="index" :value="item.id" :label="item.code"></el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="付款方" prop="renterName">
                            <el-input v-model="form.renterName" disabled placeholder="请输入应收金额" v-trim />
                        </el-form-item>
                        <el-form-item label="房源" prop="ywContractRoomList">
                            <el-select v-model="form.ywContractRoomList" multiple placeholder="请选择">
                                <el-option
                                    v-for="(item, index) in houseList"
                                    :key="index"
                                    :value="item.id"
                                    :label="item.projectName + item.buildingName + item.floorName + item.roomName" />
                            </el-select>
                        </el-form-item>
                        <el-form-item label="费用类型" prop="costType">
                            <el-select v-model="form.costType" placeholder="请选择">
                                <el-option :value="0" label="租赁费"></el-option>
                                <el-option :value="1" label="物业费"></el-option>
                                <el-option :value="2" label="租赁押金"></el-option>
                                <el-option :value="3" label="物业证金"></el-option>
                                <el-option :value="4" label="水电费"></el-option>
                                <el-option :value="5" label="杂项费"></el-option>
                                <el-option :value="6" label="其他"></el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="计费周期" prop="date">
                            <el-date-picker
                                type="daterange"
                                range-separator="至"
                                v-model="form.date"
                                @change="changeDate"
                                start-placeholder="开始日期"
                                end-placeholder="结束日期"
                                value-format="yyyy-MM-dd"
                                placeholder="请选择" />
                        </el-form-item>
                        <el-form-item label="应付金额" prop="totleFee">
                            <el-input v-model="form.totleFee" placeholder="请输入应收金额" v-trim />
                        </el-form-item>
                        <el-form-item label="应付日期" prop="planPayDate">
                            <el-date-picker type="date" v-model="form.planPayDate" value-format="yyyy-MM-dd" placeholder="请选择" />
                        </el-form-item>
                        <el-form-item label="所属公司" prop="companyId">
                            <el-select v-model="form.companyId" placeholder="请选择">
                                <el-option
                                    v-for="(item, index) in comparyList"
                                    :key="index"
                                    :value="item.id"
                                    :label="item.name" />
                            </el-select>
                        </el-form-item>
                        <el-form-item style="width: 100%;" label="账单备注" prop="remark">
                            <el-input type="textarea" :rows="5" v-model="form.remark" placeholder="请输入" />
                        </el-form-item>
                    </div>
                </el-form>
            </div>
        </div>
        <div class="file_wrap">
            <div class="head">
                <div>账单附件</div>
                <el-upload class="upload-demo" :show-file-list="false" :data="uploadData" :action="uploadImgUrl"
                           :on-success="uploadAvatarSuccess" :before-upload="beforeUpload" :on-error="uploadError">
                    <el-button icon="el-icon-plus" plain>添加附件</el-button>
                </el-upload>
            </div>
            <el-table :data="form.multifileList" stripe>
                <el-table-column prop="originname" label="附件名称" align="center" min-width="100" show-overflow-tooltip />
                <el-table-column prop="userName" label="操作人" align="center" min-width="100" show-overflow-tooltip />
                <el-table-column prop="createTime" label="操作时间" align="center" min-width="100" show-overflow-tooltip />
                <el-table-column label="操作" align="center" min-width="100">
                    <template slot-scope="{row}">
                        <span class="cu red" @click="dele(row.imgaddr)">删除</span>
                    </template>
                </el-table-column>
            </el-table>
        </div>
    </GlobalWindow>
</template>
<script>
  import GlobalWindow from '@/components/common/GlobalWindow'
  import BaseOpera from '@/components/base/BaseOpera'
  import { rules } from './config'
  import { create } from '@/api/bill'
  import { list as listAll } from '@/api/contract'
  import { companyList } from '@/api/company'
  import { Message, Loading } from 'element-ui'
  import { getContractRoom } from '@/api/house'
  import { mapState } from 'vuex'
  export default {
    name: 'bullEditFu',
    components: {
      GlobalWindow
    },
    computed: {
      ...mapState(['userInfo'])
    },
    extends: BaseOpera,
    data () {
      return {
        form: {
          contractId: '',
          renterName: '',
          renterId: '',
          costType: '',
          type: '',
          companyId: '',
          remark: '',
          startDate: '',
          endDate: '',
          totleFee: '',
          planPayDate: '',
          multifileList: [],
          ywContractRoomList: [],
          date: [],
          RoomName: ''
        },
        rules,
        loadingInstance: null,
        uploadImgUrl: process.env.VUE_APP_API_PREFIX + '/visitsAdmin/cloudService/public/uploadBatch',
        fileList: [],
        uploadData: {
          folder: 'YW_CONTRACT_BILL'
        },
        contract: [],
        payerList: [],
        comparyList: [],
        houseList: []
      }
    },
    methods: {
      open (title, target) {
        this.title = title
        this.form.multifileList = []
        this.getListAll()
        this.getCompanyList()
        this.visible = true
        // æ–°å»º
        if (target == null) {
          this.$nextTick(() => {
            this.$refs.form.resetFields()
            this.form[this.configData['field.id']] = null
          })
          return
        }
        // ç¼–辑
        this.$nextTick(() => {
          for (const key in this.form) {
            this.form[key] = target[key]
          }
        })
      },
      changeContract (e) {
        this.form.renterName = this.contract.filter(item => {
          if (item.id === e) {
            return item
          }
        })[0].renterName
        this.getHouseDate()
      },
      getHouseDate () {
        getContractRoom({ contractId: this.form.contractId, type: 0 })
          .then(res => {
            this.houseList = res
          })
      },
      confirm () {
        this.$refs.form.validate((valid) => {
          if (!valid) return
          this.isWorking = true
          let obj = JSON.parse(JSON.stringify(this.form))
          obj.ywContractRoomList = obj.ywContractRoomList.map(id => {
            return { roomId: id }
          })
          obj.feeType = 0
          obj.billType = 1
          create(obj)
            .then(() => {
              this.visible = false
              this.$tip.apiSuccess('新建成功')
              this.$emit('success')
            })
            .finally(() => {
              this.isWorking = false
            })
        })
      },
      dele (imgaddr) {
        this.form.multifileList.forEach((item, index) => {
          if (imgaddr === item.imgaddr) {
            this.form.multifileList.splice(index, 1)
          }
        })
      },
      openHouse () {
        this.$refs.selectHouse.open('选择房源', { contractId: this.form.contractId, type: 0 })
      },
      getCompanyList () {
        companyList({})
          .then(res => {
            this.comparyList = res
          })
      },
      getListAll () {
        listAll({})
          .then(res => {
            console.log(res)
            this.contract = res
          })
      },
      changeDate (e) {
        if (!e || e.length === 0) {
          this.form.startDate = ''
          this.form.endDate = ''
        } else {
          this.form.startDate = e[0]
          this.form.endDate = e[1]
        }
      },
      beforeUpload (file) {
        this.loadingInstance = Loading.service({
          lock: true,
          text: 'Loading',
          spinner: 'el-icon-loading',
          background: 'rgba(0, 0, 0, 0.7)'
        })
      },
      uploadError () {
        this.$nextTick(() => { // ä»¥æœåŠ¡çš„æ–¹å¼è°ƒç”¨çš„ Loading éœ€è¦å¼‚步关闭
          if (this.loadingInstance) {
            this.loadingInstance.close()
          }
        })
      },
      getDay () {
        const now = new Date();
        const year = now.getFullYear();
        const month = now.getMonth() + 1; // åŠ 1使其从1开始
        const day = now.getDate();
        const hours = now.getHours();
        const minutes = now.getMinutes();
        const seconds = now.getSeconds();
        return `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')} ${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
      },
      uploadAvatarSuccess (file) {
        this.$nextTick(() => {
          if (this.loadingInstance) {
            this.loadingInstance.close()
          }
        })
        const item = file.data[0]
        this.form.multifileList.push({ ...item, fileurl: item.imgaddr, name: item.originname, userName: this.userInfo.realname, createTime: this.getDay() })
      },
      close () {
        this.$emit('close')
      }
    }
  }
</script>
<style lang="scss" scoped>
    @import '@/assets/style/variables.scss';
    .cost_tabs {
        justify-content: flex-start;
        border: none;
        .tab {
            height: 36px;
            line-height: 36px;
            font-size: 14px;
        }
    }
    .main {
        display: flex;
        margin-bottom: 20px;
        .main_content {
            flex: 1;
            margin-right: 20px;
            .head {
                display: flex;
                align-items: center;
                justify-content: space-between;
                .tabs {
                    display: flex;
                    margin-bottom: 20px;
                    align-items: center;
                    justify-content: center;
                    .tab {
                        height: 14px;
                        line-height: 14px;
                        cursor: pointer;
                        border: 1px solid #ebebeb;
                        padding: 12px 24px;
                    }
                    .active {
                        font-weight: 500;
                        color: $primary-color;
                        border: 1px solid $primary-color;
                    }
                }
            }
            .list {
                display: flex;
                flex-wrap: wrap;
                .el-form-item {
                    width: 33.33%;
                    box-sizing: border-box;
                    padding: 0 12px;
                }
            }
        }
        .main_house {
            width: 320px;
            padding: 24px 12px;
            border: 1px solid #c3c6cd;
            border-radius: 2px;
            .title {
                font-size: 16px;
                font-weight: 500;
                margin-bottom: 30px;
            }
        }
    }
    .total {
        display: flex;
        justify-content: space-between;
        align-items: center;
        height: 32px;
        background-color: #e7e9f5;
        span {
            width: 160px;
            text-align: center;
        }
    }
    .file_wrap {
        padding: 20px 16px;
        border: 1px solid #c3c6cd;
        border-radius: 2px;
        .head {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
    }
    .m_title {
        font-weight: 500;
        font-size: 14px;
        margin-bottom: 15px;
        margin-top: 10px;
    }
</style>
admin/src/views/finance/components/config.js
@@ -1,3 +1,18 @@
const validateArr = (rule, value, callback) => {
  if (!value && value.length === 0) {
    callback(new Error('请选择'));
  } else {
    callback();
  }
};
export const rules = {
  name: [{ required: true, message: '请输入' }]
}
  contractId: [{ required: true, message: '不能为空' }],
  customerName: [{ required: true, message: '不能为空' }],
  ywContractRoomList: [{ required: true, validator: validateArr, trigger: 'blur' }],
  date: [{ required: true, validator: validateArr, trigger: 'blur' }],
  costType: [{ required: true, message: '不能为空' }],
  startDate: [{ required: true, message: '不能为空' }],
  totleFee: [{ required: true, message: '不能为空' }],
  planPayDate: [{ required: true, message: '不能为空' }],
  companyId: [{ required: true, message: '不能为空' }]
}
admin/src/views/finance/components/flowingWater.vue
@@ -1,37 +1,33 @@
<template>
    <GlobalWindow width="100%" :title="title" :visible.sync="isShowModal" :confirm-working="isWorking" @close="close"
    <GlobalWindow width="100%" :title="title" :visible.sync="visible" :confirm-working="isWorking" @close="close"
      @confirm="confirm">
        <div class="main">
            <div class="main_content">
                <el-form :model="param" label-position="top" ref="paramRef" :rules="rules">
                <el-form :model="form" label-position="top" ref="form" :rules="rules">
                    <div class="head">
                        <div class="m_title">流水信息</div>
                    </div>
                    <div class="list">
                        <el-form-item label="关联合同" prop="type">
                            <el-select v-model="param.type" placeholder="请选择" clearable>
                                <el-option v-for="item in types" :value="item.value" :label="item.name"></el-option>
                            </el-select>
                        <el-form-item label="关联合同" required>
                            <el-input v-model="form.contractCode" disabled placeholder="请输入" v-trim />
                        </el-form-item>
                        <el-form-item label="费用类型" prop="code">
                            <el-input v-model="param.code" placeholder="请输入合同编号" v-trim />
                        <el-form-item label="费用类型" required>
                            <el-input v-model="form.costTypeName" disabled placeholder="请输入" v-trim />
                        </el-form-item>
                        <el-form-item label="费单周期" prop="aaa">
                            <el-select v-model="param.code" placeholder="请选择" clearable>
                                <el-option v-for="item in agentList" :value="item.id" :label="item.name"></el-option>
                            </el-select>
                        <el-form-item label="计费周期" required>
                            <el-input v-model="form.date" disabled placeholder="请输入" v-trim />
                        </el-form-item>
                        <el-form-item label="应收金额" prop="">
                            <el-input v-model="param.code" placeholder="请输入实收金额" v-trim />
                        <el-form-item label="应收金额" prop="receivableFee">
                            <el-input v-model="form.receivableFee" placeholder="请输入" v-trim />
                        </el-form-item>
                        <el-form-item label="实收金额" prop="">
                            <el-input v-model="param.code" placeholder="请输入实收金额" v-trim />
                        <el-form-item label="实收金额" prop="actReceivableFee">
                            <el-input v-model="form.actReceivableFee" placeholder="请输入" v-trim />
                        </el-form-item>
                        <el-form-item label="入账日期" prop="">
                            <el-date-picker type="date" v-model="param.getDate" value-format="yyyy-MM-dd" placeholder="请选择" />
                        <el-form-item label="入账日期" prop="actPayDate">
                            <el-date-picker type="date" v-model="form.actPayDate" value-format="yyyy-MM-dd" placeholder="请选择" />
                        </el-form-item>
                        <el-form-item label="收款方式" prop="">
                            <el-select v-model="param.content" placeholder="请选择">
                        <el-form-item label="收款方式" prop="payType">
                            <el-select v-model="form.payType" placeholder="请选择">
                                <el-option label="现金" :value="1"></el-option>
                                <el-option label="网银转账" :value="2"></el-option>
                                <el-option label="POS机" :value="3"></el-option>
@@ -41,18 +37,16 @@
                                <el-option label="其它方式" :value="7"></el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="所属公司" prop="">
                            <el-select v-model="param.code" placeholder="请选择" clearable>
                                <el-option v-for="item in agentList" :value="item.id" :label="item.name"></el-option>
                        <el-form-item label="所属公司" prop="companyName">
                            <el-input disabled v-model="form.companyName" placeholder="请输入" />
                        </el-form-item>
                        <el-form-item label="收支账户" prop="accountId">
                            <el-select v-model="form.accountId" placeholder="请选择" clearable>
                                <el-option v-for="item in agentList" :value="item.id" :label="item.title"></el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="收支账户" prop="">
                            <el-select v-model="param.code" placeholder="请选择" clearable>
                                <el-option v-for="item in agentList" :value="item.id" :label="item.name"></el-option>
                            </el-select>
                        </el-form-item>
                        <el-form-item label="备注" prop="" style="width: 100%;">
                            <el-input type="textarea" :rows="6" v-model="param.content" placeholder="请输入" />
                        <el-form-item label="备注" prop="remark" style="width: 100%;">
                            <el-input type="textarea" :rows="6" v-model="form.remark" placeholder="请输入" />
                        </el-form-item>
                    </div>
                </el-form>
@@ -62,17 +56,17 @@
            <div class="head">
                <div>账单附件</div>
                <el-upload class="upload-demo" :show-file-list="false" :data="uploadData" :action="uploadImgUrl"
                           :on-success="uploadAvatarSuccess" :before-upload="beforeUpload" :on-error="uploadError">
                   :on-success="uploadAvatarSuccess" :before-upload="beforeUpload" :on-error="uploadError">
                    <el-button icon="el-icon-plus" plain>添加附件</el-button>
                </el-upload>
            </div>
            <el-table :data="param.list" stripe>
                <el-table-column prop="" label="附件名称" align="center" min-width="100" show-overflow-tooltip />
                <el-table-column prop="" label="操作人" align="center" min-width="100" show-overflow-tooltip />
                <el-table-column prop="" label="操作时间" align="center" min-width="100" show-overflow-tooltip />
                <el-table-column prop="" label="操作" align="center" min-width="100">
                    <template v-slot="scope">
                        <span class="cu red">删除</span>
            <el-table :data="form.multifileList" stripe>
                <el-table-column prop="name" label="附件名称" align="center" min-width="100" show-overflow-tooltip />
                <el-table-column prop="userName" label="操作人" align="center" min-width="100" show-overflow-tooltip />
                <el-table-column prop="createTime" label="操作时间" align="center" min-width="100" show-overflow-tooltip />
                <el-table-column label="操作" align="center" min-width="100">
                    <template slot-scope="{ row }">
                        <span class="cu red" @click="dele(row.imgaddr)">删除</span>
                    </template>
                </el-table-column>
            </el-table>
@@ -83,123 +77,77 @@
<script>
  import GlobalWindow from '@/components/common/GlobalWindow'
  import BaseOpera from '@/components/base/BaseOpera'
  import { rules } from './config'
  import { ywAccountList } from '@/api/bill'
  import { create } from '@/api/ywContractRevenue'
  import { Message, Loading } from 'element-ui'
  import { mapState } from 'vuex'
  export default {
    name: "flowingWater",
    components: {
      GlobalWindow
    },
    computed: {
      ...mapState(['userInfo'])
    },
    extends: BaseOpera,
    data() {
      return {
        isShowModal: false,
        title: '',
        activeTabs: '0',
        param: {},
        rules,
        timeTab: '0',
        form: {
          billId: '',
          billType: '',
          costType: '',
          contractCode: '',
          contractId: '',
          startDate: '',
          endDate: '',
          date: '',
          companyId: '',
          actReceivableFee: '',
          actPayDate: '',
          payType: '',
          companyName: '',
          remark: '',
          accountId: '',
          multifileList: [],
          costTypeName: ''
        },
        rules: {
          receivableFee: [
            { required: true, message: '请输入', trigger: 'blur' }
          ],
          actPayDate: [
            { required: true, message: '请选择', trigger: 'blur' }
          ],
          payType: [
            { required: true, message: '请选择', trigger: 'blur' }
          ],
          accountId: [
            { required: true, message: '请选择', trigger: 'blur' }
          ]
        },
        loadingInstance: null,
        uploadImgUrl: process.env.VUE_APP_API_PREFIX + '/visitsAdmin/cloudService/public/uploadBatch',
        fileList: [],
        uploadData: {
          folder: 'HIDDEN_DANGER_FILE'
          folder: 'YW_CONTRACT_BILL'
        },
        types: [
          { name: '物业+租赁合同', value: 0 },
          { name: '租赁合同', value: 1 },
          { name: '物业合同', value: 2 },
        ],
        agentList: [], //经办人
        projectList: [],
        comparyList: [], // å…¬å¸
        renterList: [], // ç§Ÿå®¢
        contacts: [], // è”系人
        value: [],
        options: [
          {
            value: 1,
            label: '东南',
            children: [{
              value: 2,
              label: '上海',
              children: [
                { value: 3, label: '普陀' },
                { value: 4, label: '黄埔' },
                { value: 5, label: '徐汇' }
              ]
            }, {
              value: 7,
              label: '江苏',
              children: [
                { value: 8, label: '南京' },
                { value: 9, label: '苏州' },
                { value: 10, label: '无锡' }
              ]
            }, {
              value: 12,
              label: '浙江',
              children: [
                { value: 13, label: '杭州' },
                { value: 14, label: '宁波' },
                { value: 15, label: '嘉兴' }
              ]
            }]
          },
          {
            value: 17,
            label: '西北',
            children: [{
              value: 18,
              label: '陕西',
              children: [
                { value: 19, label: '西安' },
                { value: 20, label: '延安' }
              ]
            }, {
              value: 21,
              label: '新疆维吾尔族自治区',
              children: [
                { value: 22, label: '乌鲁木齐' },
                { value: 23, label: '克拉玛依' }
              ]
            }]
          }
        ],
        cactiveTabs: 0,
        paramCost: {},
        payMethods: [
          { name: '一次性付款', value: 0 },
          { name: '3个月一付', value: 1 },
          { name: '6个月一付', value: 2 },
          { name: '1年一付', value: 2 },
        ],
        unitOps: [
          { name: '元/m²·天', value: 0 },
          { name: '元/m²·月', value: 1 },
          { name: '元/天', value: 2 },
          { name: '元/月', value: 3 },
          { name: '元/å¹´', value: 4 },
          { name: '元/m²·年', value: 5 },
          { name: '元/场', value: 6 },
        ],
        agentList: []
      }
    },
    created() {
      const { param } = this
      this.title = param.id ? '编辑收款账单' : '创建收款账单'
    },
    methods: {
      tabsClick(val) {
        this.activeTabs = val
      },
      timeTabClick(val) {
        this.timeTab = val
      },
      getDetail() {
      confirm () {
        this.$refs.form.validate((valid) => {
          if (!valid) return
          this.isWorking = true
          create(this.form)
            .then(() => {
              this.visible = false
              this.$tip.apiSuccess('创建成功')
              this.$emit('success')
            })
            .finally(() => {
              this.isWorking = false
            })
        })
      },
      handleRent() {
        this.$refs.MemberSearchRef.openModal()
@@ -207,13 +155,24 @@
      houseChange(e) {
        console.log(e)
        console.log(this.value)
      },
      getDates (companyId) {
        ywAccountList({
          companyId,
          isdeleted: 0,
          status: 0
        }).then(res => {
          this.agentList = res
        })
      },
      dele (imgaddr) {
        this.form.multifileList.forEach((item, index) => {
          if (imgaddr === item.imgaddr) {
            this.form.multifileList.splice(index, 1)
          }
        })
      },
      beforeUpload(file) {
        // if (['video/mp4', 'video/ogg', 'video/flv', 'video/avi', 'video/wmv', 'video/rmvb', 'image/jpeg', 'image/jpg', 'image/png', 'image/gif'].indexOf(file.type) == -1) {
        //   this.$message.error('请上传正确的视频/图片格式')
        //   return false
        // }
        this.loadingInstance = Loading.service({
          lock: true,
          text: 'Loading',
@@ -228,38 +187,39 @@
          }
        })
      },
      getDay () {
        const now = new Date()
        const year = now.getFullYear()
        const month = now.getMonth() + 1 // åŠ 1使其从1开始
        const day = now.getDate()
        const hours = now.getHours()
        const minutes = now.getMinutes()
        const seconds = now.getSeconds()
        return `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')} ${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
      },
      uploadAvatarSuccess(file) {
        this.$nextTick(() => { // ä»¥æœåŠ¡çš„æ–¹å¼è°ƒç”¨çš„ Loading éœ€è¦å¼‚步关闭
          if (this.loadingInstance) {
            this.loadingInstance.close()
          }
        })
        console.log('file', file)
        const item = file.data[0]
        if (['.mp4', '.avi', '.flv', '.wmv'].some(char => item.imgaddr.includes(char))) {
          this.fileList.push({
            type: 1,
            fileurl: item.imgaddr,
            fileurlFull: item.url
          })
        } else {
          this.fileList.push({
            type: 0,
            fileurl: item.imgaddr,
            fileurlFull: item.url
          })
        }
        console.log('file', this.fileList)
        // this.$set(this.param, 'faceImg', file.imgurl)
        // this.$set(this.param, 'faceImgUrl', file.imgurlfull)
        console.log(item)
        this.form.multifileList.push({ ...item, fileurl: item.imgaddr, name: item.originname, userName: this.userInfo.realname, createTime: this.getDay() })
      },
      close() {
        this.isShowModal = false
        this.$emit('close')
      },
      open(title, target) {
        this.title = title
        this.isShowModal = true
        this.visible = true
        this.$nextTick(() => {
          for (const key in this.form) {
            this.form[key] = target[key]
          }
        })
        console.log(this.form)
        this.getDates(target.companyId)
      }
    }
  }
admin/src/views/finance/components/selectHouse.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,185 @@
<template>
    <GlobalWindow
        width="100%"
        :title="title"
        :visible.sync="visible"
        :confirm-working="isWorking"
        @close="close"
        @confirm="confirm">
        <el-table
            :data="houseList"
            border
            @selection-change="handleSelectionChange"
            style="width: 100%">
            <el-table-column
                type="selection"
                width="55">
            </el-table-column>
            <el-table-column
                prop="projectName"
                label="项目名称">
            </el-table-column>
            <el-table-column
                prop="buildingName"
                label="楼宇名称">
            </el-table-column>
            <el-table-column
                prop="floorName"
                label="楼层名称">
            </el-table-column>
            <el-table-column
                prop="roomName"
                label="房间名称">
            </el-table-column>
        </el-table>
    </GlobalWindow>
</template>
<script>
import GlobalWindow from '@/components/common/GlobalWindow'
import BaseOpera from '@/components/base/BaseOpera'
import { getContractRoom } from '@/api/house'
export default {
  name: 'selectHouse',
  components: {
    GlobalWindow
  },
  extends: BaseOpera,
  data () {
    return {
      houseList: [],
      form: {},
      seleData: []
    }
  },
  methods: {
    open (title, target) {
      this.title = title
      this.form = target
      this.getAll()
    },
    getAll () {
      getContractRoom({ ...this.form })
        .then(res => {
          console.log(res)
          this.houseList = res
          this.visible = true
        })
    },
    handleSelectionChange (e) {
      console.log(e)
      this.seleData = e
    }
  }
}
</script>
<style lang="scss" scoped>
    @import '@/assets/style/variables.scss';
    .cost_tabs {
        justify-content: flex-start;
        border: none;
        .tab {
            height: 36px;
            line-height: 36px;
            font-size: 14px;
        }
    }
    .main {
        display: flex;
        margin-bottom: 20px;
        .main_content {
            flex: 1;
            margin-right: 20px;
            .head {
                display: flex;
                align-items: center;
                justify-content: space-between;
                .tabs {
                    display: flex;
                    margin-bottom: 20px;
                    align-items: center;
                    justify-content: center;
                    .tab {
                        height: 14px;
                        line-height: 14px;
                        cursor: pointer;
                        border: 1px solid #ebebeb;
                        padding: 12px 24px;
                    }
                    .active {
                        font-weight: 500;
                        color: $primary-color;
                        border: 1px solid $primary-color;
                    }
                }
            }
            .list {
                display: flex;
                flex-wrap: wrap;
                .el-form-item {
                    width: 33.33%;
                    box-sizing: border-box;
                    padding: 0 12px;
                }
            }
        }
        .main_house {
            width: 320px;
            padding: 24px 12px;
            border: 1px solid #c3c6cd;
            border-radius: 2px;
            .title {
                font-size: 16px;
                font-weight: 500;
                margin-bottom: 30px;
            }
        }
    }
    .total {
        display: flex;
        justify-content: space-between;
        align-items: center;
        height: 32px;
        background-color: #e7e9f5;
        span {
            width: 160px;
            text-align: center;
        }
    }
    .file_wrap {
        padding: 20px 16px;
        border: 1px solid #c3c6cd;
        border-radius: 2px;
        .head {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
    }
    .m_title {
        font-weight: 500;
        font-size: 14px;
        margin-bottom: 15px;
        margin-top: 10px;
    }
</style>
admin/src/views/finance/payments.vue
@@ -2,31 +2,50 @@
  <div class="main_app">
    <QueryForm v-model="filters" :query-form-config="queryFormConfig" @handleQuery="getList(1)" @clear="clear" />
    <div class="mt20">
      <el-button type="primary" @click="handleEdit()" icon="el-icon-plus"
        v-permissions="['business:ywpatrolline:create']">新建</el-button>
      <el-button @click="handleEdit()" v-permissions="['business:ywpatrolline:create']">导出</el-button>
    </div>
    <el-table v-loading="loading" :data="list" stripe>
      <el-table-column prop="" label="客户名称" min-width="100" show-overflow-tooltip />
      <el-table-column prop="" label="合同编号" min-width="100" show-overflow-tooltip />
      <el-table-column prop="" label="序号" min-width="100" show-overflow-tooltip />
      <el-table-column prop="" label="账号编号" min-width="100" show-overflow-tooltip />
      <el-table-column prop="" label="收支类型" min-width="100" show-overflow-tooltip />
      <el-table-column prop="" label="发生金额" min-width="100" show-overflow-tooltip />
      <el-table-column prop="" label="收款方式" min-width="100" show-overflow-tooltip />
      <el-table-column prop="" label="入账日期" min-width="100" show-overflow-tooltip />
      <el-table-column prop="" label="状态" min-width="100" show-overflow-tooltip>
        <template v-slot="scope">
          <el-switch v-model="scope.row.status" active-value="0" inactive-value="1">
          </el-switch>
      <el-table-column prop="customerName" label="客户名称" min-width="100" show-overflow-tooltip />
      <el-table-column prop="contractCode" label="合同编号" min-width="100" show-overflow-tooltip />
      <el-table-column label="房号" min-width="100" show-overflow-tooltip>
        <template slot-scope="{row}">
          <div style="display: flex; flex-direction: column;" v-if="row.roomPathName">
            <span v-for="(item, index) in row.roomPathName.split(';')" :key="index">{{item}}</span>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="操作" min-width="120" fixed="right">
      <el-table-column prop="billCode" label="账单编号" min-width="100" show-overflow-tooltip />
      <el-table-column label="收支类型" min-width="100" show-overflow-tooltip>
        <template slot-scope="{row}">
          <!-- <el-button type="text" @click="handleEdit(row)" icon="el-icon-edit"
            v-permissions="['business:category:update']">编辑</el-button> -->
          <el-button type="text" @click="deleteById(row)" icon="el-icon-delete"
            v-permissions="['business:category:delete']">退款</el-button>
          <span v-if="row.revenueType === 0">收入</span>
          <span v-if="row.revenueType === 1">支出</span>
        </template>
      </el-table-column>
      <el-table-column prop="actReceivableFee" label="发生金额" min-width="100" show-overflow-tooltip />
      <el-table-column label="收款方式" min-width="100" show-overflow-tooltip>
        <template slot-scope="{row}">
          <span v-if="row.payType === 0">现金</span>
          <span v-if="row.payType === 1">网银转账</span>
          <span v-if="row.payType === 2">POS机</span>
          <span v-if="row.payType === 3">支付宝</span>
          <span v-if="row.payType === 4">微信</span>
          <span v-if="row.payType === 5">转账支票</span>
          <span v-if="row.payType === 6">其他</span>
        </template>
      </el-table-column>
      <el-table-column prop="payDateEnd" label="入账日期" show-overflow-tooltip />
      <el-table-column prop="createDate" label="创建日期" show-overflow-tooltip />
      <el-table-column prop="realname" label="创建人" show-overflow-tooltip />
      <el-table-column label="状态" min-width="100" fixed="right" show-overflow-tooltip>
        <template slot-scope="{row}">
          <el-tag type="success" v-if="row.status === 0">开启</el-tag>
          <el-tag type="info" v-if="row.status === 1">关闭</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="操作" min-width="190" fixed="right">
        <template slot-scope="{row}">
          <el-button type="text">查看详情</el-button>
          <el-button type="text" @click="closeDW(row.id)" v-if="row.status !== 1">关闭流水</el-button>
        </template>
      </el-table-column>
    </el-table>
@@ -41,7 +60,7 @@
import Pagination from '@/components/common/Pagination'
import QueryForm from '@/components/common/QueryForm'
import Edit from './components/paymentsEdit.vue'
import { companyGetList, deleteById } from '@/api/business/company'
import { fetchList, close } from '@/api/ywContractRevenue'
export default {
  components: {
    Pagination,
@@ -63,22 +82,35 @@
      queryFormConfig: {
        formItems: [
          {
            filed: 'name',
            filed: 'customerName',
            type: 'input',
            label: '客户名称'
          },
          {
            filed: 'name',
            filed: 'revenueType',
            type: 'select',
            label: '收支类型'
            label: '收支类型',
            options: [
              { value: 0, label: '收入' },
              { value: 1, label: '支出' }
            ]
          },
          {
            filed: 'name',
            filed: 'payType',
            type: 'select',
            label: '收款方式'
            label: '收款方式',
            options: [
              { value: 0, label: '现金' },
              { value: 1, label: '网银转账' },
              { value: 2, label: 'POS机' },
              { value: 3, label: '支付宝' },
              { value: 4, label: '微信' },
              { value: 5, label: '转账支票' },
              { value: 6, label: '其他' }
            ]
          },
          {
            filed: 'name',
            filed: 'payDate',
            type: 'daterange',
            label: '入账日期'
          },
@@ -94,24 +126,34 @@
    getList(page) {
      const { pagination, filters } = this
      this.loading = true
      companyGetList({
      fetchList({
        model: {
          ...filters,
          type: 2
          ...filters
        },
        capacity: pagination.pageSize,
        page: page || pagination.page,
      }).then(res => {
        this.loading = false
        this.list = res.records || []
        this.list.forEach(item => {
          item.stautsName = item.status == 0 ? '正常' : item.status == 1 ? '损坏' : '报废'
        })
        this.pagination.total = res.total || 0
      }, () => {
        this.loading = false
      })
    },
    closeDW (id) {
      this.$confirm('确认关闭此流水吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        close(id)
          .then(res => {
            this.getList()
          })
      }).catch(() => {
      });
    },
    handleEdit(row) {
      this.showEdit = true
      this.$nextTick(() => {
server/system_gateway/src/main/resources/application.yml
@@ -82,7 +82,7 @@
  compression:
    enabled: true
    mime-types: application/json
  port: 10010
  port: 10030
  tomcat:
    max-swallow-size: -1
server/system_service/src/main/java/com/doumee/config/cloudfilter/LoginHandlerInterceptor.java
@@ -72,7 +72,6 @@
                                throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"没有该操作权限");
                            }
                        }
                    }
                  /* try {
                        CustomHttpServletRequestWrapper requestWrapper = (CustomHttpServletRequestWrapper)request;
server/system_service/src/main/java/com/doumee/core/utils/DateCompare.java
@@ -68,22 +68,22 @@
        int yearDays = day - DateUtil.daysBetweenDates(DateUtil.addYearToDate(fromDate,year),fromDate) ;
        if(yearDays!=0){
            yearFloat = yearFloat.add(new BigDecimal(yearDays).divide(new BigDecimal(365), 2,RoundingMode.FLOOR));
            yearFloat = yearFloat.add(new BigDecimal(1.0*yearDays).divide(new BigDecimal(365.0), 15,RoundingMode.HALF_UP));
        }
        int monthDays = day - DateUtil.daysBetweenDates(DateUtil.addMonthToDate(fromDate,month),fromDate) ;
        if(monthDays!=0){
            monthFloat = monthFloat.add(new BigDecimal(monthDays*12).divide(new BigDecimal(365), 2,RoundingMode.FLOOR));
            monthFloat = monthFloat.add(new BigDecimal(1.0*monthDays*12).divide(new BigDecimal(365.0), 15,RoundingMode.HALF_UP));
        }
        return DateCompare.builder().day(day).month(month).year(year).yearFloat(yearFloat).monthFloat(monthFloat).yearDays(yearDays).monthDays(monthDays).build();
    }
    public static void main(String[] args) {
        DateCompare dateCompare =   DateCompare.dayCompare(DateUtil.getDateFromString("2024-12-01 00:00:00"),DateUtil.getDateByString("2025-03-01 00:00:00")
                ,DateUtil.getDateFromString("2024-12-01 00:00:00"),DateUtil.getDateFromString("2024-12-03 00:00:00"));
        DateCompare dateCompare =   DateCompare.dayCompare(DateUtil.getDateFromString("2024-12-01 00:00:00"),DateUtil.getDateByString("2024-12-31 00:00:00")
                ,DateUtil.getDateFromString("2024-12-01 00:00:00"),DateUtil.getDateFromString("2024-12-02 00:00:00"));
        System.out.println(dateCompare.monthFloat);
        System.out.println(dateCompare.yearFloat);
        System.out.println(dateCompare.yearFloat);
        System.out.println(dateCompare.yearFloat);
        System.out.println(dateCompare.yearFloat.multiply(new BigDecimal(365.0)));
        System.out.println(new BigDecimal(29.0).divide(new BigDecimal(365.0),12,  RoundingMode.HALF_UP).multiply(new BigDecimal(365.0)));
    }
    public static DateCompare monthYearCompare(Date fromDate,Date toDate ){
        //开始时间往后延伸,除去有效时期
@@ -106,11 +106,11 @@
        int yearDays = day - DateUtil.daysBetweenDates(DateUtil.addYearToDate(fromDate,year),fromDate) ;
        if(yearDays!=0){
            yearFloat = yearFloat.add(new BigDecimal(yearDays).divide(new BigDecimal(365), 2,RoundingMode.FLOOR));
            yearFloat = yearFloat.add(new BigDecimal(1.0*yearDays).divide(new BigDecimal(365.0), 15,RoundingMode.HALF_UP));
        }
        int monthDays = day - DateUtil.daysBetweenDates(DateUtil.addMonthToDate(fromDate,month),fromDate) ;
        if(monthDays!=0){
            monthFloat = monthFloat.add(new BigDecimal(monthDays*12).divide(new BigDecimal(365), 2,RoundingMode.FLOOR));
            monthFloat = monthFloat.add(new BigDecimal(1.0*monthDays*12).divide(new BigDecimal(365.0), 15,RoundingMode.HALF_UP));
        }
        return DateCompare.builder().day(day).month(month).year(year).yearFloat(yearFloat).monthFloat(monthFloat).yearDays(yearDays).monthDays(monthDays).build();
    }
server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/YwAccountCloudController.java
@@ -78,6 +78,14 @@
        return ApiResponse.success(ywAccountService.findPage(pageWrap));
    }
    @ApiOperation("列表")
    @PostMapping("/list")
    @CloudRequiredPermission("business:ywaccount:query")
    public ApiResponse<List<YwAccount>> list (@RequestBody YwAccount model,@RequestHeader(Constants.HEADER_USER_TOKEN) String token) {
        return ApiResponse.success(ywAccountService.findList(model));
    }
    @ApiOperation("导出Excel")
    @PostMapping("/exportExcel")
    @CloudRequiredPermission("business:ywaccount:exportExcel")
server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/YwCustomerCloudController.java
@@ -78,6 +78,13 @@
        return ApiResponse.success(ywCustomerService.findPage(pageWrap));
    }
    @ApiOperation("列表")
    @PostMapping("/list")
    @CloudRequiredPermission("business:ywcustomer:query")
    public ApiResponse<List<YwCustomer>> list (@RequestBody YwCustomer model,@RequestHeader(Constants.HEADER_USER_TOKEN) String token) {
        return ApiResponse.success(ywCustomerService.findList(model));
    }
    @ApiOperation("导出Excel")
    @PostMapping("/exportExcel")
    @CloudRequiredPermission("business:ywcustomer:exportExcel")
server/visits/dmvisit_admin/src/main/resources/application.yml
@@ -68,7 +68,7 @@
  compression:
    enabled: true
    mime-types: application/json
  port: 10028
  port: 10038
  tomcat:
    max-swallow-size: -1
  servlet:
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/YwContractBill.java
@@ -62,11 +62,12 @@
    @ApiModelProperty(value = "开始时间")
    @ExcelColumn(name="计费开始日期",index = 10,width = 6,dateFormat = "yyyy-MM-dd")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date startDate;
    @ApiModelProperty(value = "结束时间")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @ExcelColumn(name="计费结束日期",index = 11,width = 6,dateFormat = "yyyy-MM-dd")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date endDate;
    @ApiModelProperty(value = "实际付款日")
@@ -75,7 +76,6 @@
    @ApiModelProperty(value = "计划付款日")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date planPayDate;
    @ApiModelProperty(value = "合同条款编码(关联yw_contract_detail)", example = "1")
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/YwContractRevenue.java
@@ -106,6 +106,7 @@
    @ApiModelProperty(value = "创建人名称")
    @ExcelColumn(name="创建人",index = 9,width = 10)
    @TableField(exist = false)
    private String realname;
    @ApiModelProperty(value = "关联房间数据", example = "1")
server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/YwWorkorder.java
@@ -152,6 +152,7 @@
    @ApiModelProperty(value = "项目名称")
    @TableField(exist = false)
    private String projectName;
    @ApiModelProperty(value = "楼宇名称")
    @TableField(exist = false)
    private String buildingName;
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/CompanyServiceImpl.java
@@ -604,7 +604,7 @@
            queryWrapper.le(Company::getFsDate, Utils.Date.getEnd(pageWrap.getModel().getFsDate()));
        }
        queryWrapper.orderByDesc(Company::getCreateDate);
        queryWrapper.leftJoin("company t1 on t1.id=t.parant_id");
        queryWrapper.leftJoin("company t1 on t1.id=t.parent_id");
        queryWrapper.selectAll(Company.class)
                .select("(select count(m.id) from member m where m.COMPANY_ID=t.id and m.ISDELETED=0) ",Company::getCountNum)
                .select("(select count(m.id) from yw_account m where m.COMPANY_ID=t.id and m.ISDELETED=0)",Company::getAccountNum) ;
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/SmsEmailServiceImpl.java
@@ -101,7 +101,7 @@
        if(Objects.nonNull(smsConfig) || Constants.equalsInteger(smsConfig.getStatus(),Constants.ZERO)){
            if(StringUtils.isNotBlank(smsConfig.getContent())){
                String content  = smsConfig.getContent().replace("{验证码}",code);
                emayService.sendSmsByHk(smsEmail.getPhone(),content);
                emayService.sendSingleSms(smsEmail.getPhone(),content);
                smsEmail.setRemark(code);
                smsEmail.setIsdeleted(Constants.ZERO);
                smsEmail.setCreateDate(new Date());
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwContractBillServiceImpl.java
@@ -66,7 +66,7 @@
                || Objects.isNull(ywContractBill.getBillType())
                || Objects.isNull(ywContractBill.getCompanyId())
                || com.github.xiaoymin.knife4j.core.util.CollectionUtils.isEmpty(ywContractBill.getYwContractRoomList())
                || Objects.nonNull(ywContractBill.getFeeType())
                || Objects.isNull(ywContractBill.getFeeType())
                || (Constants.equalsInteger(ywContractBill.getFeeType(),Constants.ZERO)&& (Objects.isNull(ywContractBill.getStartDate())
                || Objects.isNull(ywContractBill.getEndDate())))
        ){
@@ -87,6 +87,23 @@
        ywContractBill.setIsdeleted(Constants.ZERO);
        ywContractBill.setType(Constants.ONE);
        ywContractBill.setStatus(Constants.ZERO);
        if(Constants.equalsInteger(ywContractBill.getBillType(),Constants.ZERO)){
            ywContractBill.setPayStatus(Constants.ZERO);
        }else{
            ywContractBill.setPayStatus(Constants.THREE);
        }
        if(Constants.equalsInteger(ywContractBill.getFeeType(),Constants.ONE)){
            ywContractBill.setStartDate(ywContractBill.getPlanPayDate());
            ywContractBill.setEndDate(ywContractBill.getPlanPayDate());
        }
        //查询合同下的最大的序号
        List<YwContractBill> ywContractBillList = ywContractBillMapper.selectList(new QueryWrapper<YwContractBill>().lambda().eq(YwContractBill::getContractId,ywContract.getId()).orderByDesc(YwContractBill::getId));
        if(com.github.xiaoymin.knife4j.core.util.CollectionUtils.isNotEmpty(ywContractBillList)){
            ywContractBill.setSortnum(ywContractBillList.size() + 1 );
        }else{
            ywContractBill.setSortnum(Constants.ZERO);
        }
        ywContractBillMapper.insert(ywContractBill);
        //房源数据
@@ -172,8 +189,10 @@
                        .select(" ( select ifnull(sum(yw.ACT_RECEIVABLE_FEE),0) from  yw_contract_revenue yw where yw.bill_id = t.id and yw.status = 0 and yw.isdeleted = 0 ) as  actReceivableFee  ")
                        .selectAs(YwContract::getCode,YwContractBill::getContractCode)
                        .selectAs(YwCustomer::getName,YwContractBill::getCustomerName)
                        .selectAs(Company::getName,YwContractBill::getCompanyName)
                        .leftJoin(YwContract.class,YwContract::getId,YwContractBill::getContractId)
                        .leftJoin(YwCustomer.class,YwCustomer::getId,YwContract::getRenterId)
                        .leftJoin(Company.class,Company::getId,YwContract::getCompanyId)
                        .eq(YwContractBill::getIsdeleted,Constants.ZERO)
                        .eq(YwContractBill::getId,id));
        if(Objects.isNull(ywContractBill)){
@@ -245,6 +264,8 @@
                            YwCustomer::getName,model.getCustomerName())
                    .eq(Objects.nonNull(model)&&Objects.nonNull(model.getStatus()),
                            YwContractBill::getStatus,model.getStatus())
                    .eq(Objects.nonNull(model)&&Objects.nonNull(model.getBillType()),
                            YwContractBill::getBillType,model.getBillType())
                    .eq(Objects.nonNull(model)&&Objects.nonNull(model.getPayStatus()),
                            YwContractBill::getPayStatus,model.getPayStatus())
                    .eq(Objects.nonNull(model)&&Objects.nonNull(model.getType()),
@@ -261,11 +282,12 @@
                    ywContractBill.getReceivableFee().subtract(ywContractBill.getActReceivableFee())
            );
            //是否逾期
            if(Constants.equalsInteger(ywContractBill.getStatus(),Constants.ZERO) && (Constants.equalsInteger(ywContractBill.getPayStatus(),Constants.ZERO)
            || Constants.equalsInteger(ywContractBill.getPayStatus(),Constants.TWO)
            || Constants.equalsInteger(ywContractBill.getPayStatus(),Constants.THREE)
            || Constants.equalsInteger(ywContractBill.getPayStatus(),Constants.FOUR))
            && ywContractBill.getEndDate().getTime() < System.currentTimeMillis()){
            if(Constants.equalsInteger(ywContractBill.getStatus(),Constants.ZERO)
                && (Constants.equalsInteger(ywContractBill.getPayStatus(),Constants.ZERO)
                || Constants.equalsInteger(ywContractBill.getPayStatus(),Constants.TWO)
                || Constants.equalsInteger(ywContractBill.getPayStatus(),Constants.THREE)
                || Constants.equalsInteger(ywContractBill.getPayStatus(),Constants.FOUR))
            && ywContractBill.getPlanPayDate().getTime() < System.currentTimeMillis()){
                ywContractBill.setIsOverdue(Constants.ONE);
            }else{
                ywContractBill.setIsOverdue(Constants.ZERO);
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwContractRevenueServiceImpl.java
@@ -1,5 +1,6 @@
package com.doumee.service.business.impl;
import com.doumee.biz.system.SystemDictDataBiz;
import com.doumee.core.constants.ResponseStatus;
import com.doumee.core.exception.BusinessException;
import com.doumee.core.model.LoginUserInfo;
@@ -67,6 +68,10 @@
    @Autowired
    private SystemUserMapper systemUserMapper;
    @Autowired
    private SystemDictDataBiz systemDictDataBiz;
    @Override
    @Transactional(rollbackFor = {Exception.class,BusinessException.class})
@@ -112,8 +117,10 @@
        ywContractRevenue.setContractId(ywContractBill.getContractId());
        //根据收支情况 æ›´æ–°è´¦å•数据
        //查询当前账单下 å·²æ”¯ä»˜çš„费用
        List<YwContractRevenue> ywContractRevenueList = ywContractRevenueMapper.selectList(new QueryWrapper<YwContractRevenue>().lambda().eq(YwContractRevenue::getIsdeleted,Constants.ZERO)
        List<YwContractRevenue> ywContractRevenueList = ywContractRevenueMapper.selectList(new QueryWrapper<YwContractRevenue>()
                .lambda().eq(YwContractRevenue::getIsdeleted,Constants.ZERO)
                .eq(YwContractRevenue::getStatus,Constants.ZERO)
                .eq(YwContractRevenue::getBillId,ywContractRevenue.getBillId())
        );
        //已支付金额
        BigDecimal payTotal = BigDecimal.ZERO;
@@ -147,14 +154,14 @@
            //待支付的流水 å¦‚果为收入 åˆ™æ¯”对 é‡‘额值  å¦‚果是支出 åˆ™èŽ·å–ç»å¯¹å€¼ è¿›è¡Œå¯¹æ¯”
            if(Constants.equalsInteger(ywContractRevenue.getRevenueType(),Constants.ZERO)){
                //如果支付金额 å¤§äºŽ å¾…支付金额 åˆ™æç¤ºå¼‚常 å¦‚果支付金额小于 å¾…支付金额 åˆ™çŠ¶æ€ä¸å˜åŒ– å…¶ä»–状态 å¼‚常
                if(waitPayTotal.compareTo(ywContractRevenue.getActReceivableFee())>Constants.ZERO){
                if(waitPayTotal.compareTo(ywContractRevenue.getActReceivableFee())<Constants.ZERO){
                    throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"请输入正确的金额!");
                }else if(waitPayTotal.compareTo(ywContractRevenue.getActReceivableFee())==Constants.ZERO){
                    ywContractBill.setPayStatus(Constants.ONE);
                }
            }else{
                waitPayTotal = waitPayTotal.abs();
                if(waitPayTotal.compareTo(ywContractRevenue.getActReceivableFee())>Constants.ZERO){
                if(waitPayTotal.compareTo(ywContractRevenue.getActReceivableFee())<Constants.ZERO){
                    throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"请输入正确的金额!");
                }else if(waitPayTotal.compareTo(ywContractRevenue.getActReceivableFee())==Constants.ZERO){
                    ywContractBill.setPayStatus(Constants.ONE);
@@ -239,6 +246,26 @@
       this.getRecordData(ywContractRevenue);
        //附件数据
        List<Multifile> multifileList = multifileMapper.selectJoinList(Multifile.class,new MPJLambdaWrapper<Multifile>()
                .selectAll(Multifile.class)
                .selectAs(SystemUser::getRealname,Multifile::getUserName)
                .leftJoin(SystemUser.class,SystemUser::getId,Multifile::getCreator)
                .eq(Multifile::getObjId,id)
                .eq(Multifile::getIsdeleted,Constants.ZERO)
                .eq(Multifile::getObjType,Constants.MultiFile.FN_CONTRACT_REVENUE_FILE.getKey()));
        if(com.github.xiaoymin.knife4j.core.util.CollectionUtils.isNotEmpty(multifileList)){
            String path = systemDictDataBiz.queryByCode(Constants.FTP,Constants.FTP_RESOURCE_PATH).getCode()
                    +systemDictDataBiz.queryByCode(Constants.FTP,Constants.YW_CONTRACT_BILL).getCode();
            for (Multifile multifile:multifileList) {
                if(StringUtils.isNotBlank(multifile.getFileurl())){
                    multifile.setFileurlFull(path + multifile.getFileurl());
                }
            }
            ywContractRevenue.setMultifileList(multifileList);
        }
        return ywContractRevenue;
    }
@@ -289,11 +316,11 @@
        if(Objects.isNull(ywContract)){
            throw new BusinessException(ResponseStatus.DATA_EMPTY);
        }
        if(Constants.equalsInteger(ywContract.getStatus(),Constants.THREE)){
        if(Constants.equalsInteger(ywContract.getStatus(),Constants.FOUR)){
            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"合同状态已流转,无法操作");
        }
        if(Constants.equalsInteger(ywContractBill.getPayStatus(),Constants.ONE)
            || Constants.equalsInteger(ywContractBill.getPayStatus(),Constants.TWO)){
            || Constants.equalsInteger(ywContractBill.getPayStatus(),Constants.FIVE)){
            throw new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"账单状态已流转,无法操作");
        }
        //查询账单下 æ‰€æœ‰çš„账单
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwContractRoomServiceImpl.java
@@ -96,7 +96,7 @@
                .selectAs(YwProject::getName, YwRoom::getProjectName)
                .selectAs(YwFloor::getName,YwRoom::getFloorName)
                .selectAs(YwBuilding::getName,YwRoom::getBuildingName)
                .selectAs(YwRoom::getName,YwContractRoom::getRoomName)
                .selectAs(YwRoom::getCode,YwContractRoom::getRoomName)
                .leftJoin(YwRoom.class,YwRoom::getId,YwContractRoom::getRoomId)
                .leftJoin(YwFloor.class,YwFloor::getId,YwRoom::getFloor)
                .leftJoin(YwProject.class,YwProject::getId,YwRoom::getProjectId)
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwContractServiceImpl.java
@@ -394,16 +394,7 @@
                ywContractBillMapper.updateById(b);
            }
        }
        int yjNoBills =0;
        if(yjBills.size()>0){
            // å¦‚果是押金或者保证金,不支持退款,保持原来的状态, 0=租赁费;1=物业费;2=租赁押金;3=物业押金;4=水电费;5=杂项费;6=其他;7=保证金
            for(YwContractBill bill : yjBills){
               if(!Constants.equalsInteger(bill.getPayStatus(),Constants.ONE) ){
                   //如果是未结清押金
                   yjNoBills ++;
               }
            }
        }
        BigDecimal totalBackFee = new BigDecimal(0);
        if(canBills.size()>0){
            //直接关闭关闭账单
@@ -416,10 +407,10 @@
                    fee = Constants.formatBigdecimal(b.getActReceivableFee()).subtract(editBill.getReceivableFee());
                    if(fee.compareTo(new BigDecimal(0))== 0){
                        //如果费用正好,则修改账单信息为已结清
                        b.setStatus(Constants.ONE);
                        b.setPayStatus(Constants.ONE);
                    }else if(fee.compareTo(new BigDecimal(0))> 0){
                        //如果需要进行退款,更新账单信息为待退款
                        b.setStatus(Constants.FOUR);
                        b.setPayStatus(Constants.FOUR);
                    }else if(fee.compareTo(new BigDecimal(0)) < 0){
                        //如果账单还有款待收,则保持状态不变
                    }
@@ -444,6 +435,10 @@
                addBill.setContractId(param.getId());
                addBill.setType(Constants.ONE);
                addBill.setStatus(Constants.ZERO);
                if(Constants.equalsInteger(addBill.getFeeType(),Constants.ONE)){
                    addBill.setStartDate(addBill.getPlanPayDate());
                    addBill.setEndDate(addBill.getPlanPayDate());
                }
                if(Constants.equalsInteger(addBill.getBillType(),Constants.ZERO)){
                    //如果是收款
                    totalBackFee = totalBackFee.add(Constants.formatBigdecimal(addBill.getActReceivableFee()));
@@ -466,6 +461,33 @@
                newBills.add(addBill);
            }
            ywContractBillMapper.insert(param.getAddBillList());//批量插入数据
        }
        int yjNoBills =0;
        if(yjBills.size()>0){
            // å¦‚果是押金或者保证金,不支持退款,保持原来的状态, 0=租赁费;1=物业费;2=租赁押金;3=物业押金;4=水电费;5=杂项费;6=其他;7=保证金
            for(YwContractBill bill : yjBills){
                if(!Constants.equalsInteger(bill.getPayStatus(),Constants.ONE) ){
//                    YwContractBill b = new YwContractBill();
//                    //付款状态:0=待收款;1=已结清;2=部分结清;3=待付款;4=待退款;5=已关闭
//                    //如果账单信息做了编辑,金额计算 å®žæ”¶é‡‘额 å’Œ ä¿®æ”¹åŽåº”收金额作对比,判断是否应该退款
//                    BigDecimal fee = Constants.formatBigdecimal(bill.getActReceivableFee()).subtract(bill.getReceivableFee());
//                    if(fee.compareTo(new BigDecimal(0))== 0){
//                        //如果费用正好,则修改账单信息为已结清
//                        b.setPayStatus(Constants.ONE);
//                    }else if(fee.compareTo(new BigDecimal(0))> 0){
//                        //如果需要进行退款,更新账单信息为待退款
//                        b.setPayStatus(Constants.FOUR);
//                    }
//                    b.setId(bill.getId());
//                    b.setEditDate(param.getEditDate());
//                    b.setEditor(param.getEditor());
//                    b.setReceivableFee(BigDecimal.ZERO);
//                    ywContractBillMapper.updateById(b);
                    //如果是未结清押金
                    yjNoBills ++;
                }
            }
        }
        param.setBtWaitBill(canBills.size() + newBills.size()+yjNoBills);//未清算的账单数量
        param.setBtCLoseBill(closeBills.size());
@@ -649,7 +671,10 @@
        bill.setType(Constants.ZERO);
        bill.setCostType(type);
        bill.setPlanPayDate(bill.getStartDate());
        bill.setTotleFee(type==Constants.THREE?model.getZlDeposit():model.getWyDeposit());//押金费用
        bill.setTotleFee(type==Constants.TWO?
                Objects.isNull(model.getZlDeposit())?BigDecimal.ZERO:model.getZlDeposit()
                :
                Objects.isNull(model.getWyDeposit())?BigDecimal.ZERO:model.getWyDeposit());//押金费用
        bill.setReceivableFee(bill.getTotleFee());
        bill.setBillType(Constants.ZERO);
        bill.setPayStatus(Constants.ZERO);
@@ -762,14 +787,10 @@
            bill.setTotleFee(totalFee);
            bill.setReceivableFee(totalFee);
            bill.setBillType(Constants.ZERO);
            bill.setCompanyId(model.getCompanyId());
            list.add(bill);
        }
    }
    private BigDecimal getTotalFeeByStartEnd(YwContract model, YwContractDetail d, YwContractBill bill,Date freeStart,Date freeEnd) {
        BigDecimal totalFee = new BigDecimal(0);
        DateCompare dateCompare =   DateCompare.dayCompare(bill.getStartDate(),DateUtil.addDaysToDate(bill.getEndDate(),1),freeStart,DateUtil.addDaysToDate(freeEnd,1));
@@ -1226,7 +1247,7 @@
                    }else  if(Constants.equalsInteger(bill.getPayStatus(),Constants.ONE) ){
                        if(bill.getEndDate().getTime()<nowStart){
                            //如果已结清,账单直接关闭
                          continue;
                            continue;
                        }
                        model.getCanBackRentBills().add(bill);
                    }else  if(Constants.equalsInteger(bill.getPayStatus(),Constants.TWO) ){
@@ -1248,10 +1269,18 @@
    @Override
    public List<YwContract> findList(YwContract ywContract) {
        QueryWrapper<YwContract> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(YwContract::getIsdeleted,Constants.ZERO);
        wrapper.lambda().in(YwContract::getStatus,Constants.ZERO,Constants.ONE,Constants.TWO);
        return ywContractMapper.selectList(wrapper);
        return ywContractMapper.selectJoinList(YwContract.class,new MPJLambdaWrapper<YwContract>().selectAll(YwContract.class )
                .selectAs(Company::getName,YwContract::getCompanyName )
                .selectAs(SystemUser::getRealname,YwContract::getUserName )
                .selectAs(YwCustomer::getName,YwContract::getRenterName )
                .selectAs(YwProject::getName,YwContract::getProjectName )
                .leftJoin(Company.class,Company::getId,YwContract::getCompanyId)
                .leftJoin(SystemUser.class,SystemUser::getId,YwContract::getUserId)
                .leftJoin(SystemUser.class,SystemUser::getId,YwContract::getCreator)
                .leftJoin(YwProject.class,YwProject::getId,YwContract::getProjectId)
                .leftJoin(YwCustomer.class,YwCustomer::getId,YwContract::getRenterId)
                .eq(YwContract::getIsdeleted,Constants.ZERO)
                .in(YwContract::getStatus,Constants.ZERO,Constants.ONE,Constants.TWO));
    }
  
    @Override
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwCustomerServiceImpl.java
@@ -175,9 +175,16 @@
    }
    @Override
    public List<YwCustomer> findList(YwCustomer ywCustomer) {
        QueryWrapper<YwCustomer> wrapper = new QueryWrapper<>(ywCustomer);
        return ywCustomerMapper.selectList(wrapper);
    public List<YwCustomer> findList(YwCustomer model) {
        return ywCustomerMapper.selectJoinList(YwCustomer.class,
                new MPJLambdaWrapper<YwCustomer>()
                        .selectAll(YwCustomer.class)
                        .selectAs(Member::getName,YwCustomer::getMemberName)
                        .selectAs(Member::getPhone,YwCustomer::getMemberPhone)
                        .leftJoin(Member.class,Member::getId,YwCustomer::getMemberId)
                        .eq(YwCustomer::getIsdeleted,Constants.ZERO)
                        .like(Objects.nonNull(model)&&StringUtils.isNotBlank(model.getName()),YwCustomer::getName,model.getName())
                        .orderByDesc(YwCustomer::getCreateDate)) ;
    }
  
    @Override
server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/YwWorkorderServiceImpl.java
@@ -410,7 +410,8 @@
            queryWrapper.eq(YwWorkorder::getRemark, pageWrap.getModel().getRemark());
        }
        if (pageWrap.getModel().getStatus() != null) {
            queryWrapper.eq(YwWorkorder::getStatus, pageWrap.getModel().getStatus());
            queryWrapper.eq(!Constants.equalsInteger(pageWrap.getModel().getStatus(),-1),YwWorkorder::getStatus, pageWrap.getModel().getStatus());
            queryWrapper.in(Constants.equalsInteger(pageWrap.getModel().getStatus(),-1),YwWorkorder::getStatus, Constants.ZERO,Constants.ONE);
        }
        if (pageWrap.getModel().getSortnum() != null) {
            queryWrapper.eq(YwWorkorder::getSortnum, pageWrap.getModel().getSortnum());