收款计划

pull/853/head
wersd 2025-06-29 09:39:05 +08:00
parent 0fb01cd478
commit 05f5087306
22 changed files with 969 additions and 358 deletions

View File

@ -5,14 +5,18 @@ export interface ContractVO {
id: number id: number
name: string name: string
no: string no: string
customerId: number[] customerId: number
customer?:{ customerName?: string
otherCustomerId: number[]
otherCustomer?:{
id: number id: number
name: string name: string
} }
businessId: number businessId: number
businessName: string businessName: string
deptId: number
deptName?: string
contactLastTime: Date contactLastTime: Date
ownerUserId: number ownerUserId: number
ownerUserName?: string ownerUserName?: string
@ -38,6 +42,8 @@ export interface ContractVO {
creator: string creator: string
creatorName: string creatorName: string
updateTime?: Date updateTime?: Date
picUrls?: string[]
fileUrls?: string[]
products?: [ products?: [
{ {
id: number id: number

View File

@ -4,6 +4,7 @@ export interface ReceivableVO {
id: number id: number
no: string no: string
planId?: number planId?: number
period?: number // 期数
customerId?: number customerId?: number
customerName?: string customerName?: string
contractId?: number contractId?: number

View File

@ -11,6 +11,8 @@ export interface ReceivablePlanVO {
remindTime: Date remindTime: Date
customerId: number customerId: number
customerName?: string customerName?: string
deptId: number
deptName?: string
contractId?: number contractId?: number
contractNo?: string contractNo?: string
ownerUserId: number ownerUserId: number

View File

@ -10,6 +10,7 @@ export interface DeptVO {
phone: string phone: string
email: string email: string
createTime: Date createTime: Date
type: number
} }
// 查询部门(精简)列表 // 查询部门(精简)列表
@ -17,6 +18,11 @@ export const getSimpleDeptList = async (): Promise<DeptVO[]> => {
return await request.get({ url: '/system/dept/simple-list' }) 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) => { export const getDeptPage = async (params: PageParam) => {
return await request.get({ url: '/system/dept/list', params }) return await request.get({ url: '/system/dept/list', params })

View File

@ -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>

View File

@ -129,6 +129,7 @@ export enum DICT_TYPE {
SYSTEM_MAIL_SEND_STATUS = 'system_mail_send_status', SYSTEM_MAIL_SEND_STATUS = 'system_mail_send_status',
SYSTEM_NOTIFY_TEMPLATE_TYPE = 'system_notify_template_type', SYSTEM_NOTIFY_TEMPLATE_TYPE = 'system_notify_template_type',
SYSTEM_SOCIAL_TYPE = 'system_social_type', SYSTEM_SOCIAL_TYPE = 'system_social_type',
SYSTEM_DEPT_TYPE = 'system_dept_type',
// ========== INFRA 模块 ========== // ========== INFRA 模块 ==========
INFRA_BOOLEAN_STRING = 'infra_boolean_string', INFRA_BOOLEAN_STRING = 'infra_boolean_string',

View File

@ -14,7 +14,12 @@
</el-form-item> </el-form-item>
</el-col> --> </el-col> -->
<el-col :span="8"> <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 <el-select
v-model="formData.customerId" v-model="formData.customerId"
placeholder="请选择客户签约方 " placeholder="请选择客户签约方 "
@ -23,6 +28,26 @@
:multiple-limit="3" :multiple-limit="3"
filterable filterable
clearable 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 multiple
> >
<el-option <el-option
@ -35,7 +60,7 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item label="公司签约方主体" prop="deptId"> <el-form-item label="公司签约方" prop="deptId">
<el-select <el-select
v-model="formData.deptId" v-model="formData.deptId"
class="w-1/1" class="w-1/1"
@ -49,27 +74,6 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </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-row> <el-row>
<el-col :span="8"> <el-col :span="8">
@ -147,7 +151,7 @@
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="8"> <el-col>
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" type="textarea" /> <el-input v-model="formData.remark" placeholder="请输入备注" type="textarea" />
</el-form-item> </el-form-item>
@ -167,7 +171,7 @@
</ContentWrap> </ContentWrap>
<el-row> <el-row>
<el-col :span="8"> <el-col :span="8">
<el-form-item label="产品总金额" prop="totalProductPrice"> <el-form-item label="合同总金额" prop="totalProductPrice">
<el-input <el-input
disabled disabled
v-model="formData.totalProductPrice" v-model="formData.totalProductPrice"
@ -175,7 +179,7 @@
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <!-- <el-col :span="8">
<el-form-item label="整单折扣(%" prop="discountPercent"> <el-form-item label="整单折扣(%" prop="discountPercent">
<el-input-number <el-input-number
v-model="formData.discountPercent" v-model="formData.discountPercent"
@ -196,8 +200,14 @@
:formatter="erpPriceInputFormatter" :formatter="erpPriceInputFormatter"
/> />
</el-form-item> </el-form-item>
</el-col> </el-col> -->
</el-row> </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> </el-form>
<template #footer> <template #footer>
<el-button :disabled="formLoading" type="primary" @click="submitForm"></el-button> <el-button :disabled="formLoading" type="primary" @click="submitForm"></el-button>
@ -228,7 +238,8 @@ const formData = ref({
id: undefined, id: undefined,
no: undefined, no: undefined,
name: undefined, name: undefined,
customerId: [], customerId: undefined,
otherCustomerId: [],
contractStatus: undefined, contractStatus: undefined,
contractType: undefined, contractType: undefined,
contractAttribute: undefined, contractAttribute: undefined,
@ -243,16 +254,34 @@ const formData = ref({
discountPercent: 0, discountPercent: 0,
totalProductPrice: undefined, totalProductPrice: undefined,
remark: 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({ const formRules = reactive({
name: [{ required: true, message: '合同名称不能为空', trigger: 'blur' }], name: [{ required: true, message: '合同名称不能为空', trigger: 'blur' }],
customerId: [{ required: true, message: '客户不能为空', trigger: 'blur' }], customerId: [{ required: true, message: '主签约方不能为空', trigger: 'blur' }],
orderDate: [{ required: true, message: '下单日期不能为空', trigger: 'blur' }], orderDate: [{ required: true, message: '下单日期不能为空', trigger: 'blur' }],
ownerUserId: [{ required: true, message: '负责人不能为空', trigger: 'blur' }],
contractStatus: [{ required: true, message: '合同状态不能为空', trigger: 'blur' }], contractStatus: [{ required: true, message: '合同状态不能为空', trigger: 'blur' }],
contractType: [{ 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 formRef = ref() // Ref
const userOptions = ref<UserApi.UserVO[]>([]) // const userOptions = ref<UserApi.UserVO[]>([]) //
@ -305,13 +334,13 @@ const open = async (type: string, id?: number) => {
// //
userOptions.value = await UserApi.getSimpleUserList() userOptions.value = await UserApi.getSimpleUserList()
// //
if (formType.value === 'create') { // if (formType.value === 'create') {
formData.value.ownerUserId = useUserStore().getUser.id // formData.value.ownerUserId = useUserStore().getUser.id
} // }
// //
contactList.value = await ContactApi.getSimpleContactList() contactList.value = await ContactApi.getSimpleContactList()
// //
deptList.value = await DeptApi.getSimpleDeptList() deptList.value = await DeptApi.querySimpleDeptList()
} }
defineExpose({ open }) // open defineExpose({ open }) // open
@ -322,6 +351,19 @@ const submitForm = async () => {
if (!formRef) return if (!formRef) return
const valid = await formRef.value.validate() const valid = await formRef.value.validate()
if (!valid) return 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 formLoading.value = true
productFormRef.value.validate() productFormRef.value.validate()
@ -348,7 +390,8 @@ const resetForm = () => {
id: undefined, id: undefined,
no: undefined, no: undefined,
name: undefined, name: undefined,
customerId: [], customerId: undefined,
otherCustomerId: [],
contractStatus: undefined, contractStatus: undefined,
contractType: undefined, contractType: undefined,
contractAttribute: undefined, contractAttribute: undefined,
@ -363,7 +406,9 @@ const resetForm = () => {
discountPercent: 0, discountPercent: 0,
totalProductPrice: undefined, totalProductPrice: undefined,
remark: undefined, remark: undefined,
products: [] products: [],
picUrls: [],
fileUrls: [],
} }
formRef.value?.resetFields() formRef.value?.resetFields()
} }

View File

@ -12,48 +12,33 @@
<el-table-column label="序号" type="index" align="center" width="60" /> <el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="产品名称" min-width="180"> <el-table-column label="产品名称" min-width="180">
<template #default="{ row, $index }"> <template #default="{ row, $index }">
<el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!"> <el-form-item :prop="`${$index}.productName`" :rules="formRules.productName" class="mb-0px!">
<el-select <el-input
v-model="row.productId" v-model="row.productName"
clearable placeholder="请输入产品名称"
filterable />
@change="onChangeProduct($event, row)" </el-form-item>
placeholder="请选择产品" </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 <el-option
v-for="item in productList" v-for="dict in getIntDictOptions(DICT_TYPE.CRM_PRODUCT_UNIT)"
:key="item.id" :key="dict.value"
:label="item.name" :label="dict.label"
:value="item.id" :value="dict.value"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
</template> </template>
</el-table-column> </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"> <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 }"> <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 <el-input-number
v-model="row.contractPrice" v-model="row.productPrice"
controls-position="right" controls-position="right"
:min="0.001" :min="0.001"
:precision="2" :precision="2"
@ -96,27 +81,39 @@
<script setup lang="ts"> <script setup lang="ts">
import * as ProductApi from '@/api/crm/product' import * as ProductApi from '@/api/crm/product'
import { erpPriceInputFormatter, erpPriceMultiply } from '@/utils' import { erpPriceInputFormatter, erpPriceMultiply } from '@/utils'
import { DICT_TYPE } from '@/utils/dict' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
const props = defineProps<{ const props = defineProps<{
products: undefined products: any[]
disabled: false disabled: boolean
}>() }>()
const formLoading = ref(false) // 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({ const formRules = reactive({
productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }], productName: [{ required: true, message: '产品名称不能为空', trigger: 'blur' }],
contractPrice: [{ required: true, message: '合同价格不能为空', trigger: 'blur' }], productUnit: [{ required: true, message: '单位不能为空', trigger: 'blur' }],
productPrice: [{ required: true, message: '价格不能为空', trigger: 'blur' }],
count: [{ required: true, message: '产品数量不能为空', trigger: 'blur' }] count: [{ required: true, message: '产品数量不能为空', trigger: 'blur' }]
}) })
const formRef = ref([]) // Ref const formRef = ref([]) // Ref
const productList = ref<ProductApi.ProductVO[]>([]) //
/** 初始化设置产品项 */ /** 初始化设置产品项 */
watch( watch(
() => props.products, () => props.products,
async (val) => { (val) => {
formData.value = val formData.value = val || []
}, },
{ immediate: true } { immediate: true }
) )
@ -130,8 +127,8 @@ watch(
} }
// //
val.forEach((item) => { val.forEach((item) => {
if (item.contractPrice != null && item.count != null) { if (item.productPrice != null && item.count != null) {
item.totalPrice = erpPriceMultiply(item.contractPrice, item.count) item.totalPrice = erpPriceMultiply(item.productPrice, item.count)
} else { } else {
item.totalPrice = undefined item.totalPrice = undefined
} }
@ -142,14 +139,13 @@ watch(
/** 新增按钮操作 */ /** 新增按钮操作 */
const handleAdd = () => { const handleAdd = () => {
const row = { const row: ProductRow = {
id: undefined, id: undefined,
productId: undefined, productName: undefined,
productUnit: undefined, // productUnit: undefined, //
productNo: undefined, //
productPrice: undefined, // productPrice: undefined, //
contractPrice: undefined, count: 1,
count: 1 totalPrice: undefined
} }
formData.value.push(row) formData.value.push(row)
} }
@ -159,17 +155,6 @@ const handleDelete = (index: number) => {
formData.value.splice(index, 1) 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 = () => { const validate = () => {
return formRef.value.validate() return formRef.value.validate()
@ -178,6 +163,7 @@ defineExpose({ validate })
/** 初始化 */ /** 初始化 */
onMounted(async () => { onMounted(async () => {
productList.value = await ProductApi.getProductSimpleList() // productList
// productList.value = await ProductApi.getProductSimpleList()
}) })
</script> </script>

View File

@ -20,23 +20,22 @@
<!-- <el-descriptions-item label="合同编号">{{ contract.no }}</el-descriptions-item> --> <!-- <el-descriptions-item label="合同编号">{{ contract.no }}</el-descriptions-item> -->
<el-descriptions-item label="合同名称">{{ contract.name }}</el-descriptions-item> <el-descriptions-item label="合同名称">{{ contract.name }}</el-descriptions-item>
<el-descriptions-item label="客户签约方"> <el-descriptions-item label="客户签约方">
{{ contract.customerName || '' }}
</el-descriptions-item>
<el-descriptions-item label="其他签约方">
<div> <div>
<template v-if="Array.isArray(contract.customer)"> <template v-if="Array.isArray(contract.otherCustomer)">
<span v-for="(c, idx) in contract.otherCustomer" :key="c.id">
<span v-for="(c, idx) in contract.customer" :key="c.id"> {{ c.name }}<span v-if="idx < contract.otherCustomer.length - 1"><br /> </span>
{{ c.name }}<span v-if="idx < contract.customer.length - 1"><br /> </span>
</span> </span>
</template> </template>
<template v-else> <template v-else>
{{ contract.customer?.name || '' }} {{ contract.otherCustomer?.name || '' }}
</template> </template>
</div> </div>
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="责任人"> <el-descriptions-item label="公司签约方">
{{ contract.ownerUserName }} {{ contract.deptName }}
</el-descriptions-item>
<el-descriptions-item label="合同金额(元)">
{{ erpPriceInputFormatter(contract.totalPrice) }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="签订时间"> <el-descriptions-item label="签订时间">
{{ formatDate(contract.orderDate, 'YYYY-MM-DD') }} {{ formatDate(contract.orderDate, 'YYYY-MM-DD') }}
@ -48,7 +47,13 @@
{{ formatDate(contract.endTime, 'YYYY-MM-DD') }} {{ formatDate(contract.endTime, 'YYYY-MM-DD') }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="合同状态"> <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>
<el-descriptions-item label="合同金额(元)"> <el-descriptions-item label="合同金额(元)">
{{ erpPriceInputFormatter(contract.totalPrice) }} {{ erpPriceInputFormatter(contract.totalPrice) }}

View File

@ -3,7 +3,7 @@
<el-table :data="contract.products" :stripe="true" :show-overflow-tooltip="true"> <el-table :data="contract.products" :stripe="true" :show-overflow-tooltip="true">
<el-table-column <el-table-column
align="center" align="center"
label="产品名称" label="产品或服务"
fixed="left" fixed="left"
prop="productName" prop="productName"
min-width="160" min-width="160"
@ -12,7 +12,6 @@
{{ scope.row.productName }} {{ scope.row.productName }}
</template> </template>
</el-table-column> </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"> <el-table-column align="center" label="产品单位" prop="productUnit" min-width="160">
<template #default="{ row }"> <template #default="{ row }">
<dict-tag :type="DICT_TYPE.CRM_PRODUCT_UNIT" :value="row.productUnit" /> <dict-tag :type="DICT_TYPE.CRM_PRODUCT_UNIT" :value="row.productUnit" />
@ -25,13 +24,13 @@
min-width="140" min-width="140"
:formatter="erpPriceTableColumnFormatter" :formatter="erpPriceTableColumnFormatter"
/> />
<el-table-column <!-- <el-table-column
label="合同价格(元)" label="合同价格(元)"
align="center" align="center"
prop="contractPrice" prop="contractPrice"
min-width="140" min-width="140"
:formatter="erpPriceTableColumnFormatter" :formatter="erpPriceTableColumnFormatter"
/> /> -->
<el-table-column <el-table-column
align="center" align="center"
label="数量" label="数量"
@ -48,10 +47,10 @@
/> />
</el-table> </el-table>
<el-row class="mt-10px" justify="end"> <el-row class="mt-10px" justify="end">
<el-col :span="3"> 整单折扣{{ erpPriceInputFormatter(contract.discountPercent) }}% </el-col> <!-- <el-col :span="3"> 整单折扣{{ erpPriceInputFormatter(contract.discountPercent) }}% </el-col> -->
<el-col :span="4"> <!-- <el-col :span="4">
产品总金额{{ erpPriceInputFormatter(contract.totalProductPrice) }} 产品总金额{{ erpPriceInputFormatter(contract.) }}
</el-col> </el-col> -->
</el-row> </el-row>
</ContentWrap> </ContentWrap>
</template> </template>

View File

@ -1,37 +1,35 @@
<!-- 合同详情页面组件--> <!-- 合同详情页面组件-->
<template> <template>
<ContractDetailsHeader v-loading="loading" :contract="contract"> <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>
<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> </ContractDetailsHeader>
<el-col> <el-col>
<el-tabs> <el-tabs>
<el-tab-pane label="产品"> <el-tab-pane label="合同清单">
<ContractProductList :contract="contract" /> <ContractProductList :contract="contract" />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="付款"> <el-tab-pane label="付款计划">
<ReceivablePlanList <ReceivablePlanList
:contract-id="contract.id!" :contract-id="contract.id!"
:customer-id="Array.isArray(contract.customerId) ? contract.customerId[0] : contract.customerId" :customer-id="contract.customerId"
@create-receivable="createReceivable" @create-receivable="createReceivable"
/> />
<ReceivableList <ReceivableList
ref="receivableListRef" ref="receivableListRef"
:contract-id="contract.id!" :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>
<el-tab-pane label="团队成员"> <el-tab-pane label="合同明细">
<PermissionList <AttachmentTab
ref="permissionListRef" :loading="loading"
:biz-id="contract.id!" :pic-urls="contract.picUrls"
:biz-type="BizTypeEnum.CRM_CONTRACT" :file-urls="contract.fileUrls"
:show-action="true"
@quit-team="close"
/> />
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="操作日志"> <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 PermissionList from '@/views/crm/permission/components/PermissionList.vue'
import ReceivableList from '@/views/crm/receivable/components/ReceivableList.vue' import ReceivableList from '@/views/crm/receivable/components/ReceivableList.vue'
import ReceivablePlanList from '@/views/crm/receivable/plan/components/ReceivablePlanList.vue' import ReceivablePlanList from '@/views/crm/receivable/plan/components/ReceivablePlanList.vue'
import AttachmentTab from '@/components/AttachmentFile/index.vue'
defineOptions({ name: 'CrmContractDetail' }) defineOptions({ name: 'CrmContractDetail' })
const props = defineProps<{ id?: number }>() const props = defineProps<{ id?: number }>()

View File

@ -28,13 +28,13 @@
placeholder="请输入合同名称" placeholder="请输入合同名称"
@keyup.enter="handleQuery" @keyup.enter="handleQuery"
/> />
<el-form-item label="客户" prop="customerId"> <el-form-item label="客户签约方" prop="customerId">
<el-select <el-select
v-model="queryParams.customerId" v-model="queryParams.customerId"
class="!w-240px" class="!w-240px"
clearable clearable
lable-key="name" lable-key="name"
placeholder="请选择客户" placeholder="请选择客户签约方"
value-key="id" value-key="id"
@keyup.enter="handleQuery" @keyup.enter="handleQuery"
> >
@ -76,28 +76,27 @@
<!-- 列表 --> <!-- 列表 -->
<ContentWrap> <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="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"> <template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)"> <el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
{{ scope.row.name }} {{ scope.row.name }}
</el-link> </el-link>
</template> </template>
</el-table-column> </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"> <template #default="scope">
<el-link <el-link
:underline="false" :underline="false"
type="primary" type="primary"
@click="openCustomerDetail(scope.row.customer[0].id)" @click="openCustomerDetail(scope.row.customerId)"
> >
{{ scope.row.customer[0].name }} {{ scope.row.customerName }}
</el-link> </el-link>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="所属部门" prop="ownerUserDeptName" width="160" />
<!-- <el-table-column <!-- <el-table-column
align="center" align="center"
label="合同金额(元)" label="合同金额(元)"
@ -119,13 +118,13 @@
width="160" width="160"
:formatter="dateFormatter2" :formatter="dateFormatter2"
/> />
<el-table-column <!-- <el-table-column
align="center" align="center"
label="已付款金额(万元)" label="已付款金额(万元)"
prop="totalReceivablePrice" prop="totalReceivablePrice"
width="160" width="160"
:formatter="erpPriceTableColumnFormatter" :formatter="erpPriceTableColumnFormatter"
/> /> -->
<!-- <el-table-column <!-- <el-table-column
align="center" align="center"
label="未付款金额(元)" label="未付款金额(元)"
@ -137,14 +136,14 @@
{{ erpPriceInputFormatter(scope.row.totalPrice - scope.row.totalReceivablePrice) }} {{ erpPriceInputFormatter(scope.row.totalPrice - scope.row.totalReceivablePrice) }}
</template> </template>
</el-table-column> --> </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"> <template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_CONTRACT_STATUS" :value="scope.row.contractStatus" /> <dict-tag :type="DICT_TYPE.CRM_CONTRACT_STATUS" :value="scope.row.contractStatus" />
</template> </template>
</el-table-column> </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"> <template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_CONTRACT_TYPE" :value="scope.row.contractType" /> <dict-tag :type="DICT_TYPE.CRM_CONTRACT_TYPE" :value="scope.row.contractType" />
</template> </template>
@ -160,7 +159,7 @@
> >
编辑 编辑
</el-button> </el-button>
<el-button <!-- <el-button
v-if="scope.row.auditStatus === 0" v-if="scope.row.auditStatus === 0"
v-hasPermi="['crm:contract:update']" v-hasPermi="['crm:contract:update']"
link link
@ -168,8 +167,8 @@
@click="handleSubmit(scope.row)" @click="handleSubmit(scope.row)"
> >
提交审核 提交审核
</el-button> </el-button> -->
<el-button <!-- <el-button
v-else v-else
link link
v-hasPermi="['crm:contract:update']" v-hasPermi="['crm:contract:update']"
@ -177,7 +176,7 @@
@click="handleProcessDetail(scope.row)" @click="handleProcessDetail(scope.row)"
> >
查看审批 查看审批
</el-button> </el-button> -->
<el-button <el-button
v-hasPermi="['crm:contract:delete']" v-hasPermi="['crm:contract:delete']"
link link
@ -329,4 +328,45 @@ onMounted(async () => {
await getList() await getList()
customerList.value = await CustomerApi.getCustomerSimpleList() 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> </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>

View File

@ -63,7 +63,7 @@
<el-option <el-option
v-for="data in contractList" v-for="data in contractList"
:key="data.id" :key="data.id"
:disabled="data.auditStatus !== 20"
:label="data.name" :label="data.name"
:value="data.id!" :value="data.id!"
/> />

View File

@ -1,39 +1,45 @@
<template> <template>
<!-- 操作栏 --> <!-- 操作栏 -->
<el-row justify="end"> <el-row>
<el-button @click="openForm('create')"> <text class="text-xs font-bold">
实付明细
</text>
<!-- <el-button @click="openForm('create')">
<Icon class="mr-5px" icon="icon-park:income-one" /> <Icon class="mr-5px" icon="icon-park:income-one" />
创建付款 创建付款
</el-button> </el-button> -->
</el-row> </el-row>
<!-- 列表 --> <!-- 列表 -->
<ContentWrap class="mt-10px"> <ContentWrap class="mt-10px">
<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">
<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 <el-table-column
:formatter="dateFormatter2" :formatter="dateFormatter2"
align="center" align="center"
label="付款日期" label="实际付款日期"
prop="returnTime" 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"> <template #default="scope">
<dict-tag :type="DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE" :value="scope.row.returnType" /> <dict-tag :type="DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE" :value="scope.row.returnType" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <!-- <el-table-column align="center" label="负责人" prop="ownerUserName" /> -->
align="center" <!-- <el-table-column align="center" label="备注" prop="remark" /> -->
label="付款金额(元)" <!-- <el-table-column align="center" fixed="right" label="操作" width="130px">
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">
<template #default="scope"> <template #default="scope">
<el-button <el-button
v-hasPermi="['crm:receivable:update']" v-hasPermi="['crm:receivable:update']"
@ -52,7 +58,7 @@
删除 删除
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column> -->
</el-table> </el-table>
<!-- 分页 --> <!-- 分页 -->
<Pagination <Pagination

View File

@ -9,22 +9,24 @@
> >
<el-row> <el-row>
<el-col :span="12"> <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-input v-model="formData.period" disabled placeholder="保存时自动生成" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="负责人" prop="ownerUserId"> <el-form-item label="付款单位">
<el-select <el-select
v-model="formData.ownerUserId" v-model="formData.contractId"
:disabled="formType !== 'create'" disabled
class="w-1/1" class="w-1/1"
filterable
placeholder="请选择付款单位"
> >
<el-option <el-option
v-for="item in userOptions" v-for="data in contractList"
:key="item.id" :key="data.id"
:label="item.nickname" :label="data.deptName"
:value="item.id" :value="data.id!"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -32,14 +34,13 @@
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="客户名称" prop="customerId"> <el-form-item label="收款单位" prop="customerId">
<el-select <el-select
v-model="formData.customerId" v-model="formData.customerId"
:disabled="formType !== 'create'" disabled
class="w-1/1" class="w-1/1"
filterable filterable
placeholder="请选择客户" placeholder="请选择收款单位"
@change="handleCustomerChange"
> >
<el-option <el-option
v-for="item in customerList" v-for="item in customerList"
@ -54,7 +55,7 @@
<el-form-item label="合同名称" prop="contractId"> <el-form-item label="合同名称" prop="contractId">
<el-select <el-select
v-model="formData.contractId" v-model="formData.contractId"
:disabled="formType !== 'create' || !formData.customerId" disabled
class="w-1/1" class="w-1/1"
filterable filterable
placeholder="请选择合同" placeholder="请选择合同"
@ -71,14 +72,14 @@
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="计划付款金额" prop="price"> <el-form-item label="计划金额(元)" prop="price">
<el-input-number <el-input-number
v-model="formData.price" v-model="formData.price"
:min="0.01" :min="0.01"
:precision="2" :precision="2"
class="!w-100%" class="!w-100%"
controls-position="right" controls-position="right"
placeholder="请输入计划付款金额" placeholder="请输入计划金额"
/> />
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -95,7 +96,7 @@
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="12"> <!-- <el-col :span="12">
<el-form-item label="提前几天提醒" prop="remindDays"> <el-form-item label="提前几天提醒" prop="remindDays">
<el-input-number <el-input-number
v-model="formData.remindDays" v-model="formData.remindDays"
@ -116,10 +117,10 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col> -->
<el-col :span="24"> <el-col :span="24">
<el-form-item label="备注" prop="remark"> <el-form-item label="用途" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" type="textarea" /> <el-input v-model="formData.remark" placeholder="请输入用途" type="textarea" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@ -150,9 +151,7 @@ const formData = ref<ReceivablePlanApi.ReceivablePlanVO>({} as ReceivablePlanApi
const formRules = reactive({ const formRules = reactive({
price: [{ required: true, message: '计划付款金额不能为空', trigger: 'blur' }], price: [{ required: true, message: '计划付款金额不能为空', trigger: 'blur' }],
returnTime: [{ required: true, message: '计划付款日期不能为空', trigger: 'blur' }], returnTime: [{ required: true, message: '计划付款日期不能为空', trigger: 'blur' }],
customerId: [{ required: true, message: '客户编号不能为空', trigger: 'blur' }], remark: [{ required: true, message: '用途不能为空', trigger: 'blur' }]
contractId: [{ required: true, message: '合同编号不能为空', trigger: 'blur' }],
ownerUserId: [{ required: true, message: '负责人不能为空', trigger: 'blur' }]
}) })
const formRef = ref() // Ref const formRef = ref() // Ref
const customerList = ref<CustomerApi.CustomerVO[]>([]) // const customerList = ref<CustomerApi.CustomerVO[]>([]) //
@ -181,9 +180,9 @@ const open = async (type: string, id?: number, customerId?: number, contractId?:
// //
customerList.value = await CustomerApi.getCustomerSimpleList() customerList.value = await CustomerApi.getCustomerSimpleList()
// //
if (formType.value === 'create') { // if (formType.value === 'create') {
formData.value.ownerUserId = useUserStore().getUser.id // formData.value.ownerUserId = useUserStore().getUser.id
} // }
// customerId contractId // customerId contractId
if (customerId) { if (customerId) {
formData.value.customerId = customerId formData.value.customerId = customerId
@ -231,10 +230,13 @@ const resetForm = () => {
const handleCustomerChange = async (customerId: number) => { const handleCustomerChange = async (customerId: number) => {
// //
formData.value.contractId = undefined formData.value.contractId = undefined
formData.value.deptName = undefined
// //
if (customerId) { if (customerId) {
contractList.value = [] contractList.value = []
contractList.value = await ContractApi.getContractSimpleList(customerId) contractList.value = await ContractApi.getContractSimpleList(customerId)
} }
} }
</script> </script>

View File

@ -1,45 +1,51 @@
<template> <template>
<!-- 操作栏 --> <!-- 操作栏 -->
<el-row justify="end"> <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)"> <el-button @click="openForm('create', undefined)">
<Icon class="mr-5px" icon="icon-park:income" /> <Icon class="mr-5px" icon="icon-park:income" />
创建付款计划 创建付款计划
</el-button> </el-button>
</el-col>
</el-row> </el-row>
<!-- 列表 --> <!-- 列表 -->
<ContentWrap class="mt-10px"> <ContentWrap class="mt-10px">
<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">
<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 <el-table-column
:formatter="dateFormatter2" :formatter="dateFormatter2"
align="center" align="center"
label="计划付款日期" label="计划付款日期"
prop="returnTime" 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 <el-table-column
:formatter="dateFormatter2" :formatter="dateFormatter2"
align="center" align="center"
label="提醒日期" label="提醒日期"
prop="remindTime" prop="remindTime"
width="180px" width="180px"
/> /> -->
<el-table-column label="负责人" prop="ownerUserName" width="120" /> <!-- <el-table-column label="负责人" prop="ownerUserName" width="120" /> -->
<el-table-column align="center" label="备注" prop="remark" /> <el-table-column align="center" label="用途" prop="remark" min-width="300px"/>
<el-table-column align="center" fixed="right" label="操作" width="200px"> <el-table-column align="center" fixed="right" label="操作" width="200px">
<template #default="scope"> <template #default="scope">
<el-button <!-- <el-button
v-hasPermi="['crm:receivable:create']" v-hasPermi="['crm:receivable:create']"
link link
type="primary" type="primary"
@ -47,7 +53,7 @@
:disabled="scope.row.receivableId" :disabled="scope.row.receivableId"
> >
创建付款 创建付款
</el-button> </el-button> -->
<el-button <el-button
v-hasPermi="['crm:receivable-plan:update']" v-hasPermi="['crm:receivable-plan:update']"
link link

View File

@ -44,7 +44,7 @@
<Icon class="mr-5px" icon="ep:refresh" /> <Icon class="mr-5px" icon="ep:refresh" />
重置 重置
</el-button> </el-button>
<el-button <!-- <el-button
v-hasPermi="['crm:receivable-plan:create']" v-hasPermi="['crm:receivable-plan:create']"
plain plain
type="primary" type="primary"
@ -52,7 +52,7 @@
> >
<Icon class="mr-5px" icon="ep:plus" /> <Icon class="mr-5px" icon="ep:plus" />
新增 新增
</el-button> </el-button> -->
<el-button <el-button
v-hasPermi="['crm:receivable-plan:export']" v-hasPermi="['crm:receivable-plan:export']"
:loading="exportLoading" :loading="exportLoading"
@ -69,12 +69,15 @@
<!-- 列表 --> <!-- 列表 -->
<ContentWrap> <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 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"> <template #default="scope">
<el-link <el-link
:underline="false" :underline="false"
@ -85,7 +88,17 @@
</el-link> </el-link>
</template> </template>
</el-table-column> </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"> <el-table-column align="center" label="期数" prop="period">
<template #default="scope"> <template #default="scope">
<el-link :underline="false" type="primary" @click="openDetail(scope.row.id)"> <el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
@ -101,30 +114,8 @@
:formatter="erpPriceTableColumnFormatter" :formatter="erpPriceTableColumnFormatter"
/> />
<el-table-column <el-table-column
:formatter="dateFormatter2"
align="center" align="center"
label="计划付款日期" 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="实际付款金额(元)"
prop="receivable.price" prop="receivable.price"
width="160" width="160"
> >
@ -135,16 +126,16 @@
<el-text v-else>{{ erpPriceInputFormatter(0) }}</el-text> <el-text v-else>{{ erpPriceInputFormatter(0) }}</el-text>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <!-- <el-table-column
align="center" align="center"
label="实际付款日期" label="实际付款日期"
prop="receivable.returnTime" prop="receivable.returnTime"
width="180px" width="180px"
:formatter="dateFormatter2" :formatter="dateFormatter2"
/> /> -->
<el-table-column <el-table-column
align="center" align="center"
label="实际付款金额(元)" label="付款金额(元)"
prop="receivable.price" prop="receivable.price"
width="160" width="160"
> >
@ -155,21 +146,6 @@
<el-text v-else>{{ erpPriceInputFormatter(scope.row.price) }}</el-text> <el-text v-else>{{ erpPriceInputFormatter(scope.row.price) }}</el-text>
</template> </template>
</el-table-column> </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"> <el-table-column align="center" fixed="right" label="操作" width="180px">
<template #default="scope"> <template #default="scope">
<el-button <el-button
@ -245,11 +221,6 @@ const exportLoading = ref(false) // 导出的加载中
const activeName = ref('1') // tab const activeName = ref('1') // tab
const customerList = ref<CustomerApi.CustomerVO[]>([]) // const customerList = ref<CustomerApi.CustomerVO[]>([]) //
/** tab 切换 */
const handleTabClick = (tab: TabsPaneContext) => {
queryParams.sceneType = tab.paneName
handleQuery()
}
/** 查询列表 */ /** 查询列表 */
const getList = async () => { const getList = async () => {
@ -325,6 +296,10 @@ const openDetail = (id: number) => {
const openCustomerDetail = (id: number) => { const openCustomerDetail = (id: number) => {
push({ name: 'CrmCustomerDetail', params: { id } }) push({ name: 'CrmCustomerDetail', params: { id } })
} }
/** 打开合同详情 */
const openContractDetail = (id: number) => {
push({ name: 'CrmContractDetail', params: { id } })
}
/** 初始化 **/ /** 初始化 **/
onMounted(async () => { onMounted(async () => {

View File

@ -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) // 12
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>

View File

@ -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>

View File

@ -22,83 +22,11 @@
<!-- 附件标签页 --> <!-- 附件标签页 -->
<el-tab-pane label="附件"> <el-tab-pane label="附件">
<div v-if="loading" class="loading-container"> <AttachmentTab
<el-skeleton :rows="5" animated /> :loading="loading"
</div> :pic-urls="stationSite.picUrls"
:file-urls="stationSite.fileUrls"
<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>
</el-tab-pane> </el-tab-pane>
<!-- <el-tabs> <!-- <el-tabs>
<el-tab-pane label="操作日志"> <el-tab-pane label="操作日志">
@ -128,6 +56,7 @@ import FollowUpList from '@/views/crm/followup/components/FollowUpList.vue'
import StationSiteForm from '../StationSiteForm.vue' import StationSiteForm from '../StationSiteForm.vue'
import CrmTransferForm from '@/views/crm/permission/components/TransferForm.vue' import CrmTransferForm from '@/views/crm/permission/components/TransferForm.vue'
import { ElMessage, ElLoading } from 'element-plus' import { ElMessage, ElLoading } from 'element-plus'
import AttachmentTab from '@/components/AttachmentFile/index.vue'
const route = useRoute() const route = useRoute()
const stationSiteId = ref<number>() const stationSiteId = ref<number>()

View File

@ -24,7 +24,17 @@
<el-form-item label="显示排序" prop="sort"> <el-form-item label="显示排序" prop="sort">
<el-input-number v-model="formData.sort" :min="0" controls-position="right" /> <el-input-number v-model="formData.sort" :min="0" controls-position="right" />
</el-form-item> </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-select v-model="formData.leaderUserId" clearable placeholder="请输入负责人">
<el-option <el-option
v-for="item in userList" v-for="item in userList"
@ -33,14 +43,14 @@
:value="item.id" :value="item.id"
/> />
</el-select> </el-select>
</el-form-item> </el-form-item> -->
<el-form-item label="联系电话" prop="phone"> <el-form-item label="联系电话" prop="phone">
<el-input v-model="formData.phone" maxlength="11" placeholder="请输入联系电话" /> <el-input v-model="formData.phone" maxlength="11" placeholder="请输入联系电话" />
</el-form-item> </el-form-item>
<el-form-item label="邮箱" prop="email"> <el-form-item label="邮箱" prop="email">
<el-input v-model="formData.email" maxlength="50" placeholder="请输入邮箱" /> <el-input v-model="formData.email" maxlength="50" placeholder="请输入邮箱" />
</el-form-item> </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-select v-model="formData.status" clearable placeholder="请选择状态">
<el-option <el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
@ -83,13 +93,15 @@ const formData = ref({
leaderUserId: undefined, leaderUserId: undefined,
phone: undefined, phone: undefined,
email: undefined, email: undefined,
status: CommonStatusEnum.ENABLE status: CommonStatusEnum.ENABLE,
type: undefined
}) })
const formRules = reactive<FormRules>({ const formRules = reactive<FormRules>({
parentId: [{ required: true, message: '上级部门不能为空', trigger: 'blur' }], parentId: [{ required: true, message: '上级部门不能为空', trigger: 'blur' }],
name: [{ required: true, message: '部门名称不能为空', trigger: 'blur' }], name: [{ required: true, message: '部门名称不能为空', trigger: 'blur' }],
sort: [{ required: true, message: '显示排序不能为空', trigger: 'blur' }], sort: [{ required: true, message: '显示排序不能为空', trigger: 'blur' }],
email: [{ type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }], email: [{ type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }],
type: [{ required: true, message: '部门类型不能为空', trigger: ['blur', 'change'] }],
phone: [ phone: [
{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: '请输入正确的手机号码', trigger: 'blur' } { pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: '请输入正确的手机号码', trigger: 'blur' }
], ],

View File

@ -59,25 +59,31 @@
:default-expand-all="isExpandAll" :default-expand-all="isExpandAll"
v-if="refreshTable" v-if="refreshTable"
> >
<el-table-column prop="name" label="部门名称" /> <el-table-column prop="name" label="部门名称" width="500px" />
<!--
<el-table-column prop="leader" label="负责人"> <el-table-column prop="leader" label="负责人">
<template #default="scope"> <template #default="scope">
{{ userList.find((user) => user.id === scope.row.leaderUserId)?.nickname }} {{ userList.find((user) => user.id === scope.row.leaderUserId)?.nickname }}
</template> </template>
</el-table-column> </el-table-column> -->
<el-table-column prop="sort" label="排序" /> <el-table-column prop="sort" label="排序" />
<el-table-column prop="status" label="状态"> <el-table-column prop="status" label="状态">
<template #default="scope"> <template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template> </template>
</el-table-column> </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="创建时间" label="创建时间"
align="center" align="center"
prop="createTime" prop="createTime"
width="180" width="180"
:formatter="dateFormatter" :formatter="dateFormatter"
/> /> -->
<el-table-column label="操作" align="center"> <el-table-column label="操作" align="center">
<template #default="scope"> <template #default="scope">
<el-button <el-button