| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611 |
- <template>
- <basic-container>
- <avue-crud :option="option" :data="data" ref="crud" v-model="form" :page.sync="page"
- :permission="permissionList" :before-open="beforeOpen" :table-loading="loading" @row-del="rowDel"
- @row-update="rowUpdate" @row-save="rowSave" @search-change="searchChange" @search-reset="searchReset"
- @selection-change="selectionChange" @current-change="currentChange" @size-change="sizeChange"
- @refresh-change="refreshChange" @on-load="onLoad">
- <template slot="menuLeft">
- <el-button type="danger" size="small" plain icon="el-icon-delete" v-if="permission.order_lead_delete"
- @click="handleDelete">
- 删除
- </el-button>
- </template>
- <template slot-scope="{row}" slot="status">
- <el-tag :type="getStatusType(row.status)">
- {{ getStatusText(row.status) }}
- </el-tag>
- </template>
- <template slot-scope="{row}" slot="priority">
- <el-tag :type="getPriorityType(row.priority)">
- {{ getPriorityText(row.priority) }}
- </el-tag>
- </template>
- <template slot-scope="{row}" slot="endTime">
- <span :class="{ 'text-danger': isOverdue(row.endTime, row.status) }">
- {{ row.endTime }}
- </span>
- </template>
- </avue-crud>
- </basic-container>
- </template>
- <script>
- import { getList, add, update, remove, getDetail } from '@/api/order/lead'
- import { getCustomerList } from '@/api/common/index'
- import { mapGetters } from 'vuex'
- /**
- * 销售线索记录类型定义
- * @typedef {Object} LeadRecord
- * @property {string} id - 线索ID
- * @property {string} createUser - 创建用户ID
- * @property {string} createDept - 创建部门ID
- * @property {string} createTime - 创建时间
- * @property {string} updateUser - 更新用户ID
- * @property {string} updateTime - 更新时间
- * @property {number} status - 状态 1-新建 2-跟进中 3-已关闭
- * @property {number} isDeleted - 是否删除
- * @property {string} leadCode - 线索编码
- * @property {number} customerId - 客户ID
- * @property {string} customerCode - 客户编码
- * @property {string} customerName - 客户名称
- * @property {string} contactName - 联系人姓名
- * @property {string} contactPhone - 联系人电话
- * @property {string} title - 线索标题
- * @property {string} endTime - 截止时间
- * @property {number} priority - 优先级
- * @property {string} source - 线索来源
- * @property {string} groupName - 分组名称
- * @property {string|null} closeReason - 关闭原因
- */
- /**
- * 销售线索查询参数类型定义
- * @typedef {Object} LeadQueryParams
- * @property {string} [leadCode] - 线索编码
- * @property {string} [customerCode] - 客户编码
- * @property {string} [customerName] - 客户名称
- * @property {string} [contactName] - 联系人姓名
- * @property {string} [contactPhone] - 联系人电话
- * @property {string} [title] - 线索标题
- * @property {number} [status] - 状态
- * @property {number} [priority] - 优先级
- * @property {string} [source] - 线索来源
- * @property {string} [groupName] - 分组名称
- * @property {string[]} [endTime] - 截止时间范围
- */
- export default {
- name: 'Lead',
- data() {
- return {
- /**
- * 表格数据
- * @type {LeadRecord[]}
- */
- data: [],
- /**
- * 查询参数
- * @type {LeadQueryParams}
- */
- query: {},
- /**
- * 加载状态
- * @type {boolean}
- */
- loading: true,
- /**
- * 表单数据
- * @type {LeadRecord}
- */
- form: {},
- /**
- * 选中的数据列表
- * @type {LeadRecord[]}
- */
- selectionList: [],
- /**
- * 分页信息
- * @type {{total: number, currentPage: number, pageSize: number}}
- */
- page: {
- total: 0,
- currentPage: 1,
- pageSize: 10
- },
- /**
- * 客户选项列表
- * @type {{label: string, value: string}[]}
- */
- customerOptions: [],
- /**
- * 表格配置
- */
- option: {
- height: 'auto',
- calcHeight: 30,
- tip: false,
- searchShow: true,
- searchMenuSpan: 6,
- border: true,
- index: true,
- viewBtn: true,
- selection: true,
- dialogClickModal: false,
- column: [
- {
- label: '线索编码',
- prop: 'leadCode',
- rules: [{
- required: true,
- message: '请输入线索编码',
- trigger: 'blur'
- }],
- search: true
- },
- {
- label: '客户编码',
- prop: 'customerCode',
- rules: [{
- required: true,
- message: '请输入客户编码',
- trigger: 'blur'
- }],
- search: true
- },
- {
- label: '客户名称',
- prop: 'customerName',
- rules: [{
- required: true,
- message: '请输入客户名称',
- trigger: 'blur'
- }],
- search: true
- },
- {
- label: '联系人',
- prop: 'contactName',
- rules: [{
- required: true,
- message: '请输入联系人姓名',
- trigger: 'blur'
- }],
- search: true
- },
- {
- label: '联系电话',
- prop: 'contactPhone',
- rules: [{
- required: true,
- message: '请输入联系电话',
- trigger: 'blur'
- }, {
- pattern: /^1[3-9]\d{9}$/,
- message: '请输入正确的手机号码',
- trigger: 'blur'
- }],
- search: true
- },
- {
- label: '线索标题',
- prop: 'title',
- rules: [{
- required: true,
- message: '请输入线索标题',
- trigger: 'blur'
- }],
- search: true,
- overHidden: true
- },
- {
- label: '截止时间',
- prop: 'endTime',
- type: 'datetime',
- format: 'yyyy-MM-dd HH:mm:ss',
- valueFormat: 'yyyy-MM-dd HH:mm:ss',
- rules: [{
- required: true,
- message: '请选择截止时间',
- trigger: 'blur'
- }],
- search: true,
- searchRange: true,
- slot: true
- },
- {
- label: '优先级',
- prop: 'priority',
- type: 'select',
- dicData: [
- { label: '高', value: 1 },
- { label: '中', value: 2 },
- { label: '低', value: 3 }
- ],
- rules: [{
- required: true,
- message: '请选择优先级',
- trigger: 'blur'
- }],
- search: true,
- slot: true
- },
- {
- label: '线索来源',
- prop: 'source',
- rules: [{
- required: true,
- message: '请输入线索来源',
- trigger: 'blur'
- }],
- search: true
- },
- {
- label: '分组名称',
- prop: 'groupName',
- rules: [{
- required: true,
- message: '请输入分组名称',
- trigger: 'blur'
- }],
- search: true
- },
- {
- label: '状态',
- prop: 'status',
- type: 'select',
- dicData: [
- { label: '新建', value: 1 },
- { label: '跟进中', value: 2 },
- { label: '已关闭', value: 3 }
- ],
- rules: [{
- required: true,
- message: '请选择状态',
- trigger: 'blur'
- }],
- search: true,
- slot: true
- },
- {
- label: '关闭原因',
- prop: 'closeReason',
- type: 'textarea',
- span: 24,
- hide: true,
- viewDisplay: true
- },
- {
- 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
- },
- {
- 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
- }
- ]
- },
- /**
- * 权限列表
- */
- permissionList: {
- // addBtn: this.vaildData(this.permission.order_lead_add, false),
- // viewBtn: this.vaildData(this.permission.order_lead_view, false),
- // delBtn: this.vaildData(this.permission.order_lead_delete, false),
- // editBtn: this.vaildData(this.permission.order_lead_edit, false)
- addBtn: true,
- viewBtn: true,
- delBtn: false,
- editBtn: true,
- }
- }
- },
- computed: {
- ...mapGetters(['permission']),
- ids() {
- const ids = []
- this.selectionList.forEach(ele => {
- ids.push(ele.id)
- })
- return ids.join(',')
- }
- },
- methods: {
- /**
- * 获取状态文本
- * @param {number} status - 状态值
- * @returns {string} 状态文本
- */
- getStatusText(status) {
- const statusMap = {
- 1: '新建',
- 2: '跟进中',
- 3: '已关闭'
- }
- return statusMap[status] || '未知状态'
- },
- /**
- * 获取状态标签类型
- * @param {number} status - 状态值
- * @returns {string} 标签类型
- */
- getStatusType(status) {
- const typeMap = {
- 1: 'info',
- 2: 'warning',
- 3: 'success'
- }
- return typeMap[status] || 'info'
- },
- /**
- * 获取优先级文本
- * @param {number} priority - 优先级值
- * @returns {string} 优先级文本
- */
- getPriorityText(priority) {
- const priorityMap = {
- 1: '高',
- 2: '中',
- 3: '低'
- }
- return priorityMap[priority] || '未知优先级'
- },
- /**
- * 获取优先级标签类型
- * @param {number} priority - 优先级值
- * @returns {string} 标签类型
- */
- getPriorityType(priority) {
- const typeMap = {
- 1: 'danger',
- 2: 'warning',
- 3: 'success'
- }
- return typeMap[priority] || 'info'
- },
- /**
- * 判断是否逾期
- * @param {string} endTime - 截止时间
- * @param {number} status - 状态
- * @returns {boolean} 是否逾期
- */
- isOverdue(endTime, status) {
- if (status === 3) return false // 已关闭的不显示逾期
- const now = new Date()
- const end = new Date(endTime)
- return end < now
- },
- /**
- * 删除操作
- * @returns {Promise<void>}
- */
- async rowDel(row) {
- try {
- await this.$confirm('确定将选择数据删除?', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- })
- await remove(row.id)
- await this.onLoad(this.page)
- this.$message({
- type: 'success',
- message: '操作成功!'
- })
- } catch (error) {
- console.error('删除失败:', error)
- }
- },
- /**
- * 批量删除
- * @returns {Promise<void>}
- */
- async handleDelete() {
- if (this.selectionList.length === 0) {
- this.$message.warning('请选择至少一条数据')
- return
- }
- try {
- await this.$confirm('确定将选择数据删除?', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- })
- await remove(this.ids)
- await this.onLoad(this.page)
- this.$message({
- type: 'success',
- message: '操作成功!'
- })
- this.$refs.crud.toggleSelection()
- } catch (error) {
- console.error('批量删除失败:', error)
- }
- },
- /**
- * 更新操作
- * @param {LeadRecord} row - 行数据
- * @param {number} index - 行索引
- * @param {Function} done - 完成回调
- * @param {Function} loading - 加载回调
- * @returns {Promise<void>}
- */
- async rowUpdate(row, index, done, loading) {
- try {
- await update(row)
- await this.onLoad(this.page)
- this.$message({
- type: 'success',
- message: '操作成功!'
- })
- done()
- } catch (error) {
- console.error('更新失败:', error)
- loading()
- }
- },
- /**
- * 新增操作
- * @param {LeadRecord} row - 行数据
- * @param {Function} done - 完成回调
- * @param {Function} loading - 加载回调
- * @returns {Promise<void>}
- */
- async rowSave(row, done, loading) {
- try {
- await add(row)
- await this.onLoad(this.page)
- this.$message({
- type: 'success',
- message: '操作成功!'
- })
- done()
- } catch (error) {
- console.error('新增失败:', error)
- loading()
- }
- },
- /**
- * 新增前的回调
- * @param {Function} done - 完成回调
- * @param {string} type - 操作类型
- */
- beforeOpen(done, type) {
- if (['edit', 'view'].includes(type)) {
- // 编辑和查看时获取详情
- getDetail(this.form.id).then(res => {
- this.form = res.data.data
- })
- }
- done()
- },
- /**
- * 获取数据
- * @param {Object} page - 分页信息
- * @param {LeadQueryParams} [params] - 查询参数
- * @returns {Promise<void>}
- */
- async onLoad(page, params = {}) {
- this.loading = true
- try {
- // 处理时间范围查询
- const queryParams = { ...params }
- if (queryParams.endTime && Array.isArray(queryParams.endTime)) {
- queryParams.endTimeStart = queryParams.endTime[0]
- queryParams.endTimeEnd = queryParams.endTime[1]
- delete queryParams.endTime
- }
- const res = await getList(page.currentPage, page.pageSize, queryParams)
- const data = res.data.data
- this.data = data.records || []
- this.page.total = data.total || 0
- } catch (error) {
- console.error('获取数据失败:', error)
- this.$message.error('获取数据失败')
- } finally {
- this.loading = false
- }
- },
- /**
- * 搜索变更
- * @param {LeadQueryParams} params - 查询参数
- * @param {Function} done - 完成回调
- */
- searchChange(params, done) {
- this.query = params
- this.onLoad(this.page, params)
- done()
- },
- /**
- * 搜索重置
- * @param {Function} done - 完成回调
- */
- searchReset(done) {
- this.query = {}
- this.onLoad(this.page)
- done()
- },
- /**
- * 选择变更
- * @param {LeadRecord[]} list - 选中的数据
- */
- selectionChange(list) {
- this.selectionList = list
- },
- /**
- * 清空选择
- */
- selectionClear() {
- this.selectionList = []
- },
- /**
- * 当前页变更
- * @param {number} currentPage - 当前页
- */
- currentChange(currentPage) {
- this.page.currentPage = currentPage
- },
- /**
- * 页大小变更
- * @param {number} pageSize - 页大小
- */
- sizeChange(pageSize) {
- this.page.pageSize = pageSize
- },
- /**
- * 刷新变更
- */
- refreshChange() {
- this.onLoad(this.page, this.query)
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .text-danger {
- color: #f56c6c;
- font-weight: bold;
- }
- // 表格中的优先级和状态样式
- ::v-deep .el-table {
- .el-tag {
- margin: 0;
- }
- }
- </style>
|