diff --git a/src/api/bst/customer.js b/src/api/bst/customer.js
index f35ac09..c12e6f2 100644
--- a/src/api/bst/customer.js
+++ b/src/api/bst/customer.js
@@ -54,3 +54,4 @@ export function delCustomer(id) {
method: 'delete'
})
}
+
diff --git a/src/api/dashboard/customer.js b/src/api/dashboard/customer.js
index bf30a19..ab54b61 100644
--- a/src/api/dashboard/customer.js
+++ b/src/api/dashboard/customer.js
@@ -9,4 +9,12 @@ export function dailyCreateCountCustomer(params) {
})
}
+// 客户概览
+export function customerBrief(params) {
+ return request({
+ url: '/dashboard/customer/brief',
+ method: 'get',
+ params
+ })
+}
diff --git a/src/api/dashboard/task.js b/src/api/dashboard/task.js
new file mode 100644
index 0000000..5d30b9c
--- /dev/null
+++ b/src/api/dashboard/task.js
@@ -0,0 +1,9 @@
+import request from '@/utils/request';
+
+export function taskBrief(params) {
+ return request({
+ url: '/dashboard/task/brief',
+ method: 'get',
+ params
+ });
+}
diff --git a/src/assets/styles/ruoyi.scss b/src/assets/styles/ruoyi.scss
index c0ae6ed..3f27e19 100644
--- a/src/assets/styles/ruoyi.scss
+++ b/src/assets/styles/ruoyi.scss
@@ -92,7 +92,7 @@
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
th {
word-break: break-word;
- background-color: #f8f8f9;
+ background-color: #fff;
color: #515a6e;
height: 40px;
font-size: 13px;
diff --git a/src/components/CardTab/index.vue b/src/components/CardTab/index.vue
new file mode 100644
index 0000000..1101504
--- /dev/null
+++ b/src/components/CardTab/index.vue
@@ -0,0 +1,77 @@
+
+
+
+ {{title}}
+
+
+
+
{{item.label}}
+
{{item.value}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/layout/components/AppMain.vue b/src/layout/components/AppMain.vue
index c4b3895..4e3394e 100644
--- a/src/layout/components/AppMain.vue
+++ b/src/layout/components/AppMain.vue
@@ -33,6 +33,7 @@ export default {
width: 100%;
position: relative;
overflow: hidden;
+ background-color: #fafafa;
}
.fixed-header + .app-main {
diff --git a/src/utils/enums.js b/src/utils/enums.js
index 8ece80c..a38b6d1 100644
--- a/src/utils/enums.js
+++ b/src/utils/enums.js
@@ -52,7 +52,11 @@ export const CustomerStatus = {
POTENTIAL: "1", // 潜在
INTENTION: "2", // 意向
TRANSACTION: "3", // 成交
- INVALID: "4" // 失效
+ INVALID: "4", // 失效
+ // 跟进中的客户状态
+ following() {
+ return [this.POTENTIAL, this.INTENTION, this.TRANSACTION]
+ }
}
// 客户意向级别
diff --git a/src/views/bst/customer/components/CustomerCardTabs.vue b/src/views/bst/customer/components/CustomerCardTabs.vue
new file mode 100644
index 0000000..df7f1a3
--- /dev/null
+++ b/src/views/bst/customer/components/CustomerCardTabs.vue
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/bst/customer/edit/index.vue b/src/views/bst/customer/edit/index.vue
index fec4cf8..908a329 100644
--- a/src/views/bst/customer/edit/index.vue
+++ b/src/views/bst/customer/edit/index.vue
@@ -7,35 +7,31 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -121,12 +123,6 @@ export default {
status: [
{ required: true, message: "状态不能为空", trigger: "change" }
],
- intentLevel: [
- { required: true, message: "意向强度不能为空", trigger: "change" }
- ],
- source: [
- { required: true, message: "来源不能为空", trigger: "change" }
- ],
followId: [
{ required: true, message: "跟进人不能为空", trigger: "change" }
],
@@ -139,6 +135,15 @@ export default {
],
followTime: [
{ required: true, message: "跟进时间不能为空", trigger: "change" }
+ ],
+ customerStatus: [
+ { required: true, message: "客户状态不能为空", trigger: "change" }
+ ],
+ customerIntentLevel: [
+ { required: true, message: "意向强度不能为空", trigger: "change" }
+ ],
+ nextFollowTime: [
+ { required: true, message: "下次跟进时间不能为空", trigger: "change" }
]
}
},
@@ -187,8 +192,8 @@ export default {
id: null,
code: null,
name: null,
- status: CustomerStatus.POTENTIAL,
- intentLevel: CustomerIntentLevel.MEDIUM,
+ status: null,
+ intentLevel: null,
mobile: null,
wechat: null,
source: null,
@@ -197,6 +202,9 @@ export default {
remark: null,
follow: {
followTime: parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}'),
+ nextFollowTime: null,
+ customerStatus: CustomerStatus.POTENTIAL,
+ customerIntentLevel: CustomerIntentLevel.MEDIUM,
}
};
this.resetForm("form");
diff --git a/src/views/bst/customer/index.vue b/src/views/bst/customer/index.vue
index 1bae1a6..11545be 100644
--- a/src/views/bst/customer/index.vue
+++ b/src/views/bst/customer/index.vue
@@ -1,15 +1,15 @@
-
+
-
+
-
+
+
-
+
-
+
-
+
-
+
-
+
+
+
@@ -136,17 +138,13 @@
{{d.row[column.key]}}
-
-
-
-
-
-
{{d.row[column.key].join(',')}}
+
+
{{d.row[column.key]}}
@@ -200,7 +198,12 @@
@@ -211,6 +214,8 @@ import { $showColumns } from '@/utils/mixins';
import FormCol from "@/components/FormCol/index.vue";
import CustomerLink from '@/components/Business/Customer/CustomerLink.vue';
import CustomerFollowEditDialog from '@/views/bst/customerFollow/components/CustomerFollowEditDialog.vue';
+import CustomerCardTabs from './components/CustomerCardTabs.vue';
+
// 默认排序字段
const defaultSort = {
prop: "createTime",
@@ -221,7 +226,7 @@ export default {
name: "Customer",
mixins: [$showColumns],
dicts: ['customer_intent_level', 'customer_status'],
- components: {FormCol, CustomerLink, CustomerFollowEditDialog},
+ components: {FormCol, CustomerLink, CustomerFollowEditDialog, CustomerCardTabs},
props: {
query: {
type: Object,
@@ -231,6 +236,10 @@ export default {
initShowSearch: {
type: Boolean,
default: true
+ },
+ listApi: {
+ type: Function,
+ default: listCustomer
}
},
data() {
@@ -241,17 +250,15 @@ export default {
// 字段列表
columns: [
{key: 'id', visible: false, label: '编号', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
- {key: 'name', visible: true, label: '名称', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
- {key: 'status', visible: true, label: '状态', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
- {key: 'intentLevel', visible: true, label: '意向强度', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
+ {key: 'name', visible: true, label: '名称', minWidth: "200", sortable: true, overflow: false, align: 'left', width: null},
+ {key: 'remark', visible: true, label: '备注', minWidth: null, sortable: true, overflow: true, align: 'center', width: null},
+ {key: 'intents', visible: true, label: '意向', minWidth: null, sortable: true, overflow: true, align: 'center', width: null},
{key: 'mobile', visible: true, label: '手机号', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'wechat', visible: true, label: '微信号', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'source', visible: true, label: '来源', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
- {key: 'intents', visible: true, label: '意向', minWidth: null, sortable: true, overflow: true, align: 'center', width: null},
{key: 'followName', visible: true, label: '跟进人', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
- {key: 'lastFollowTime', visible: true, label: '最近跟进', minWidth: null, sortable: false, overflow: false, align: 'center', width: "100"},
- {key: 'nextFollowTime', visible: true, label: '下次跟进', minWidth: null, sortable: false, overflow: false, align: 'center', width: "100"},
- {key: 'remark', visible: true, label: '备注', minWidth: null, sortable: true, overflow: true, align: 'center', width: null},
+ {key: 'lastFollowTime', visible: true, label: '最近跟进', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
+ {key: 'nextFollowTime', visible: true, label: '下次跟进', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
{key: 'createName', visible: true, label: '创建人', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'createTime', visible: true, label: '创建时间', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
],
@@ -338,16 +345,24 @@ export default {
/** 查询客户列表 */
getList() {
this.loading = true;
- listCustomer(this.queryParams).then(response => {
+ this.listApi(this.queryParams).then(response => {
this.customerList = response.rows;
this.total = response.total;
this.loading = false;
});
},
+ // 切换卡片
+ handleChangeTab() {
+ this.queryParams.pageNum = 1;
+ this.getList();
+ },
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
+ if (this.$refs.customerCardTabs) {
+ this.$refs.customerCardTabs.getBrief();
+ }
},
/** 重置按钮操作 */
resetQuery() {
diff --git a/src/views/bst/customerFollow/components/CustomerFollowEditDialog.vue b/src/views/bst/customerFollow/components/CustomerFollowEditDialog.vue
index aeb5b7a..e943aa4 100644
--- a/src/views/bst/customerFollow/components/CustomerFollowEditDialog.vue
+++ b/src/views/bst/customerFollow/components/CustomerFollowEditDialog.vue
@@ -24,6 +24,7 @@ import { getCustomerFollow, addCustomerFollow, updateCustomerFollow } from "@/ap
import { mapGetters } from 'vuex';
import { parseTime } from '@/utils/ruoyi.js';
import CustomerFollowForm from '@/views/bst/customerFollow/components/CustomerFollowForm.vue';
+
export default {
name: "CustomerFollowEditDialog",
components: { CustomerFollowForm },
@@ -61,6 +62,15 @@ export default {
],
followTime: [
{ required: true, message: "跟进时间不能为空", trigger: "change" }
+ ],
+ customerStatus: [
+ { required: true, message: "客户状态不能为空", trigger: "change" }
+ ],
+ customerIntentLevel: [
+ { required: true, message: "意向强度不能为空", trigger: "change" }
+ ],
+ nextFollowTime: [
+ { required: true, message: "下次跟进时间不能为空", trigger: "change" }
]
},
disabledKeys: [],
@@ -101,6 +111,8 @@ export default {
userId: null,
nextFollowTime: null,
followTime: parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}'),
+ customerStatus: null,
+ customerIntentLevel: null,
// vo
customerName: null,
...this.initData
diff --git a/src/views/bst/customerFollow/components/CustomerFollowForm.vue b/src/views/bst/customerFollow/components/CustomerFollowForm.vue
index 45a8da8..674ffcb 100644
--- a/src/views/bst/customerFollow/components/CustomerFollowForm.vue
+++ b/src/views/bst/customerFollow/components/CustomerFollowForm.vue
@@ -4,7 +4,32 @@
-
+
+
+
+
+
+
+
+
+
+
+
@@ -30,7 +55,7 @@
placeholder="请选择跟进时间">
-
+
diff --git a/src/views/bst/index/index.vue b/src/views/bst/index/index.vue
index 0771d04..853f834 100644
--- a/src/views/bst/index/index.vue
+++ b/src/views/bst/index/index.vue
@@ -11,22 +11,37 @@
-
-
-
+
+
+
-
-
+
+
-
+
-
+
+
+
+
-
@@ -51,7 +66,8 @@ import Task from '@/views/bst/task/index.vue';
import Customer from '@/views/bst/customer/index.vue';
import { checkPermi } from '@/utils/permission';
import { parseTime } from '@/utils/ruoyi';
-import { TaskStatus } from '@/utils/enums';
+import { TaskStatus, CustomerStatus } from '@/utils/enums';
+import { mapGetters } from 'vuex';
export default {
name: 'Index',
@@ -59,7 +75,9 @@ export default {
data() {
return {
TaskStatus,
+ CustomerStatus,
today: parseTime(new Date(), '{y}-{m}-{d}'),
+ now: parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}'),
projectHideColumns: [
'id',
'no',
@@ -100,8 +118,13 @@ export default {
],
}
},
+ computed: {
+ ...mapGetters([
+ 'userId'
+ ])
+ },
methods: {
- checkPermi,
+ checkPermi
}
}
diff --git a/src/views/bst/task/components/TaskCardTabs.vue b/src/views/bst/task/components/TaskCardTabs.vue
new file mode 100644
index 0000000..831c60f
--- /dev/null
+++ b/src/views/bst/task/components/TaskCardTabs.vue
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/bst/task/index.vue b/src/views/bst/task/index.vue
index d740695..47af104 100644
--- a/src/views/bst/task/index.vue
+++ b/src/views/bst/task/index.vue
@@ -14,7 +14,7 @@
/>
-
+
-
+
+
+
@@ -222,6 +224,8 @@ import UserSelect from '@/components/Business/User/UserSelect.vue';
import {TaskStatus} from '@/utils/enums'
import BooleanTag from '@/components/BooleanTag'
import TaskStatistics from '@/views/bst/task/components/TaskStatistics.vue'
+import TaskCardTabs from '@/views/bst/task/components/TaskCardTabs.vue'
+
// 默认排序字段
const defaultSort = {
prop: "createTime",
@@ -232,7 +236,7 @@ export default {
name: "Task",
mixins: [$showColumns, $task],
dicts: ['task_status', 'task_level', 'task_type'],
- components: {FormCol, TaskEditDialog, ProjectSelect, TaskViewDialog, ProjectLink, AvatarList, UserSelect, BooleanTag, TaskStatistics},
+ components: {FormCol, TaskEditDialog, ProjectSelect, TaskViewDialog, ProjectLink, AvatarList, UserSelect, BooleanTag, TaskStatistics, TaskCardTabs},
props: {
initData: {
type: Object,
@@ -352,10 +356,18 @@ export default {
this.loading = false;
});
},
+ // 切换任务卡片
+ handleChangeTab() {
+ this.queryParams.pageNum = 1;
+ this.getList();
+ },
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
+ if (this.$refs.taskCardTabs) {
+ this.$refs.taskCardTabs.getBrief();
+ }
},
/** 重置按钮操作 */
resetQuery() {
diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue
index 08e659b..262bac8 100644
--- a/src/views/system/user/index.vue
+++ b/src/views/system/user/index.vue
@@ -293,6 +293,8 @@ export default {
{key: 'status', visible: true, label: '状态', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'phonenumber', visible: true, label: '手机号', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'email', visible: true, label: '邮箱', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
+ {key: 'projectCount', visible: true, label: '项目数', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
+ {key: 'taskCount', visible: true, label: '任务数', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
{key: 'loginIp', visible: true, label: '登录IP', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
{key: 'loginDate', visible: true, label: '登录时间', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
{key: 'createTime', visible: true, label: '创建时间', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},