收款计划
parent
0fb01cd478
commit
05f5087306
|
|
@ -5,14 +5,18 @@ export interface ContractVO {
|
|||
id: number
|
||||
name: string
|
||||
no: string
|
||||
customerId: number[]
|
||||
customer?:{
|
||||
customerId: number
|
||||
customerName?: string
|
||||
otherCustomerId: number[]
|
||||
otherCustomer?:{
|
||||
id: number
|
||||
name: string
|
||||
}
|
||||
|
||||
businessId: number
|
||||
businessName: string
|
||||
deptId: number
|
||||
deptName?: string
|
||||
contactLastTime: Date
|
||||
ownerUserId: number
|
||||
ownerUserName?: string
|
||||
|
|
@ -38,6 +42,8 @@ export interface ContractVO {
|
|||
creator: string
|
||||
creatorName: string
|
||||
updateTime?: Date
|
||||
picUrls?: string[]
|
||||
fileUrls?: string[]
|
||||
products?: [
|
||||
{
|
||||
id: number
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ export interface ReceivableVO {
|
|||
id: number
|
||||
no: string
|
||||
planId?: number
|
||||
period?: number // 期数
|
||||
customerId?: number
|
||||
customerName?: string
|
||||
contractId?: number
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ export interface ReceivablePlanVO {
|
|||
remindTime: Date
|
||||
customerId: number
|
||||
customerName?: string
|
||||
deptId: number
|
||||
deptName?: string
|
||||
contractId?: number
|
||||
contractNo?: string
|
||||
ownerUserId: number
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ export interface DeptVO {
|
|||
phone: string
|
||||
email: string
|
||||
createTime: Date
|
||||
type: number
|
||||
}
|
||||
|
||||
// 查询部门(精简)列表
|
||||
|
|
@ -17,6 +18,11 @@ export const getSimpleDeptList = async (): Promise<DeptVO[]> => {
|
|||
return await request.get({ url: '/system/dept/simple-list' })
|
||||
}
|
||||
|
||||
// 查询部门(精简)列表
|
||||
export const querySimpleDeptList = async () => {
|
||||
return await request.get({ url: '/system/dept/query-list?type=2'})
|
||||
}
|
||||
|
||||
// 查询部门列表
|
||||
export const getDeptPage = async (params: PageParam) => {
|
||||
return await request.get({ url: '/system/dept/list', params })
|
||||
|
|
|
|||
|
|
@ -0,0 +1,147 @@
|
|||
<template>
|
||||
<div>
|
||||
<div v-if="loading" class="loading-container">
|
||||
<el-skeleton :rows="5" animated />
|
||||
</div>
|
||||
<div v-else class="attachment-container">
|
||||
<!-- 图片展示部分 -->
|
||||
<div class="section" v-if="picUrls?.length">
|
||||
<h3 class="section-title">图片</h3>
|
||||
<div class="image-list">
|
||||
<div
|
||||
v-for="(url, index) in picUrls"
|
||||
:key="index"
|
||||
class="image-item"
|
||||
>
|
||||
<el-image
|
||||
:src="url"
|
||||
:preview-src-list="picUrls"
|
||||
:initial-index="index"
|
||||
fit="cover"
|
||||
class="thumbnail"
|
||||
>
|
||||
<template #error>
|
||||
<div class="image-error">
|
||||
<span>加载失败</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 文件展示部分 -->
|
||||
<div class="section" v-if="fileUrls?.length">
|
||||
<h3 class="section-title">文件</h3>
|
||||
<div class="file-list">
|
||||
<div
|
||||
v-for="(url, index) in fileUrls"
|
||||
:key="index"
|
||||
class="file-item"
|
||||
>
|
||||
<el-icon class="file-icon"><Document /></el-icon>
|
||||
<div class="file-info">
|
||||
<a
|
||||
:href="url"
|
||||
target="_blank"
|
||||
class="file-name"
|
||||
@click.prevent="downloadFile(url)"
|
||||
>
|
||||
{{ extractFileName(url) }}
|
||||
</a>
|
||||
<!-- <div class="file-actions">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@click="downloadFile(url)"
|
||||
>
|
||||
下载
|
||||
</el-button>
|
||||
<el-button
|
||||
type="info"
|
||||
link
|
||||
@click="previewFile(url)"
|
||||
>
|
||||
预览
|
||||
</el-button>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 空状态显示 -->
|
||||
<el-empty
|
||||
v-if="!picUrls?.length && !fileUrls?.length"
|
||||
description="暂无附件数据"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ElMessage, ElLoading } from 'element-plus'
|
||||
import { ref } from 'vue'
|
||||
import { Document } from '@element-plus/icons-vue'
|
||||
|
||||
const props = defineProps<{
|
||||
loading: boolean
|
||||
picUrls: string[]
|
||||
fileUrls: string[]
|
||||
}>()
|
||||
|
||||
// 从URL中提取文件名
|
||||
const extractFileName = (url: string) => {
|
||||
try {
|
||||
const path = new URL(url).pathname
|
||||
return decodeURIComponent(path.substring(path.lastIndexOf('/') + 1))
|
||||
} catch {
|
||||
return decodeURIComponent(url.substring(url.lastIndexOf('/') + 1))
|
||||
}
|
||||
}
|
||||
|
||||
// 下载文件
|
||||
const downloadFile = (url: string) => {
|
||||
const loadingInstance = ElLoading.service({
|
||||
lock: true,
|
||||
text: '文件下载中...',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
try {
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = extractFileName(url)
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
ElMessage.success('文件下载开始')
|
||||
} catch (error: any) {
|
||||
ElMessage.error('下载失败: ' + error.message)
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
loadingInstance.close()
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
|
||||
// 预览文件(简单实现)
|
||||
const previewFile = (url: string) => {
|
||||
if (url.match(/\.(png|jpg|jpeg|gif|webp)$/i)) {
|
||||
window.open(url, '_blank')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.attachment-container { padding: 16px; }
|
||||
.section { margin-bottom: 24px; }
|
||||
.section-title { font-weight: bold; margin-bottom: 8px; }
|
||||
.image-list { display: flex; flex-wrap: wrap; gap: 12px; }
|
||||
.image-item { width: 120px; height: 120px; }
|
||||
.thumbnail { width: 100%; height: 100%; object-fit: cover; }
|
||||
.file-list { display: flex; flex-direction: column; gap: 12px; }
|
||||
.file-item { display: flex; align-items: center; }
|
||||
.file-icon { margin-right: 8px; }
|
||||
.file-info { flex: 1; }
|
||||
.file-name { color: #409EFF; text-decoration: underline; cursor: pointer; }
|
||||
.file-actions { margin-left: 16px; }
|
||||
.image-error { color: #f56c6c; text-align: center; }
|
||||
</style>
|
||||
|
|
@ -129,6 +129,7 @@ export enum DICT_TYPE {
|
|||
SYSTEM_MAIL_SEND_STATUS = 'system_mail_send_status',
|
||||
SYSTEM_NOTIFY_TEMPLATE_TYPE = 'system_notify_template_type',
|
||||
SYSTEM_SOCIAL_TYPE = 'system_social_type',
|
||||
SYSTEM_DEPT_TYPE = 'system_dept_type',
|
||||
|
||||
// ========== INFRA 模块 ==========
|
||||
INFRA_BOOLEAN_STRING = 'infra_boolean_string',
|
||||
|
|
|
|||
|
|
@ -14,7 +14,12 @@
|
|||
</el-form-item>
|
||||
</el-col> -->
|
||||
<el-col :span="8">
|
||||
<el-form-item label="客户签约方 " prop="customerId">
|
||||
<el-form-item label="合同名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入合同名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="主客户签约方 " prop="customerId">
|
||||
<el-select
|
||||
v-model="formData.customerId"
|
||||
placeholder="请选择客户签约方 "
|
||||
|
|
@ -23,6 +28,26 @@
|
|||
:multiple-limit="3"
|
||||
filterable
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in customerList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="其他客户签约方 " prop="otherCustomerId">
|
||||
<el-select
|
||||
v-model="formData.otherCustomerId"
|
||||
placeholder="请选择客户签约方 "
|
||||
class="w-1/1"
|
||||
@change="handleCustomerChange"
|
||||
:multiple-limit="2"
|
||||
filterable
|
||||
clearable
|
||||
multiple
|
||||
>
|
||||
<el-option
|
||||
|
|
@ -35,7 +60,7 @@
|
|||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="公司签约方主体" prop="deptId">
|
||||
<el-form-item label="公司签约方" prop="deptId">
|
||||
<el-select
|
||||
v-model="formData.deptId"
|
||||
class="w-1/1"
|
||||
|
|
@ -49,27 +74,6 @@
|
|||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="合同名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入合同名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="负责人" prop="ownerUserId">
|
||||
<el-select
|
||||
v-model="formData.ownerUserId"
|
||||
:disabled="formType !== 'create'"
|
||||
class="w-1/1"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in userOptions"
|
||||
:key="item.id"
|
||||
:label="item.nickname"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
|
|
@ -147,7 +151,7 @@
|
|||
</el-row>
|
||||
<el-row>
|
||||
|
||||
<el-col :span="8">
|
||||
<el-col>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="formData.remark" placeholder="请输入备注" type="textarea" />
|
||||
</el-form-item>
|
||||
|
|
@ -167,7 +171,7 @@
|
|||
</ContentWrap>
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="产品总金额" prop="totalProductPrice">
|
||||
<el-form-item label="合同总金额" prop="totalProductPrice">
|
||||
<el-input
|
||||
disabled
|
||||
v-model="formData.totalProductPrice"
|
||||
|
|
@ -175,7 +179,7 @@
|
|||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<!-- <el-col :span="8">
|
||||
<el-form-item label="整单折扣(%)" prop="discountPercent">
|
||||
<el-input-number
|
||||
v-model="formData.discountPercent"
|
||||
|
|
@ -196,8 +200,14 @@
|
|||
:formatter="erpPriceInputFormatter"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-col> -->
|
||||
</el-row>
|
||||
<el-form-item label="附加图片" prop="picUrls">
|
||||
<UploadImgs v-model="formData.picUrls" :fileType="['image/jpeg', 'image/png']" />
|
||||
</el-form-item>
|
||||
<el-form-item label="附件" prop="fileUrls">
|
||||
<UploadFile v-model="formData.fileUrls" :fileType="['pdf']"/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">保存</el-button>
|
||||
|
|
@ -228,7 +238,8 @@ const formData = ref({
|
|||
id: undefined,
|
||||
no: undefined,
|
||||
name: undefined,
|
||||
customerId: [],
|
||||
customerId: undefined,
|
||||
otherCustomerId: [],
|
||||
contractStatus: undefined,
|
||||
contractType: undefined,
|
||||
contractAttribute: undefined,
|
||||
|
|
@ -243,16 +254,34 @@ const formData = ref({
|
|||
discountPercent: 0,
|
||||
totalProductPrice: undefined,
|
||||
remark: undefined,
|
||||
products: []
|
||||
products: [],
|
||||
picUrls: [],
|
||||
fileUrls: [],
|
||||
})
|
||||
const validateEndTime = (rule: any, value: any, callback: any) => {
|
||||
if (!value || !formData.value.startTime) {
|
||||
callback()
|
||||
return
|
||||
}
|
||||
if (value < formData.value.startTime) {
|
||||
callback(new Error('结束时间不能早于开始时间'))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const formRules = reactive({
|
||||
name: [{ required: true, message: '合同名称不能为空', trigger: 'blur' }],
|
||||
customerId: [{ required: true, message: '客户不能为空', trigger: 'blur' }],
|
||||
customerId: [{ required: true, message: '主签约方不能为空', trigger: 'blur' }],
|
||||
orderDate: [{ required: true, message: '下单日期不能为空', trigger: 'blur' }],
|
||||
ownerUserId: [{ required: true, message: '负责人不能为空', trigger: 'blur' }],
|
||||
contractStatus: [{ required: true, message: '合同状态不能为空', trigger: 'blur' }],
|
||||
contractType: [{ required: true, message: '合同类型不能为空', trigger: 'blur' }],
|
||||
contractAttribute: [{ required: true, message: '合同属性不能为空', trigger: 'blur' }]
|
||||
contractAttribute: [{ required: true, message: '合同属性不能为空', trigger: 'blur' }],
|
||||
deptId: [{ required: true, message: '公司签约方不能为空', trigger: 'blur' }],
|
||||
startTime: [{ required: true, message: '开始时间不能为空', trigger: 'blur' }],
|
||||
endTime: [
|
||||
{ required: true, message: '结束时间不能为空', trigger: 'blur' },
|
||||
{ validator: validateEndTime, trigger: 'blur' }
|
||||
],
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
const userOptions = ref<UserApi.UserVO[]>([]) // 用户列表
|
||||
|
|
@ -305,13 +334,13 @@ const open = async (type: string, id?: number) => {
|
|||
// 获得用户列表
|
||||
userOptions.value = await UserApi.getSimpleUserList()
|
||||
// 默认新建时选中自己
|
||||
if (formType.value === 'create') {
|
||||
formData.value.ownerUserId = useUserStore().getUser.id
|
||||
}
|
||||
// if (formType.value === 'create') {
|
||||
// formData.value.ownerUserId = useUserStore().getUser.id
|
||||
// }
|
||||
// 获取联系人
|
||||
contactList.value = await ContactApi.getSimpleContactList()
|
||||
// 加载部门列表
|
||||
deptList.value = await DeptApi.getSimpleDeptList()
|
||||
deptList.value = await DeptApi.querySimpleDeptList()
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
|
|
@ -322,6 +351,19 @@ const submitForm = async () => {
|
|||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 校验产品清单不能为空
|
||||
if (!formData.value.products || formData.value.products.length === 0) {
|
||||
message.error('产品清单不能为空')
|
||||
return
|
||||
}
|
||||
|
||||
// 校验图片或附件至少有一个不为空
|
||||
const hasPic = formData.value.picUrls && formData.value.picUrls.length > 0
|
||||
const hasFile = formData.value.fileUrls && formData.value.fileUrls.length > 0
|
||||
if (!hasPic && !hasFile) {
|
||||
message.error('附加图片和附件不能同时为空')
|
||||
return
|
||||
}
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
productFormRef.value.validate()
|
||||
|
|
@ -348,7 +390,8 @@ const resetForm = () => {
|
|||
id: undefined,
|
||||
no: undefined,
|
||||
name: undefined,
|
||||
customerId: [],
|
||||
customerId: undefined,
|
||||
otherCustomerId: [],
|
||||
contractStatus: undefined,
|
||||
contractType: undefined,
|
||||
contractAttribute: undefined,
|
||||
|
|
@ -363,7 +406,9 @@ const resetForm = () => {
|
|||
discountPercent: 0,
|
||||
totalProductPrice: undefined,
|
||||
remark: undefined,
|
||||
products: []
|
||||
products: [],
|
||||
picUrls: [],
|
||||
fileUrls: [],
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,48 +12,33 @@
|
|||
<el-table-column label="序号" type="index" align="center" width="60" />
|
||||
<el-table-column label="产品名称" min-width="180">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!">
|
||||
<el-select
|
||||
v-model="row.productId"
|
||||
clearable
|
||||
filterable
|
||||
@change="onChangeProduct($event, row)"
|
||||
placeholder="请选择产品"
|
||||
>
|
||||
<el-form-item :prop="`${$index}.productName`" :rules="formRules.productName" class="mb-0px!">
|
||||
<el-input
|
||||
v-model="row.productName"
|
||||
placeholder="请输入产品名称"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单位" min-width="80">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.productUnit`" :rules="formRules.productUnit" class="mb-0px!">
|
||||
<el-select v-model="row.productUnit" placeholder="请选择单位">
|
||||
<el-option
|
||||
v-for="item in productList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.CRM_PRODUCT_UNIT)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="条码" min-width="150">
|
||||
<template #default="{ row }">
|
||||
<el-form-item class="mb-0px!">
|
||||
<el-input disabled v-model="row.productNo" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单位" min-width="80">
|
||||
<template #default="{ row }">
|
||||
<dict-tag :type="DICT_TYPE.CRM_PRODUCT_UNIT" :value="row.productUnit" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="价格(元)" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-form-item class="mb-0px!">
|
||||
<el-input disabled v-model="row.productPrice" :formatter="erpPriceInputFormatter" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="售价(元)" fixed="right" min-width="140">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.contractPrice`" class="mb-0px!">
|
||||
<el-form-item :prop="`${$index}.productPrice`" :rules="formRules.productPrice" class="mb-0px!">
|
||||
<el-input-number
|
||||
v-model="row.contractPrice"
|
||||
v-model="row.productPrice"
|
||||
controls-position="right"
|
||||
:min="0.001"
|
||||
:precision="2"
|
||||
|
|
@ -96,27 +81,39 @@
|
|||
<script setup lang="ts">
|
||||
import * as ProductApi from '@/api/crm/product'
|
||||
import { erpPriceInputFormatter, erpPriceMultiply } from '@/utils'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
|
||||
const props = defineProps<{
|
||||
products: undefined
|
||||
disabled: false
|
||||
products: any[]
|
||||
disabled: boolean
|
||||
}>()
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formData = ref([])
|
||||
|
||||
// 定义产品行类型
|
||||
interface ProductRow {
|
||||
id?: string | number
|
||||
productName?: string
|
||||
productUnit?: string
|
||||
productPrice?: number
|
||||
count?: number
|
||||
totalPrice?: number
|
||||
}
|
||||
|
||||
const formData = ref<ProductRow[]>([])
|
||||
|
||||
const formRules = reactive({
|
||||
productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }],
|
||||
contractPrice: [{ required: true, message: '合同价格不能为空', trigger: 'blur' }],
|
||||
productName: [{ required: true, message: '产品名称不能为空', trigger: 'blur' }],
|
||||
productUnit: [{ required: true, message: '单位不能为空', trigger: 'blur' }],
|
||||
productPrice: [{ required: true, message: '价格不能为空', trigger: 'blur' }],
|
||||
count: [{ required: true, message: '产品数量不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref([]) // 表单 Ref
|
||||
const productList = ref<ProductApi.ProductVO[]>([]) // 产品列表
|
||||
|
||||
/** 初始化设置产品项 */
|
||||
watch(
|
||||
() => props.products,
|
||||
async (val) => {
|
||||
formData.value = val
|
||||
(val) => {
|
||||
formData.value = val || []
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
|
@ -130,8 +127,8 @@ watch(
|
|||
}
|
||||
// 循环处理
|
||||
val.forEach((item) => {
|
||||
if (item.contractPrice != null && item.count != null) {
|
||||
item.totalPrice = erpPriceMultiply(item.contractPrice, item.count)
|
||||
if (item.productPrice != null && item.count != null) {
|
||||
item.totalPrice = erpPriceMultiply(item.productPrice, item.count)
|
||||
} else {
|
||||
item.totalPrice = undefined
|
||||
}
|
||||
|
|
@ -142,14 +139,13 @@ watch(
|
|||
|
||||
/** 新增按钮操作 */
|
||||
const handleAdd = () => {
|
||||
const row = {
|
||||
const row: ProductRow = {
|
||||
id: undefined,
|
||||
productId: undefined,
|
||||
productName: undefined,
|
||||
productUnit: undefined, // 产品单位
|
||||
productNo: undefined, // 产品条码
|
||||
productPrice: undefined, // 产品价格
|
||||
contractPrice: undefined,
|
||||
count: 1
|
||||
count: 1,
|
||||
totalPrice: undefined
|
||||
}
|
||||
formData.value.push(row)
|
||||
}
|
||||
|
|
@ -159,17 +155,6 @@ const handleDelete = (index: number) => {
|
|||
formData.value.splice(index, 1)
|
||||
}
|
||||
|
||||
/** 处理产品变更 */
|
||||
const onChangeProduct = (productId, row) => {
|
||||
const product = productList.value.find((item) => item.id === productId)
|
||||
if (product) {
|
||||
row.productUnit = product.unit
|
||||
row.productNo = product.no
|
||||
row.productPrice = product.price
|
||||
row.contractPrice = product.price
|
||||
}
|
||||
}
|
||||
|
||||
/** 表单校验 */
|
||||
const validate = () => {
|
||||
return formRef.value.validate()
|
||||
|
|
@ -178,6 +163,7 @@ defineExpose({ validate })
|
|||
|
||||
/** 初始化 */
|
||||
onMounted(async () => {
|
||||
productList.value = await ProductApi.getProductSimpleList()
|
||||
// 移除未用的 productList 相关内容
|
||||
// productList.value = await ProductApi.getProductSimpleList()
|
||||
})
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -20,23 +20,22 @@
|
|||
<!-- <el-descriptions-item label="合同编号">{{ contract.no }}</el-descriptions-item> -->
|
||||
<el-descriptions-item label="合同名称">{{ contract.name }}</el-descriptions-item>
|
||||
<el-descriptions-item label="客户签约方">
|
||||
<div>
|
||||
<template v-if="Array.isArray(contract.customer)">
|
||||
|
||||
<span v-for="(c, idx) in contract.customer" :key="c.id">
|
||||
{{ c.name }}<span v-if="idx < contract.customer.length - 1"><br /> </span>
|
||||
{{ contract.customerName || '' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="其他签约方">
|
||||
<div>
|
||||
<template v-if="Array.isArray(contract.otherCustomer)">
|
||||
<span v-for="(c, idx) in contract.otherCustomer" :key="c.id">
|
||||
{{ c.name }}<span v-if="idx < contract.otherCustomer.length - 1"><br /> </span>
|
||||
</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ contract.customer?.name || '' }}
|
||||
{{ contract.otherCustomer?.name || '' }}
|
||||
</template>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="责任人">
|
||||
{{ contract.ownerUserName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="合同金额(元)">
|
||||
{{ erpPriceInputFormatter(contract.totalPrice) }}
|
||||
<el-descriptions-item label="公司签约方">
|
||||
{{ contract.deptName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="签订时间">
|
||||
{{ formatDate(contract.orderDate, 'YYYY-MM-DD') }}
|
||||
|
|
@ -48,7 +47,13 @@
|
|||
{{ formatDate(contract.endTime, 'YYYY-MM-DD') }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="合同状态">
|
||||
<dict-tag :type="DICT_TYPE.CRM_AUDIT_STATUS" :value="contract.auditStatus" />
|
||||
<dict-tag :type="DICT_TYPE.CRM_CONTRACT_STATUS" :value="contract.contractStatus" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="合同类型">
|
||||
<dict-tag :type="DICT_TYPE.CRM_CONTRACT_TYPE" :value="contract.contractType" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="合同属性">
|
||||
<dict-tag :type="DICT_TYPE.CRM_CONTRACT_ATTRIBUTE" :value="contract.contractAttribute" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="合同金额(元)">
|
||||
{{ erpPriceInputFormatter(contract.totalPrice) }}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<el-table :data="contract.products" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="产品名称"
|
||||
label="产品或服务"
|
||||
fixed="left"
|
||||
prop="productName"
|
||||
min-width="160"
|
||||
|
|
@ -12,7 +12,6 @@
|
|||
{{ scope.row.productName }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="产品条码" align="center" prop="productNo" min-width="120" />
|
||||
<el-table-column align="center" label="产品单位" prop="productUnit" min-width="160">
|
||||
<template #default="{ row }">
|
||||
<dict-tag :type="DICT_TYPE.CRM_PRODUCT_UNIT" :value="row.productUnit" />
|
||||
|
|
@ -25,13 +24,13 @@
|
|||
min-width="140"
|
||||
:formatter="erpPriceTableColumnFormatter"
|
||||
/>
|
||||
<el-table-column
|
||||
<!-- <el-table-column
|
||||
label="合同价格(元)"
|
||||
align="center"
|
||||
prop="contractPrice"
|
||||
min-width="140"
|
||||
:formatter="erpPriceTableColumnFormatter"
|
||||
/>
|
||||
/> -->
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="数量"
|
||||
|
|
@ -48,10 +47,10 @@
|
|||
/>
|
||||
</el-table>
|
||||
<el-row class="mt-10px" justify="end">
|
||||
<el-col :span="3"> 整单折扣:{{ erpPriceInputFormatter(contract.discountPercent) }}% </el-col>
|
||||
<el-col :span="4">
|
||||
产品总金额:{{ erpPriceInputFormatter(contract.totalProductPrice) }} 元
|
||||
</el-col>
|
||||
<!-- <el-col :span="3"> 整单折扣:{{ erpPriceInputFormatter(contract.discountPercent) }}% </el-col> -->
|
||||
<!-- <el-col :span="4">
|
||||
产品总金额:{{ erpPriceInputFormatter(contract.) }} 元
|
||||
</el-col> -->
|
||||
</el-row>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,37 +1,35 @@
|
|||
<!-- 合同详情页面组件-->
|
||||
<template>
|
||||
<ContractDetailsHeader v-loading="loading" :contract="contract">
|
||||
<el-button v-if="permissionListRef?.validateWrite" @click="openForm('update', contract.id)">
|
||||
<el-button v-hasPermi="['crm:contract:update']" @click="openForm('update', contract.id)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button v-if="permissionListRef?.validateOwnerUser" type="primary" @click="transferContract">
|
||||
<!-- <el-button v-hasPermi="['crm:contract:update']" type="primary" @click="transferContract">
|
||||
转移
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</ContractDetailsHeader>
|
||||
<el-col>
|
||||
<el-tabs>
|
||||
<el-tab-pane label="产品">
|
||||
<el-tab-pane label="合同清单">
|
||||
<ContractProductList :contract="contract" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="付款">
|
||||
<el-tab-pane label="付款计划">
|
||||
<ReceivablePlanList
|
||||
:contract-id="contract.id!"
|
||||
:customer-id="Array.isArray(contract.customerId) ? contract.customerId[0] : contract.customerId"
|
||||
:customer-id="contract.customerId"
|
||||
@create-receivable="createReceivable"
|
||||
/>
|
||||
<ReceivableList
|
||||
ref="receivableListRef"
|
||||
:contract-id="contract.id!"
|
||||
:customer-id="Array.isArray(contract.customerId) ? contract.customerId[0] : contract.customerId"
|
||||
:customer-id="contract.customerId"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="团队成员">
|
||||
<PermissionList
|
||||
ref="permissionListRef"
|
||||
:biz-id="contract.id!"
|
||||
:biz-type="BizTypeEnum.CRM_CONTRACT"
|
||||
:show-action="true"
|
||||
@quit-team="close"
|
||||
<el-tab-pane label="合同明细">
|
||||
<AttachmentTab
|
||||
:loading="loading"
|
||||
:pic-urls="contract.picUrls"
|
||||
:file-urls="contract.fileUrls"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="操作日志">
|
||||
|
|
@ -57,6 +55,7 @@ import CrmTransferForm from '@/views/crm/permission/components/TransferForm.vue'
|
|||
import PermissionList from '@/views/crm/permission/components/PermissionList.vue'
|
||||
import ReceivableList from '@/views/crm/receivable/components/ReceivableList.vue'
|
||||
import ReceivablePlanList from '@/views/crm/receivable/plan/components/ReceivablePlanList.vue'
|
||||
import AttachmentTab from '@/components/AttachmentFile/index.vue'
|
||||
|
||||
defineOptions({ name: 'CrmContractDetail' })
|
||||
const props = defineProps<{ id?: number }>()
|
||||
|
|
|
|||
|
|
@ -28,13 +28,13 @@
|
|||
placeholder="请输入合同名称"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
<el-form-item label="客户" prop="customerId">
|
||||
<el-form-item label="客户签约方" prop="customerId">
|
||||
<el-select
|
||||
v-model="queryParams.customerId"
|
||||
class="!w-240px"
|
||||
clearable
|
||||
lable-key="name"
|
||||
placeholder="请选择客户"
|
||||
placeholder="请选择客户签约方"
|
||||
value-key="id"
|
||||
@keyup.enter="handleQuery"
|
||||
>
|
||||
|
|
@ -76,28 +76,27 @@
|
|||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
|
||||
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true" :row-class-name="tableRowClassName">
|
||||
<!-- <el-table-column align="center" fixed="left" label="合同编号" prop="no" width="180" /> -->
|
||||
<el-table-column align="center" fixed="left" label="合同名称" prop="name" width="160">
|
||||
<el-table-column align="center" fixed="left" label="合同名称" prop="name" width="300">
|
||||
<template #default="scope">
|
||||
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
|
||||
{{ scope.row.name }}
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="客户签约方" prop="customer.id" width="350">
|
||||
<el-table-column align="center" label="客户签约方" prop="deptId" width="300">
|
||||
<template #default="scope">
|
||||
|
||||
<el-link
|
||||
:underline="false"
|
||||
type="primary"
|
||||
@click="openCustomerDetail(scope.row.customer[0].id)"
|
||||
@click="openCustomerDetail(scope.row.customerId)"
|
||||
>
|
||||
{{ scope.row.customer[0].name }}
|
||||
{{ scope.row.customerName }}
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="160" />
|
||||
<!-- <el-table-column
|
||||
align="center"
|
||||
label="合同金额(元)"
|
||||
|
|
@ -119,13 +118,13 @@
|
|||
width="160"
|
||||
:formatter="dateFormatter2"
|
||||
/>
|
||||
<el-table-column
|
||||
<!-- <el-table-column
|
||||
align="center"
|
||||
label="已付款金额(万元)"
|
||||
prop="totalReceivablePrice"
|
||||
width="160"
|
||||
:formatter="erpPriceTableColumnFormatter"
|
||||
/>
|
||||
/> -->
|
||||
<!-- <el-table-column
|
||||
align="center"
|
||||
label="未付款金额(元)"
|
||||
|
|
@ -137,14 +136,14 @@
|
|||
{{ erpPriceInputFormatter(scope.row.totalPrice - scope.row.totalReceivablePrice) }}
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column align="center" label="责任人" prop="ownerUserName" width="160" />
|
||||
<!-- <el-table-column align="center" label="责任人" prop="ownerUserName" width="160" /> -->
|
||||
|
||||
<el-table-column align="center" fixed="right" label="合同状态" prop="contractStatus" width="160">
|
||||
<el-table-column align="center" label="合同状态" prop="contractStatus" width="160">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.CRM_CONTRACT_STATUS" :value="scope.row.contractStatus" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" fixed="right" label="合同类型" prop="contractType" width="160">
|
||||
<el-table-column align="center" label="合同类型" prop="contractType" width="160">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.CRM_CONTRACT_TYPE" :value="scope.row.contractType" />
|
||||
</template>
|
||||
|
|
@ -160,7 +159,7 @@
|
|||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
<!-- <el-button
|
||||
v-if="scope.row.auditStatus === 0"
|
||||
v-hasPermi="['crm:contract:update']"
|
||||
link
|
||||
|
|
@ -168,8 +167,8 @@
|
|||
@click="handleSubmit(scope.row)"
|
||||
>
|
||||
提交审核
|
||||
</el-button>
|
||||
<el-button
|
||||
</el-button> -->
|
||||
<!-- <el-button
|
||||
v-else
|
||||
link
|
||||
v-hasPermi="['crm:contract:update']"
|
||||
|
|
@ -177,7 +176,7 @@
|
|||
@click="handleProcessDetail(scope.row)"
|
||||
>
|
||||
查看审批
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
<el-button
|
||||
v-hasPermi="['crm:contract:delete']"
|
||||
link
|
||||
|
|
@ -329,4 +328,45 @@ onMounted(async () => {
|
|||
await getList()
|
||||
customerList.value = await CustomerApi.getCustomerSimpleList()
|
||||
})
|
||||
|
||||
|
||||
// 计算行样式的方法
|
||||
const tableRowClassName = ({ row }: { row: any }) => {
|
||||
if (!row.endTime) return '';
|
||||
|
||||
const endTime = new Date(row.endTime);
|
||||
const today = new Date();
|
||||
|
||||
if(row.contractAttribute === 2 ) {
|
||||
// 如果是一次性合同,直接返回空样式
|
||||
return '';
|
||||
}
|
||||
// 计算剩余天数
|
||||
const diffTime = today.getTime() - endTime.getTime();
|
||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
||||
console.log('diffDays', diffDays, endTime);
|
||||
if (diffDays <= 90) { // 少于3个月
|
||||
return 'expiring-soon-row';
|
||||
} else if (diffDays <= 180) { // 少于6个月
|
||||
return 'expiring-row';
|
||||
}
|
||||
return '';
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* 添加行样式 */
|
||||
.el-table .expiring-row td {
|
||||
background-color: #fffcde !important; /* 黄色背景 */
|
||||
}
|
||||
|
||||
.el-table .expiring-soon-row td {
|
||||
background-color: #ffe8e8 !important; /* 红色背景 */
|
||||
}
|
||||
|
||||
/* 如果需要,可以添加悬停效果 */
|
||||
.el-table .expiring-row:hover>td,
|
||||
.el-table .expiring-soon-row:hover>td {
|
||||
opacity: 0.9;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
<el-option
|
||||
v-for="data in contractList"
|
||||
:key="data.id"
|
||||
:disabled="data.auditStatus !== 20"
|
||||
|
||||
:label="data.name"
|
||||
:value="data.id!"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,39 +1,45 @@
|
|||
<template>
|
||||
<!-- 操作栏 -->
|
||||
<el-row justify="end">
|
||||
<el-button @click="openForm('create')">
|
||||
<el-row>
|
||||
<text class="text-xs font-bold">
|
||||
实付明细
|
||||
</text>
|
||||
<!-- <el-button @click="openForm('create')">
|
||||
<Icon class="mr-5px" icon="icon-park:income-one" />
|
||||
创建付款
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap class="mt-10px">
|
||||
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
|
||||
<el-table-column align="center" label="付款编号" prop="no" />
|
||||
<el-table-column align="center" label="客户" prop="customerName" />
|
||||
<el-table-column align="center" label="合同" prop="contract.no" />
|
||||
<el-table-column
|
||||
:formatter="dateFormatter2"
|
||||
align="center"
|
||||
label="付款日期"
|
||||
label="实际付款日期"
|
||||
prop="returnTime"
|
||||
width="150px"
|
||||
min-width="150px"
|
||||
/>
|
||||
<el-table-column align="center" label="付款方式" prop="returnType" width="130px">
|
||||
<!-- <el-table-column align="center" label="付款编号" prop="no" /> -->
|
||||
<el-table-column align="center" label="收款单位" prop="customerName" min-width="300px" />
|
||||
<el-table-column align="center" label="付款单位" prop="deptName" min-width="300px"/>
|
||||
<el-table-column align="center" label="对应计划期数" prop="period" min-width="150px" />
|
||||
<!-- <el-table-column align="center" label="合同" prop="contract.no" /> -->
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="实付金额(元)"
|
||||
prop="price"
|
||||
:formatter="erpPriceTableColumnFormatter"
|
||||
min-width="150px"
|
||||
/>
|
||||
<el-table-column align="center" label="付款方式" prop="returnType">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE" :value="scope.row.returnType" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="付款金额(元)"
|
||||
prop="price"
|
||||
:formatter="erpPriceTableColumnFormatter"
|
||||
/>
|
||||
<el-table-column align="center" label="负责人" prop="ownerUserName" />
|
||||
<el-table-column align="center" label="备注" prop="remark" />
|
||||
<el-table-column align="center" fixed="right" label="操作" width="130px">
|
||||
<!-- <el-table-column align="center" label="负责人" prop="ownerUserName" /> -->
|
||||
<!-- <el-table-column align="center" label="备注" prop="remark" /> -->
|
||||
<!-- <el-table-column align="center" fixed="right" label="操作" width="130px">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-hasPermi="['crm:receivable:update']"
|
||||
|
|
@ -52,7 +58,7 @@
|
|||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column> -->
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
|
|
|
|||
|
|
@ -9,22 +9,24 @@
|
|||
>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="还款期数" prop="period">
|
||||
<el-form-item label="付款期数" prop="period">
|
||||
<el-input v-model="formData.period" disabled placeholder="保存时自动生成" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="负责人" prop="ownerUserId">
|
||||
<el-form-item label="付款单位">
|
||||
<el-select
|
||||
v-model="formData.ownerUserId"
|
||||
:disabled="formType !== 'create'"
|
||||
v-model="formData.contractId"
|
||||
disabled
|
||||
class="w-1/1"
|
||||
filterable
|
||||
placeholder="请选择付款单位"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in userOptions"
|
||||
:key="item.id"
|
||||
:label="item.nickname"
|
||||
:value="item.id"
|
||||
v-for="data in contractList"
|
||||
:key="data.id"
|
||||
:label="data.deptName"
|
||||
:value="data.id!"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
|
@ -32,14 +34,13 @@
|
|||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="客户名称" prop="customerId">
|
||||
<el-form-item label="收款单位" prop="customerId">
|
||||
<el-select
|
||||
v-model="formData.customerId"
|
||||
:disabled="formType !== 'create'"
|
||||
disabled
|
||||
class="w-1/1"
|
||||
filterable
|
||||
placeholder="请选择客户"
|
||||
@change="handleCustomerChange"
|
||||
placeholder="请选择收款单位"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in customerList"
|
||||
|
|
@ -54,7 +55,7 @@
|
|||
<el-form-item label="合同名称" prop="contractId">
|
||||
<el-select
|
||||
v-model="formData.contractId"
|
||||
:disabled="formType !== 'create' || !formData.customerId"
|
||||
disabled
|
||||
class="w-1/1"
|
||||
filterable
|
||||
placeholder="请选择合同"
|
||||
|
|
@ -71,14 +72,14 @@
|
|||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="计划付款金额" prop="price">
|
||||
<el-form-item label="计划金额(元)" prop="price">
|
||||
<el-input-number
|
||||
v-model="formData.price"
|
||||
:min="0.01"
|
||||
:precision="2"
|
||||
class="!w-100%"
|
||||
controls-position="right"
|
||||
placeholder="请输入计划付款金额"
|
||||
placeholder="请输入计划金额"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
|
@ -95,7 +96,7 @@
|
|||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<!-- <el-col :span="12">
|
||||
<el-form-item label="提前几天提醒" prop="remindDays">
|
||||
<el-input-number
|
||||
v-model="formData.remindDays"
|
||||
|
|
@ -116,10 +117,10 @@
|
|||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-col> -->
|
||||
<el-col :span="24">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="formData.remark" placeholder="请输入备注" type="textarea" />
|
||||
<el-form-item label="用途" prop="remark">
|
||||
<el-input v-model="formData.remark" placeholder="请输入用途" type="textarea" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
|
@ -150,9 +151,7 @@ const formData = ref<ReceivablePlanApi.ReceivablePlanVO>({} as ReceivablePlanApi
|
|||
const formRules = reactive({
|
||||
price: [{ required: true, message: '计划付款金额不能为空', trigger: 'blur' }],
|
||||
returnTime: [{ required: true, message: '计划付款日期不能为空', trigger: 'blur' }],
|
||||
customerId: [{ required: true, message: '客户编号不能为空', trigger: 'blur' }],
|
||||
contractId: [{ required: true, message: '合同编号不能为空', trigger: 'blur' }],
|
||||
ownerUserId: [{ required: true, message: '负责人不能为空', trigger: 'blur' }]
|
||||
remark: [{ required: true, message: '用途不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
const customerList = ref<CustomerApi.CustomerVO[]>([]) // 客户列表
|
||||
|
|
@ -181,9 +180,9 @@ const open = async (type: string, id?: number, customerId?: number, contractId?:
|
|||
// 获得客户列表
|
||||
customerList.value = await CustomerApi.getCustomerSimpleList()
|
||||
// 默认新建时选中自己
|
||||
if (formType.value === 'create') {
|
||||
formData.value.ownerUserId = useUserStore().getUser.id
|
||||
}
|
||||
// if (formType.value === 'create') {
|
||||
// formData.value.ownerUserId = useUserStore().getUser.id
|
||||
// }
|
||||
// 设置 customerId 和 contractId 默认值
|
||||
if (customerId) {
|
||||
formData.value.customerId = customerId
|
||||
|
|
@ -231,10 +230,13 @@ const resetForm = () => {
|
|||
const handleCustomerChange = async (customerId: number) => {
|
||||
// 重置合同编号
|
||||
formData.value.contractId = undefined
|
||||
formData.value.deptName = undefined
|
||||
|
||||
// 获得合同列表
|
||||
if (customerId) {
|
||||
contractList.value = []
|
||||
contractList.value = await ContractApi.getContractSimpleList(customerId)
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,45 +1,51 @@
|
|||
<template>
|
||||
<!-- 操作栏 -->
|
||||
<el-row justify="end">
|
||||
<el-button @click="openForm('create', undefined)">
|
||||
<Icon class="mr-5px" icon="icon-park:income" />
|
||||
创建付款计划
|
||||
</el-button>
|
||||
<el-row align="middle" class="mb-2">
|
||||
<el-col :span="12">
|
||||
<span class="text-xs font-bold">付款计划</span>
|
||||
</el-col>
|
||||
<el-col :span="12" class="text-right">
|
||||
<el-button @click="openForm('create', undefined)">
|
||||
<Icon class="mr-5px" icon="icon-park:income" />
|
||||
创建付款计划
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap class="mt-10px">
|
||||
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
|
||||
<el-table-column align="center" label="客户名称" prop="customerName" width="150px" />
|
||||
<el-table-column align="center" label="合同编号" prop="contractNo" width="200px" />
|
||||
<el-table-column align="center" label="期数" prop="period" />
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="计划付款(元)"
|
||||
prop="price"
|
||||
width="120"
|
||||
:formatter="erpPriceTableColumnFormatter"
|
||||
/>
|
||||
<el-table-column
|
||||
:formatter="dateFormatter2"
|
||||
align="center"
|
||||
label="计划付款日期"
|
||||
prop="returnTime"
|
||||
width="180px"
|
||||
min-width="150px"
|
||||
/>
|
||||
<el-table-column align="center" label="提前几天提醒" prop="remindDays" width="150" />
|
||||
<el-table-column align="center" label="收款单位" prop="customerName" min-width="300px" />
|
||||
<el-table-column align="center" label="付款单位" prop="deptName" min-width="300px"/>
|
||||
<el-table-column align="center" label="期数" prop="period" min-width="150px"/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="计划付款金额(元)"
|
||||
prop="price"
|
||||
min-width="180"
|
||||
:formatter="erpPriceTableColumnFormatter"
|
||||
/>
|
||||
|
||||
<!-- <el-table-column align="center" label="提前几天提醒" prop="remindDays" width="150" />
|
||||
<el-table-column
|
||||
:formatter="dateFormatter2"
|
||||
align="center"
|
||||
label="提醒日期"
|
||||
prop="remindTime"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column label="负责人" prop="ownerUserName" width="120" />
|
||||
<el-table-column align="center" label="备注" prop="remark" />
|
||||
/> -->
|
||||
<!-- <el-table-column label="负责人" prop="ownerUserName" width="120" /> -->
|
||||
<el-table-column align="center" label="用途" prop="remark" min-width="300px"/>
|
||||
<el-table-column align="center" fixed="right" label="操作" width="200px">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
<!-- <el-button
|
||||
v-hasPermi="['crm:receivable:create']"
|
||||
link
|
||||
type="primary"
|
||||
|
|
@ -47,7 +53,7 @@
|
|||
:disabled="scope.row.receivableId"
|
||||
>
|
||||
创建付款
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
<el-button
|
||||
v-hasPermi="['crm:receivable-plan:update']"
|
||||
link
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
<Icon class="mr-5px" icon="ep:refresh" />
|
||||
重置
|
||||
</el-button>
|
||||
<el-button
|
||||
<!-- <el-button
|
||||
v-hasPermi="['crm:receivable-plan:create']"
|
||||
plain
|
||||
type="primary"
|
||||
|
|
@ -52,7 +52,7 @@
|
|||
>
|
||||
<Icon class="mr-5px" icon="ep:plus" />
|
||||
新增
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
<el-button
|
||||
v-hasPermi="['crm:receivable-plan:export']"
|
||||
:loading="exportLoading"
|
||||
|
|
@ -69,12 +69,15 @@
|
|||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-tabs v-model="activeName" @tab-click="handleTabClick">
|
||||
<el-tab-pane label="我负责的" name="1" />
|
||||
<el-tab-pane label="下属负责的" name="3" />
|
||||
</el-tabs>
|
||||
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
|
||||
<el-table-column align="center" fixed="left" label="客户名称" prop="customerName" width="150">
|
||||
<el-table-column
|
||||
:formatter="dateFormatter2"
|
||||
align="center"
|
||||
label="计划付款日期"
|
||||
prop="returnTime"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column align="center" label="收款单位名称" prop="customerName" width="150">
|
||||
<template #default="scope">
|
||||
<el-link
|
||||
:underline="false"
|
||||
|
|
@ -85,7 +88,17 @@
|
|||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="合同编号" prop="contractNo" width="200px" />
|
||||
<el-table-column align="center" label="合同名称" prop="contractName" width="200px" >
|
||||
<template #default="scope">
|
||||
<el-link
|
||||
:underline="false"
|
||||
type="primary"
|
||||
@click="openContractDetail(scope.row.contractId)"
|
||||
>
|
||||
{{ scope.row.contractName }}
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="期数" prop="period">
|
||||
<template #default="scope">
|
||||
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
|
||||
|
|
@ -101,30 +114,8 @@
|
|||
:formatter="erpPriceTableColumnFormatter"
|
||||
/>
|
||||
<el-table-column
|
||||
:formatter="dateFormatter2"
|
||||
align="center"
|
||||
label="计划付款日期"
|
||||
prop="returnTime"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column align="center" label="提前几天提醒" prop="remindDays" width="150" />
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="提醒日期"
|
||||
prop="remindTime"
|
||||
width="180px"
|
||||
:formatter="dateFormatter2"
|
||||
/>
|
||||
<el-table-column align="center" label="付款方式" prop="returnType" width="130px">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE" :value="scope.row.returnType" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="备注" prop="remark" />
|
||||
<el-table-column label="负责人" prop="ownerUserName" width="120" />
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="实际付款金额(元)"
|
||||
label="已付款金额(元)"
|
||||
prop="receivable.price"
|
||||
width="160"
|
||||
>
|
||||
|
|
@ -135,16 +126,16 @@
|
|||
<el-text v-else>{{ erpPriceInputFormatter(0) }}</el-text>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
<!-- <el-table-column
|
||||
align="center"
|
||||
label="实际付款日期"
|
||||
prop="receivable.returnTime"
|
||||
width="180px"
|
||||
:formatter="dateFormatter2"
|
||||
/>
|
||||
/> -->
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="实际付款金额(元)"
|
||||
label="应付款金额(元)"
|
||||
prop="receivable.price"
|
||||
width="160"
|
||||
>
|
||||
|
|
@ -155,21 +146,6 @@
|
|||
<el-text v-else>{{ erpPriceInputFormatter(scope.row.price) }}</el-text>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:formatter="dateFormatter"
|
||||
align="center"
|
||||
label="更新时间"
|
||||
prop="updateTime"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column
|
||||
:formatter="dateFormatter"
|
||||
align="center"
|
||||
label="创建时间"
|
||||
prop="createTime"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column align="center" label="创建人" prop="creatorName" width="100px" />
|
||||
<el-table-column align="center" fixed="right" label="操作" width="180px">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
|
|
@ -245,11 +221,6 @@ const exportLoading = ref(false) // 导出的加载中
|
|||
const activeName = ref('1') // 列表 tab
|
||||
const customerList = ref<CustomerApi.CustomerVO[]>([]) // 客户列表
|
||||
|
||||
/** tab 切换 */
|
||||
const handleTabClick = (tab: TabsPaneContext) => {
|
||||
queryParams.sceneType = tab.paneName
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
|
|
@ -325,6 +296,10 @@ const openDetail = (id: number) => {
|
|||
const openCustomerDetail = (id: number) => {
|
||||
push({ name: 'CrmCustomerDetail', params: { id } })
|
||||
}
|
||||
/** 打开合同详情 */
|
||||
const openContractDetail = (id: number) => {
|
||||
push({ name: 'CrmContractDetail', params: { id } })
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(async () => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,162 @@
|
|||
<template>
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="110px"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="付款单位">
|
||||
<el-select
|
||||
v-model="formData.contractId"
|
||||
class="w-1/1"
|
||||
filterable
|
||||
placeholder="请选择付款单位"
|
||||
>
|
||||
<el-option
|
||||
v-for="data in deptList"
|
||||
:key="data.id"
|
||||
:label="data.name"
|
||||
:value="data.id!"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="收款单位" prop="customerName">
|
||||
<el-input
|
||||
v-model="formData.customerName"
|
||||
placeholder="请输入收款单位"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="计划金额(元)" prop="price">
|
||||
<el-input-number
|
||||
v-model="formData.price"
|
||||
:min="0.01"
|
||||
:precision="2"
|
||||
class="!w-100%"
|
||||
controls-position="right"
|
||||
placeholder="请输入计划金额"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="计划付款日期" prop="returnTime">
|
||||
<el-date-picker
|
||||
v-model="formData.returnTime"
|
||||
placeholder="选择计划付款日期"
|
||||
type="date"
|
||||
value-format="x"
|
||||
class="!w-100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="用途" prop="remark">
|
||||
<el-input v-model="formData.remark" placeholder="请输入用途" type="textarea" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import * as ReceivablePlanApi from '@/api/crm/receivable/plan'
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import * as CustomerApi from '@/api/crm/customer'
|
||||
import * as ContractApi from '@/api/crm/contract'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import * as DeptApi from '@/api/system/dept'
|
||||
import { de } from 'element-plus/es/locale'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
const userOptions = ref<UserApi.UserVO[]>([]) // 用户列表
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref<ReceivablePlanApi.ReceivablePlanVO>({} as ReceivablePlanApi.ReceivablePlanVO)
|
||||
const formRules = reactive({
|
||||
price: [{ required: true, message: '计划付款金额不能为空', trigger: 'blur' }],
|
||||
returnTime: [{ required: true, message: '计划付款日期不能为空', trigger: 'blur' }],
|
||||
remark: [{ required: true, message: '用途不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
const deptList = ref<DeptApi.DeptVO[]>([])
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number, customerId?: number, contractId?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = await ReceivablePlanApi.getReceivablePlan(id)
|
||||
formData.value = cloneDeep(data)
|
||||
formData.value.contractId = data?.contractId
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
// 获得用户列表
|
||||
userOptions.value = await UserApi.getSimpleUserList()
|
||||
// 加载部门列表
|
||||
deptList.value = await DeptApi.querySimpleDeptList()
|
||||
// 默认新建时选中自己
|
||||
// if (formType.value === 'create') {
|
||||
// formData.value.ownerUserId = useUserStore().getUser.id
|
||||
// }
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as ReceivablePlanApi.ReceivablePlanVO
|
||||
if (formType.value === 'create') {
|
||||
await ReceivablePlanApi.createReceivablePlan(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await ReceivablePlanApi.updateReceivablePlan(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {} as ReceivablePlanApi.ReceivablePlanVO
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,276 @@
|
|||
<template>
|
||||
|
||||
|
||||
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
:model="queryParams"
|
||||
class="-mb-15px"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="客户名称" prop="customerId">
|
||||
<el-select
|
||||
v-model="queryParams.customerId"
|
||||
class="!w-240px"
|
||||
placeholder="请选择客户"
|
||||
@keyup.enter="handleQuery"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in customerList"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="合同编号" prop="contractNo">
|
||||
<el-input
|
||||
v-model="queryParams.contractNo"
|
||||
class="!w-240px"
|
||||
clearable
|
||||
placeholder="请输入合同编号"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery">
|
||||
<Icon class="mr-5px" icon="ep:search" />
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button @click="resetQuery">
|
||||
<Icon class="mr-5px" icon="ep:refresh" />
|
||||
重置
|
||||
</el-button>
|
||||
<el-button
|
||||
v-hasPermi="['crm:receivable-plan:create']"
|
||||
plain
|
||||
type="primary"
|
||||
@click="openForm('create')"
|
||||
>
|
||||
<Icon class="mr-5px" icon="ep:plus" />
|
||||
新增
|
||||
</el-button>
|
||||
<el-button
|
||||
v-hasPermi="['crm:receivable-plan:export']"
|
||||
:loading="exportLoading"
|
||||
plain
|
||||
type="success"
|
||||
@click="handleExport"
|
||||
>
|
||||
<Icon class="mr-5px" icon="ep:download" />
|
||||
导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
|
||||
<el-table-column
|
||||
:formatter="dateFormatter2"
|
||||
align="center"
|
||||
label="计划付款日期"
|
||||
prop="returnTime"
|
||||
width="180px"
|
||||
/>
|
||||
<el-table-column align="center" label="付款单位" prop="deptName" min-width="300">
|
||||
<template #default="scope">
|
||||
{{ scope.row.deptName }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="收款单位" prop="customerName" min-width="300">
|
||||
<template #default="scope">
|
||||
{{ scope.row.customerName }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="计划付款金额(元)"
|
||||
prop="price"
|
||||
width="160"
|
||||
:formatter="erpPriceTableColumnFormatter"
|
||||
/>
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="已付款金额(元)"
|
||||
prop="receivable.price"
|
||||
width="160"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-text v-if="scope.row.receivable">
|
||||
{{ erpPriceInputFormatter(scope.row.receivable.price) }}
|
||||
</el-text>
|
||||
<el-text v-else>{{ erpPriceInputFormatter(0) }}</el-text>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column
|
||||
align="center"
|
||||
label="实际付款日期"
|
||||
prop="receivable.returnTime"
|
||||
width="180px"
|
||||
:formatter="dateFormatter2"
|
||||
/> -->
|
||||
<el-table-column
|
||||
align="center"
|
||||
label="应付款金额(元)"
|
||||
prop="receivable.price"
|
||||
width="160"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-text v-if="scope.row.receivable">
|
||||
{{ erpPriceInputFormatter(scope.row.price - scope.row.receivable.price) }}
|
||||
</el-text>
|
||||
<el-text v-else>{{ erpPriceInputFormatter(scope.row.price) }}</el-text>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="创建人" prop="creatorName" width="150">
|
||||
<template #default="scope">
|
||||
{{ scope.row.creatorName }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column align="center" fixed="right" label="操作" width="180px">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-hasPermi="['crm:receivable-plan:update']"
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
v-hasPermi="['crm:receivable-plan:delete']"
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
v-model:limit="queryParams.pageSize"
|
||||
v-model:page="queryParams.pageNo"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<RequestForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import * as ReceivablePlanApi from '@/api/crm/receivable/plan'
|
||||
import * as CustomerApi from '@/api/crm/customer'
|
||||
import { erpPriceInputFormatter, erpPriceTableColumnFormatter } from '@/utils'
|
||||
import { TabsPaneContext } from 'element-plus'
|
||||
import RequestForm from '@/views/crm/receivable/request/RequestForm.vue'
|
||||
|
||||
defineOptions({ name: 'ExpenseRequest' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref([]) // 列表的数据
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
sceneType: '1', // 默认和 activeName 相等
|
||||
customerId: undefined,
|
||||
contractNo: undefined
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
const activeName = ref('1') // 列表 tab
|
||||
const customerList = ref<CustomerApi.CustomerVO[]>([]) // 客户列表
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await ReceivablePlanApi.getReceivablePlanPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await ReceivablePlanApi.deleteReceivablePlan(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await ReceivablePlanApi.exportReceivablePlan(queryParams)
|
||||
download.excel(data, '付款计划.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 打开详情 */
|
||||
const { push } = useRouter()
|
||||
const openDetail = (id: number) => {
|
||||
push({ name: 'CrmReceivablePlanDetail', params: { id } })
|
||||
}
|
||||
|
||||
/** 打开客户详情 */
|
||||
const openCustomerDetail = (id: number) => {
|
||||
push({ name: 'CrmCustomerDetail', params: { id } })
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(async () => {
|
||||
await getList()
|
||||
// 获得客户列表
|
||||
customerList.value = await CustomerApi.getCustomerSimpleList()
|
||||
})
|
||||
</script>
|
||||
|
|
@ -22,83 +22,11 @@
|
|||
|
||||
<!-- 附件标签页 -->
|
||||
<el-tab-pane label="附件">
|
||||
<div v-if="loading" class="loading-container">
|
||||
<el-skeleton :rows="5" animated />
|
||||
</div>
|
||||
|
||||
<div v-else class="attachment-container">
|
||||
<!-- 图片展示部分 -->
|
||||
<div class="section" v-if="stationSite.picUrls?.length">
|
||||
<h3 class="section-title">图片</h3>
|
||||
<div class="image-list">
|
||||
<div
|
||||
v-for="(url, index) in stationSite.picUrls"
|
||||
:key="index"
|
||||
class="image-item"
|
||||
>
|
||||
<el-image
|
||||
:src="url"
|
||||
:preview-src-list="stationSite.picUrls"
|
||||
:initial-index="index"
|
||||
fit="cover"
|
||||
class="thumbnail"
|
||||
>
|
||||
<template #error>
|
||||
<div class="image-error">
|
||||
<span>加载失败</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 文件展示部分 -->
|
||||
<div class="section" v-if="stationSite.fileUrls?.length">
|
||||
<h3 class="section-title">文件</h3>
|
||||
<div class="file-list">
|
||||
<div
|
||||
v-for="(url, index) in stationSite.fileUrls"
|
||||
:key="index"
|
||||
class="file-item"
|
||||
>
|
||||
<el-icon class="file-icon"><Document /></el-icon>
|
||||
<div class="file-info">
|
||||
<a
|
||||
:href="url"
|
||||
target="_blank"
|
||||
class="file-name"
|
||||
@click.prevent="downloadFile(url)"
|
||||
>
|
||||
{{ extractFileName(url) }}
|
||||
</a>
|
||||
<div class="file-actions">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@click="downloadFile(url)"
|
||||
>
|
||||
下载
|
||||
</el-button>
|
||||
<el-button
|
||||
type="info"
|
||||
link
|
||||
@click="previewFile(url)"
|
||||
>
|
||||
预览
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 空状态显示 -->
|
||||
<el-empty
|
||||
v-if="!stationSite.picUrls?.length && !stationSite.fileUrls?.length"
|
||||
description="暂无附件数据"
|
||||
/>
|
||||
</div>
|
||||
<AttachmentTab
|
||||
:loading="loading"
|
||||
:pic-urls="stationSite.picUrls"
|
||||
:file-urls="stationSite.fileUrls"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<!-- <el-tabs>
|
||||
<el-tab-pane label="操作日志">
|
||||
|
|
@ -128,6 +56,7 @@ import FollowUpList from '@/views/crm/followup/components/FollowUpList.vue'
|
|||
import StationSiteForm from '../StationSiteForm.vue'
|
||||
import CrmTransferForm from '@/views/crm/permission/components/TransferForm.vue'
|
||||
import { ElMessage, ElLoading } from 'element-plus'
|
||||
import AttachmentTab from '@/components/AttachmentFile/index.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const stationSiteId = ref<number>()
|
||||
|
|
|
|||
|
|
@ -24,7 +24,17 @@
|
|||
<el-form-item label="显示排序" prop="sort">
|
||||
<el-input-number v-model="formData.sort" :min="0" controls-position="right" />
|
||||
</el-form-item>
|
||||
<el-form-item label="负责人" prop="leaderUserId">
|
||||
<el-form-item label="部门类型" prop="type">
|
||||
<el-select v-model="formData.type" clearable placeholder="请选择类型">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_DEPT_TYPE)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="负责人" prop="leaderUserId">
|
||||
<el-select v-model="formData.leaderUserId" clearable placeholder="请输入负责人">
|
||||
<el-option
|
||||
v-for="item in userList"
|
||||
|
|
@ -33,14 +43,14 @@
|
|||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="联系电话" prop="phone">
|
||||
<el-input v-model="formData.phone" maxlength="11" placeholder="请输入联系电话" />
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="formData.email" maxlength="50" placeholder="请输入邮箱" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-form-item label="状态" prop="status" width="300px">
|
||||
<el-select v-model="formData.status" clearable placeholder="请选择状态">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
|
||||
|
|
@ -83,13 +93,15 @@ const formData = ref({
|
|||
leaderUserId: undefined,
|
||||
phone: undefined,
|
||||
email: undefined,
|
||||
status: CommonStatusEnum.ENABLE
|
||||
status: CommonStatusEnum.ENABLE,
|
||||
type: undefined
|
||||
})
|
||||
const formRules = reactive<FormRules>({
|
||||
parentId: [{ required: true, message: '上级部门不能为空', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '部门名称不能为空', trigger: 'blur' }],
|
||||
sort: [{ required: true, message: '显示排序不能为空', trigger: 'blur' }],
|
||||
email: [{ type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }],
|
||||
type: [{ required: true, message: '部门类型不能为空', trigger: ['blur', 'change'] }],
|
||||
phone: [
|
||||
{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: '请输入正确的手机号码', trigger: 'blur' }
|
||||
],
|
||||
|
|
|
|||
|
|
@ -59,25 +59,31 @@
|
|||
:default-expand-all="isExpandAll"
|
||||
v-if="refreshTable"
|
||||
>
|
||||
<el-table-column prop="name" label="部门名称" />
|
||||
<el-table-column prop="name" label="部门名称" width="500px" />
|
||||
<!--
|
||||
<el-table-column prop="leader" label="负责人">
|
||||
<template #default="scope">
|
||||
{{ userList.find((user) => user.id === scope.row.leaderUserId)?.nickname }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column> -->
|
||||
<el-table-column prop="sort" label="排序" />
|
||||
<el-table-column prop="status" label="状态">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
<el-table-column label="部门类型" align="center" prop="type" width="150px">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.SYSTEM_DEPT_TYPE" :value="scope.row.type" width="300px"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
width="180"
|
||||
:formatter="dateFormatter"
|
||||
/>
|
||||
/> -->
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
|
|
|
|||
Loading…
Reference in New Issue