|
@@ -12,6 +12,24 @@
|
|
|
</el-button>
|
|
|
</template>
|
|
|
|
|
|
+ <template slot="menu" slot-scope="{row}">
|
|
|
+ <el-button type="text" size="small" icon="el-icon-view" @click="handleView(row)"
|
|
|
+ v-if="permission.order_lead_view">
|
|
|
+ 查看
|
|
|
+ </el-button>
|
|
|
+ <el-button type="text" size="small" icon="el-icon-edit" @click="handleEdit(row)"
|
|
|
+ v-if="permission.order_lead_edit">
|
|
|
+ 编辑
|
|
|
+ </el-button>
|
|
|
+ <el-button type="text" size="small" icon="el-icon-document" @click="handleViewDetail(row)">
|
|
|
+ 详细信息
|
|
|
+ </el-button>
|
|
|
+ <el-button type="text" size="small" icon="el-icon-delete" @click="handleRowDelete(row)"
|
|
|
+ v-if="permission.order_lead_delete">
|
|
|
+ 删除
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+
|
|
|
<template slot-scope="{row}" slot="status">
|
|
|
<el-tag :type="getStatusType(row.status)">
|
|
|
{{ getStatusText(row.status) }}
|
|
@@ -30,11 +48,55 @@
|
|
|
</span>
|
|
|
</template>
|
|
|
</avue-crud>
|
|
|
+
|
|
|
+ <!-- 线索详细信息弹窗 -->
|
|
|
+ <el-dialog
|
|
|
+ title="线索详细信息管理"
|
|
|
+ :visible.sync="detailDialogVisible"
|
|
|
+ width="80%"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ :destroy-on-close="true"
|
|
|
+ append-to-body>
|
|
|
+ <div v-if="currentLead">
|
|
|
+ <el-descriptions :column="3" border class="lead-info-desc">
|
|
|
+ <el-descriptions-item label="线索编码">{{ currentLead.leadCode }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="客户名称">{{ currentLead.customerName }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="联系人">{{ currentLead.contactName }}</el-descriptions-item>
|
|
|
+ <el-descriptions-item label="线索标题" :span="3">{{ currentLead.title }}</el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <avue-crud
|
|
|
+ :option="detailOption"
|
|
|
+ :data="detailData"
|
|
|
+ ref="detailCrud"
|
|
|
+ v-model="detailForm"
|
|
|
+ :page.sync="detailPage"
|
|
|
+ :permission="detailPermissionList"
|
|
|
+ :before-open="detailBeforeOpen"
|
|
|
+ :table-loading="detailLoading"
|
|
|
+ @row-del="detailRowDel"
|
|
|
+ @row-update="detailRowUpdate"
|
|
|
+ @row-save="detailRowSave"
|
|
|
+ @selection-change="detailSelectionChange"
|
|
|
+ @current-change="detailCurrentChange"
|
|
|
+ @size-change="detailSizeChange"
|
|
|
+ @refresh-change="detailRefreshChange"
|
|
|
+ @on-load="detailOnLoad">
|
|
|
+ <template slot="menuLeft">
|
|
|
+ <el-button type="danger" size="small" plain icon="el-icon-delete"
|
|
|
+ @click="handleDetailDelete" :disabled="detailSelectionList.length === 0">
|
|
|
+ 删除
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </avue-crud>
|
|
|
+ </el-dialog>
|
|
|
</basic-container>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import { getList, add, update, remove, getDetail } from '@/api/order/lead'
|
|
|
+import { getList as getDetailList, add as addDetail, update as updateDetail, remove as removeDetail, getDetail as getDetailDetail } from '@/api/order/lead-detail'
|
|
|
import { getCustomerList } from '@/api/common/index'
|
|
|
import { mapGetters } from 'vuex'
|
|
|
|
|
@@ -84,6 +146,118 @@ export default {
|
|
|
data() {
|
|
|
return {
|
|
|
/**
|
|
|
+ * 详细信息表格配置
|
|
|
+ */
|
|
|
+ detailOption: {
|
|
|
+ height: 'auto',
|
|
|
+ calcHeight: 30,
|
|
|
+ tip: false,
|
|
|
+ searchShow: false,
|
|
|
+ border: true,
|
|
|
+ index: true,
|
|
|
+ viewBtn: true,
|
|
|
+ selection: true,
|
|
|
+ dialogClickModal: false,
|
|
|
+ column: [
|
|
|
+ {
|
|
|
+ label: '详细信息内容',
|
|
|
+ prop: 'detailText',
|
|
|
+ type: 'textarea',
|
|
|
+ span: 24,
|
|
|
+ minRows: 4,
|
|
|
+ maxRows: 8,
|
|
|
+ rules: [{
|
|
|
+ required: true,
|
|
|
+ message: '请输入详细信息内容',
|
|
|
+ trigger: 'blur'
|
|
|
+ }, {
|
|
|
+ min: 10,
|
|
|
+ message: '详细信息内容至少10个字符',
|
|
|
+ trigger: 'blur'
|
|
|
+ }],
|
|
|
+ overHidden: true,
|
|
|
+ width: 400
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '创建时间',
|
|
|
+ prop: 'createTime',
|
|
|
+ type: 'datetime',
|
|
|
+ format: 'yyyy-MM-dd HH:mm:ss',
|
|
|
+ valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
|
|
+ addDisplay: false,
|
|
|
+ editDisplay: false,
|
|
|
+ viewDisplay: true,
|
|
|
+ width: 180
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '更新时间',
|
|
|
+ prop: 'updateTime',
|
|
|
+ type: 'datetime',
|
|
|
+ format: 'yyyy-MM-dd HH:mm:ss',
|
|
|
+ valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
|
|
+ addDisplay: false,
|
|
|
+ editDisplay: false,
|
|
|
+ viewDisplay: true,
|
|
|
+ width: 180
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详细信息权限列表
|
|
|
+ */
|
|
|
+ detailPermissionList: {
|
|
|
+ addBtn: true,
|
|
|
+ viewBtn: true,
|
|
|
+ delBtn: false,
|
|
|
+ editBtn: true,
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详细信息分页信息
|
|
|
+ * @type {{total: number, currentPage: number, pageSize: number}}
|
|
|
+ */
|
|
|
+ detailPage: {
|
|
|
+ total: 0,
|
|
|
+ currentPage: 1,
|
|
|
+ pageSize: 10
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详细信息加载状态
|
|
|
+ * @type {boolean}
|
|
|
+ */
|
|
|
+ detailLoading: false,
|
|
|
+ /**
|
|
|
+ * 详细信息弹窗显示状态
|
|
|
+ * @type {boolean}
|
|
|
+ */
|
|
|
+ detailDialogVisible: false,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 当前选中的线索
|
|
|
+ * @type {LeadRecord|null}
|
|
|
+ */
|
|
|
+ currentLead: null,
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详细信息表格数据
|
|
|
+ * @type {LeadDetailRecord[]}
|
|
|
+ */
|
|
|
+ detailData: [],
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详细信息表单数据
|
|
|
+ * @type {LeadDetailRecord}
|
|
|
+ */
|
|
|
+ detailForm: {},
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详细信息选中的数据列表
|
|
|
+ * @type {LeadDetailRecord[]}
|
|
|
+ */
|
|
|
+ detailSelectionList: [],
|
|
|
+ /**
|
|
|
* 表格数据
|
|
|
* @type {LeadRecord[]}
|
|
|
*/
|
|
@@ -389,6 +563,17 @@ export default {
|
|
|
ids.push(ele.id)
|
|
|
})
|
|
|
return ids.join(',')
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 详细信息选中的ID列表
|
|
|
+ * @returns {string} 逗号分隔的ID字符串
|
|
|
+ */
|
|
|
+ detailIds() {
|
|
|
+ const ids = []
|
|
|
+ this.detailSelectionList.forEach(ele => {
|
|
|
+ ids.push(ele.id)
|
|
|
+ })
|
|
|
+ return ids.join(',')
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
@@ -779,6 +964,285 @@ export default {
|
|
|
*/
|
|
|
refreshChange() {
|
|
|
this.onLoad(this.page, this.query)
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查看线索详细信息
|
|
|
+ * @param {LeadRecord} row - 行数据
|
|
|
+ * @returns {Promise<void>}
|
|
|
+ */
|
|
|
+ async handleViewDetail(row) {
|
|
|
+ this.currentLead = row
|
|
|
+ this.detailDialogVisible = true
|
|
|
+ this.detailPage.currentPage = 1
|
|
|
+ await this.detailOnLoad(this.detailPage)
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查看详情
|
|
|
+ * @param {LeadRecord} row - 行数据
|
|
|
+ * @returns {void}
|
|
|
+ */
|
|
|
+ handleView(row) {
|
|
|
+ this.form = { ...row }
|
|
|
+ this.$refs.crud.rowView(row)
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 编辑
|
|
|
+ * @param {LeadRecord} row - 行数据
|
|
|
+ * @returns {void}
|
|
|
+ */
|
|
|
+ handleEdit(row) {
|
|
|
+ this.form = { ...row }
|
|
|
+ this.$refs.crud.rowEdit(row)
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除单行
|
|
|
+ * @param {LeadRecord} row - 行数据
|
|
|
+ * @returns {Promise<void>}
|
|
|
+ */
|
|
|
+ async handleRowDelete(row) {
|
|
|
+ try {
|
|
|
+ await this.$confirm(`确定删除线索 "${row.title}" 吗?`, '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ })
|
|
|
+
|
|
|
+ const res = await remove(row.id)
|
|
|
+ if (res.data && res.data.success) {
|
|
|
+ this.$message.success('删除成功')
|
|
|
+ this.onLoad(this.page)
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.data ? res.data.msg : '删除失败')
|
|
|
+
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ if (error !== 'cancel') {
|
|
|
+ console.error('删除失败:', error)
|
|
|
+ this.$message.error('删除失败,请稍后重试')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // ========== 详细信息相关方法 ==========
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详细信息数据加载
|
|
|
+ * @param {Object} page - 分页参数
|
|
|
+ * @param {Object} params - 查询参数
|
|
|
+ * @returns {Promise<void>}
|
|
|
+ */
|
|
|
+ async detailOnLoad(page, params = {}) {
|
|
|
+ if (!this.currentLead) return
|
|
|
+
|
|
|
+ this.detailLoading = true
|
|
|
+ try {
|
|
|
+ const queryParams = {
|
|
|
+ ...params,
|
|
|
+ leadId: this.currentLead.id
|
|
|
+ }
|
|
|
+
|
|
|
+ const res = await getDetailList(page.currentPage, page.pageSize, queryParams)
|
|
|
+ if (res.data && res.data.success) {
|
|
|
+ const data = res.data.data
|
|
|
+ this.detailData = data.records || []
|
|
|
+ this.detailPage.total = data.total || 0
|
|
|
+ } else {
|
|
|
+ this.detailData = []
|
|
|
+ this.detailPage.total = 0
|
|
|
+ this.$message.error(res.data ? res.data.msg : '获取详细信息失败')
|
|
|
+
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ this.detailData = []
|
|
|
+ this.detailPage.total = 0
|
|
|
+ console.error('获取详细信息失败:', error)
|
|
|
+ this.$message.error('获取详细信息失败,请稍后重试')
|
|
|
+ } finally {
|
|
|
+ this.detailLoading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详细信息新增前的回调
|
|
|
+ * @param {Function} done - 完成回调
|
|
|
+ * @param {string} type - 操作类型
|
|
|
+ * @returns {Promise<void>}
|
|
|
+ */
|
|
|
+ async detailBeforeOpen(done, type) {
|
|
|
+ if (['edit', 'view'].includes(type)) {
|
|
|
+ try {
|
|
|
+ const res = await getDetailDetail(this.detailForm.id)
|
|
|
+ if (res.data && res.data.success) {
|
|
|
+ this.detailForm = res.data.data
|
|
|
+ } else {
|
|
|
+ this.$message.error('获取详情失败')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('获取详情失败:', error)
|
|
|
+ this.$message.error('获取详情失败')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ } else if (type === 'add') {
|
|
|
+ // 新增时设置线索ID
|
|
|
+ this.detailForm.leadId = this.currentLead.id
|
|
|
+ }
|
|
|
+ done()
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详细信息新增
|
|
|
+ * @param {LeadDetailRecord} row - 表单数据
|
|
|
+ * @param {Function} done - 完成回调
|
|
|
+ * @param {Function} loading - 加载状态回调
|
|
|
+ * @returns {Promise<void>}
|
|
|
+ */
|
|
|
+ async detailRowSave(row, done, loading) {
|
|
|
+ try {
|
|
|
+ loading()
|
|
|
+ const params = {
|
|
|
+ leadId: this.currentLead.id,
|
|
|
+ detailText: row.detailText
|
|
|
+ }
|
|
|
+ const res = await addDetail(params)
|
|
|
+ if (res.data && res.data.success) {
|
|
|
+ this.$message.success('添加成功')
|
|
|
+ this.detailOnLoad(this.detailPage)
|
|
|
+ done()
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.data ? res.data.msg : '添加失败')
|
|
|
+ loading()
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('添加失败:', error)
|
|
|
+ this.$message.error('添加失败,请稍后重试')
|
|
|
+ loading()
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详细信息修改
|
|
|
+ * @param {LeadDetailRecord} row - 表单数据
|
|
|
+ * @param {number} index - 行索引
|
|
|
+ * @param {Function} done - 完成回调
|
|
|
+ * @param {Function} loading - 加载状态回调
|
|
|
+ * @returns {Promise<void>}
|
|
|
+ */
|
|
|
+ async detailRowUpdate(row, index, done, loading) {
|
|
|
+ try {
|
|
|
+ loading()
|
|
|
+ const params = {
|
|
|
+ id: row.id,
|
|
|
+ leadId: this.currentLead.id,
|
|
|
+ detailText: row.detailText
|
|
|
+ }
|
|
|
+ const res = await updateDetail(params)
|
|
|
+ if (res.data && res.data.success) {
|
|
|
+ this.$message.success('修改成功')
|
|
|
+ this.detailOnLoad(this.detailPage)
|
|
|
+ done()
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.data ? res.data.msg : '修改失败')
|
|
|
+ loading()
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('修改失败:', error)
|
|
|
+ this.$message.error('修改失败,请稍后重试')
|
|
|
+ loading()
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详细信息删除
|
|
|
+ * @param {LeadDetailRecord} row - 行数据
|
|
|
+ * @param {number} index - 行索引
|
|
|
+ * @returns {Promise<void>}
|
|
|
+ */
|
|
|
+ async detailRowDel(row, index) {
|
|
|
+ try {
|
|
|
+ const res = await removeDetail(row.id)
|
|
|
+ if (res.data && res.data.success) {
|
|
|
+ this.$message.success('删除成功')
|
|
|
+ this.detailOnLoad(this.detailPage)
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.data ? res.data.msg : '删除失败')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('删除失败:', error)
|
|
|
+ this.$message.error('删除失败,请稍后重试')
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详细信息选择变更
|
|
|
+ * @param {LeadDetailRecord[]} list - 选中的数据列表
|
|
|
+ * @returns {void}
|
|
|
+ */
|
|
|
+ detailSelectionChange(list) {
|
|
|
+ this.detailSelectionList = list
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详细信息当前页变更
|
|
|
+ * @param {number} currentPage - 当前页码
|
|
|
+ * @returns {void}
|
|
|
+ */
|
|
|
+ detailCurrentChange(currentPage) {
|
|
|
+ this.detailPage.currentPage = currentPage
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详细信息页大小变更
|
|
|
+ * @param {number} pageSize - 页大小
|
|
|
+ * @returns {void}
|
|
|
+ */
|
|
|
+ detailSizeChange(pageSize) {
|
|
|
+ this.detailPage.pageSize = pageSize
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 详细信息刷新变更
|
|
|
+ * @param {Object} page - 分页参数
|
|
|
+ * @returns {void}
|
|
|
+ */
|
|
|
+ detailRefreshChange(page) {
|
|
|
+ this.detailOnLoad(page)
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量删除详细信息
|
|
|
+ * @returns {Promise<void>}
|
|
|
+ */
|
|
|
+ async handleDetailDelete() {
|
|
|
+ if (this.detailSelectionList.length === 0) {
|
|
|
+ this.$message.warning('请选择要删除的数据')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ await this.$confirm('确定删除选中的详细信息吗?', '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ })
|
|
|
+
|
|
|
+ const res = await removeDetail(this.detailIds)
|
|
|
+ if (res.data && res.data.success) {
|
|
|
+ this.$message.success('删除成功')
|
|
|
+ this.detailOnLoad(this.detailPage)
|
|
|
+ this.$refs.detailCrud.toggleSelection()
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.data ? res.data.msg : '删除失败')
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ if (error !== 'cancel') {
|
|
|
+ console.error('删除失败:', error)
|
|
|
+ this.$message.error('删除失败,请稍后重试')
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
},
|
|
|
mounted() {
|
|
@@ -801,6 +1265,10 @@ export default {
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
|
|
|
+.lead-info-desc {
|
|
|
+ margin-bottom: 20px;
|
|
|
+}
|
|
|
+
|
|
|
// 表格中的优先级和状态样式
|
|
|
::v-deep .el-table {
|
|
|
.el-tag {
|