添加系统码

This commit is contained in:
浅念
2025-07-21 18:12:16 +08:00
parent 31cd18fade
commit c7d890809c
7 changed files with 150 additions and 103 deletions
+4 -4
View File
@@ -65,16 +65,16 @@ export class CrmService {
})
}
//标签列表/crm/tagGroup/list
static tagGrouplist() {
static tagGrouplist(params: any) {
return request.get<any>({
url: '/crm/tagGroup/list'
url: '/crm/tagGroup/list',
params
})
}
//更新客户标签 /crm/tagGroup/updatePivot
static tagGroupupdatePivot(params: any) {
return request.get<Api.Work.AddResponse>({
url: '/crm/tagGroup/updatePivot',
params
url: '/crm/tagGroup/updatePivot'
})
}
//跟进列表crm/follow/list
+6
View File
@@ -6,6 +6,12 @@ export class UserService {
return request.get<Api.Brand.BrandInfo>({
url: '/common/preset/corps'
})
}
//获取系统
static getsystemsList() {
return request.get<Api.Brand.BrandInfo>({
url: '/common/preset/systems'
})
}
//注册
static register(params: any) {
+10
View File
@@ -25,6 +25,8 @@ export const useUserStore = defineStore(
const refreshToken = ref('')
const companyid = ref('')
const companyabbr = ref('')
const systemsid = ref('')
const systemsabbr = ref('')
const loginType = ref<'feishu' | 'upwd'>('upwd')
const tokenExpireAt = ref<number>(0)
@@ -76,6 +78,11 @@ export const useUserStore = defineStore(
companyid.value = id
companyabbr.value = abbr
}
const setSystems= (id: string, abbr: string) => {
systemsid.value = id
systemsabbr.value = abbr
}
function restoreTokenTimer() {
const expireAt = Number(localStorage.getItem('token_expire_at') || '0')
if (accessToken.value && expireAt > Date.now()) {
@@ -139,6 +146,8 @@ export const useUserStore = defineStore(
info,
companyid,
companyabbr,
systemsid,
systemsabbr,
searchHistory,
loginType,
accessToken,
@@ -155,6 +164,7 @@ export const useUserStore = defineStore(
setLockPassword,
setToken,
setCompany,
setSystems,
setLoginType,
logOut,
restoreTokenTimer
+2 -1
View File
@@ -47,9 +47,10 @@ axiosInstance.interceptors.request.use(
const { language } = useUserStore()
const { loginType } = useUserStore()
const { companyabbr } = useUserStore()
const { systemsabbr } = useUserStore()
request.headers.set('Fdesk-Language', language)
request.headers.set('Fdesk-Corp-Abbr', companyabbr)
request.headers.set('Fdesk-System-Code', 'fdesk')
request.headers.set('Fdesk-System-Code', systemsabbr)
request.headers.set('Fdesk-Login-Type', loginType)
// 设置 token 和 请求头
if (accessToken) {
+46 -2
View File
@@ -72,6 +72,18 @@
</ElOption>
</ElSelect>
</ElFormItem>
<ElFormItem prop="company" label="系统">
<ElSelect v-model="formData.systems" class="account-select" @change="changesystems">
<ElOption
v-for="account in systemsList"
:key="account.id"
:label="account.name"
:value="account.id"
>
<span>{{ account.name }}</span>
</ElOption>
</ElSelect>
</ElFormItem>
<div class="drag-verify">
<div class="drag-verify-content" :class="{ error: !isPassing && isClickPass }">
<ArtDragVerify
@@ -127,6 +139,18 @@
</ElOption>
</ElSelect>
</ElFormItem>
<ElFormItem prop="company" label="系统">
<ElSelect v-model="formData.systems" class="account-select" @change="changesystems">
<ElOption
v-for="account in systemsList"
:key="account.id"
:label="account.name"
:value="account.id"
>
<span>{{ account.name }}</span>
</ElOption>
</ElSelect>
</ElFormItem>
</ElForm>
<div class="qrcode-login" v-if="!isInFeishu">
<div id="login_container"></div>
@@ -175,13 +199,18 @@
const formRef = ref<FormInstance>()
const companyid = ref('')
companyid.value = useUserStore().companyid
const systemsid = ref('')
systemsid.value = useUserStore().systemsid
const iscompany = ref(false)
const { companyabbr } = useUserStore()
//获取公司 getCompanyList
const companyList = ref<any>()
//系统
const systemsList = ref<any>()
const feishuresponse=ref()
const formData = reactive({
account: '',
systems: useUserStore().companyid?Number(useUserStore().companyid):'',
company: useUserStore().companyid?Number(useUserStore().companyid):'',
username: '',
password: '',
@@ -198,11 +227,19 @@
const { width } = useWindowSize()
const getcompanyList = async () => {
try {
// 这里调用获取品牌列表的接口
// 这里调用公司列表的接口
const response = await UserService.getCompanyList()
companyList.value = response || []
} catch (error) { }
}
const getsystemsList = async () => {
try {
// 这里调用公司列表的接口
const response = await UserService.getsystemsList()
systemsList.value = response || []
} catch (error) { }
}
// 切换语言
const { locale } = useI18n()
@@ -214,7 +251,7 @@
const getfeishuAppList = async () => {
try {
// 这里调用获取品牌列表的接口
// 这里调用飞书
feishuresponse.value = await UserService.getfeishuAppList({ corp_id: companyid.value })
if(activeLoginType.value=='qrcode'){
feishulogin()
@@ -222,6 +259,12 @@
console.log(feishuresponse)
} catch (error) { }
}
//切换系统
const changesystems = (systems: any) => {
const systemsdata = systemsList.value.find((c: any) => c.id === systems)
systemsid.value = systems
userStore.setSystems(systems,systemsdata?.code)
}
//切换公司
const changeCompany = (company: any) => {
@@ -383,6 +426,7 @@
onMounted(() => {
getcompanyList()
getsystemsList()
// 自动读取 query 参数并存入 userStore
const companyid = Array.isArray(route.query.corp_id) ? route.query.corp_id[0] : route.query.corp_id
const companyabbr = Array.isArray(route.query.corp_abbr) ? route.query.corp_abbr[0] : route.query.corp_abbr
+1 -1
View File
@@ -185,7 +185,7 @@ function addtag(){
}
const tagGrouplistfn = async () => {
try {
const res = await CrmService.tagGrouplist()
const res = await CrmService.tagGrouplist({})
tagGroups.value = res || []
// 回显选中
if (customerInfo.value && Array.isArray(customerInfo.value.tags)) {
+56 -70
View File
@@ -19,43 +19,40 @@
<!-- 筛选标签 -->
<div class="customer-tags boxshadow">
<div class="filter-row">
<span class="filter-label">价值标签</span>
<!-- 前3组 -->
<div class="filter-row" v-for="item in visibleTagGroups" :key="item.id">
<span class="filter-label">{{item.name}}</span>
<div class="filter-tags">
<span v-for="item in valueTags" :key="item.label" :class="['tag-item', { 'tag-active': tagActiveMap['value'] === item.label }]" @click="handleTagClick('value', item.label)">
{{ item.label }}({{ item.count }})
<span
v-for="item1 in item.tags"
:key="item1.id"
:class="['tag-item', { 'tag-active': tagActiveMap[item.id] === item1.id }]"
@click="handleTagClick(item.id, item1.id)"
>
{{ item1.name }}({{ item1.count }})
</span>
</div>
</div>
<div class="filter-row">
<span class="filter-label">生命周期标签</span>
<div class="filter-tags">
<span v-for="item in lifeTags" :key="item.label" :class="['tag-item', { 'tag-active': tagActiveMap['life'] === item.label }]" @click="handleTagClick('life', item.label)">
{{ item.label }}({{ item.count }})
</span>
</div>
</div>
<div class="filter-row">
<span class="filter-label">行为标签</span>
<div class="filter-tags">
<span v-for="item in actionTags" :key="item.label" :class="['tag-item', { 'tag-active': tagActiveMap['action'] === item.label }]" @click="handleTagClick('action', item.label)">
{{ item.label }}({{ item.count }})
</span>
</div>
</div>
<!-- 更多 -->
<transition name="fade">
<div v-if="showMore" class="filter-row">
<span class="filter-label">更多标签</span>
<div v-if="showMore">
<div class="filter-row" v-for="item in moreTagGroups" :key="item.id">
<span class="filter-label">{{item.name}}</span>
<div class="filter-tags">
<span v-for="item in moreTags" :key="item.label" :class="['tag-item', { 'tag-active': tagActiveMap['more'] === item.label }]" @click="handleTagClick('more', item.label)">
{{ item.label }}({{ item.count }})
<span
v-for="item1 in item.tags"
:key="item1.id"
:class="['tag-item', { 'tag-active': tagActiveMap[item.id] === item1.id }]"
@click="handleTagClick(item.id, item1.id)"
>
{{ item1.name }}({{ item1.count }})
</span>
</div>
</div>
</div>
</transition>
<div class="filter-more-btn">
<el-link :underline="false" @click="showMore = !showMore">
<div class="filter-more-btn" v-if="moreTagGroups.length">
<el-link underline="never" @click="showMore = !showMore">
{{ showMore ? '收起' : '更多' }}
<i v-if="showMore" class="iconfont-sys"> &#xe864;</i>
<i v-else class="iconfont-sys">&#xe867;</i>
@@ -90,8 +87,8 @@
</el-table-column>
<el-table-column fixed="right" label="操作" width="200px" align="center">
<template #default="scope">
<el-link type="primary" :underline="false" style="margin-right: 8px;" @click="goEdit(scope.row)"> <i class="iconfont-sys"> &#xe70f;</i>查看</el-link>
<el-link type="primary" :underline="false" @click="goAddFollow(scope.row)"> <i class="iconfont-sys"> &#xe6bf;</i> 添加跟进</el-link>
<el-link type="primary" underline="never" style="margin-right: 8px;" @click="goEdit(scope.row)"> <i class="iconfont-sys"> &#xe70f;</i>查看</el-link>
<el-link type="primary" underline="never" @click="goAddFollow(scope.row)"> <i class="iconfont-sys"> &#xe6bf;</i> 添加跟进</el-link>
</template>
</el-table-column>
</template>
@@ -102,7 +99,7 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import { CrmService } from '@/api/crmApi'
const searchValue = ref('')
@@ -121,40 +118,24 @@ const selectOptions = [
{ label: '近三天', value: '1' },
{ label: '近七天', value: '2' }
]
const valueTags = [
{ label: '高价值', count: 10 },
{ label: '中价值', count: 10 },
{ label: '低价值', count: 10 },
{ label: '潜在高价值', count: 10 }
]
const lifeTags = [
{ label: '新客户', count: 10 },
{ label: '活跃', count: 10 },
{ label: '深度', count: 10 },
{ label: '流失', count: 10 }
]
const actionTags = [
{ label: '高频购买', count: 10 },
{ label: '大单', count: 10 },
{ label: '促销敏感', count: 10 }
]
const moreTags = [
{ label: '标签A', count: 5 },
{ label: '标签B', count: 3 }
]
//获取标签
const tagGroups = ref<any[]>([])
type TagGroup = { id: string; name: string; tags: { id: string; name: string; count: number }[] }
const tagGroups = ref<TagGroup[]>([])
const tagGrouplistfn = async () => {
try {
const res = await CrmService.tagGrouplist()
const res = await CrmService.tagGrouplist({scene:'customers'})
tagGroups.value = res || []
} catch (error) { }
}
// 计算前3组和更多组
defineProps()
const visibleTagGroups = computed(() => tagGroups.value.slice(0, 3))
const moreTagGroups = computed(() => tagGroups.value.slice(3))
// 表格数据
const tableData = ref<any[]>([])
onMounted(() => {
gettableList()
tagGrouplistfn()
})
// tabs 切换联动
watch([activeTab, searchValue, selectValue], () => {
@@ -162,6 +143,7 @@ watch([activeTab, searchValue, selectValue], () => {
gettableList()
})
// 获取列表数据
const tagActiveMap = reactive<{ [groupId: string]: string }>({})
const gettableList = async () => {
loading.value = true
try {
@@ -173,11 +155,12 @@ const gettableList = async () => {
if (searchValue.value) params.keyword = searchValue.value
if (selectValue.value) params.follow_last = selectValue.value
if (activeTab.value && activeTab.value !== '') params.follow = activeTab.value
// 标签参数
if (tagActiveMap.value) params.value_tag = tagActiveMap.value
if (tagActiveMap.life) params.life_tag = tagActiveMap.life
if (tagActiveMap.action) params.action_tag = tagActiveMap.action
if (tagActiveMap.more) params.more_tag = tagActiveMap.more
// 标签参数,所有选中的标签id组成数组
const selectedTagIds = Object.values(tagActiveMap).filter(Boolean)
if (selectedTagIds.length) {
params.tag_id = selectedTagIds
}
console.log(params)
const { data, current, size, total } = await CrmService.getcustomerList(params)
tableData.value = data.map((item: any, index: number) => ({
...item
@@ -194,7 +177,6 @@ const handleSizeChange = (newPageSize: number) => {
pagination.pageSize = newPageSize
// getWorkList()
}
const handleCurrentChange = (newCurrentPage: number) => {
pagination.currentPage = newCurrentPage
// getWorkList()
@@ -205,7 +187,6 @@ function statusClass(status: any) {
if (status === 2) return 'status-lost'
return ''
}
const router = useRouter()
function goAdd() {
router.push('/crmpc/customer/add')
@@ -222,15 +203,12 @@ const router = useRouter()
query: { id: row.id } // 可带客户名等参数
})
}
// 标签选中状态,key为组名,值为选中的标签label
const tagActiveMap = reactive<{ [group: string]: string }>({})
function handleTagClick(group: string, label: string) {
if (tagActiveMap[group] === label) {
tagActiveMap[group] = '' // 取消选中
// 标签选中状态,key为组id,值为选中的标签id
function handleTagClick(groupId: string, tagId: string) {
if (tagActiveMap[groupId] === tagId) {
tagActiveMap[groupId] = '' // 取消选中
} else {
tagActiveMap[group] = label // 选中
tagActiveMap[groupId] = tagId // 选中
}
pagination.currentPage = 1
gettableList()
@@ -338,6 +316,14 @@ function handleTagClick(group: string, label: string) {
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
.tag-item { cursor: pointer; border-radius: 4px; padding: 2px 10px; margin-right: 8px; transition: background 0.2s; }
.tag-item {
cursor: pointer;
border-radius: 4px;
padding: 2px 10px;
margin-right: 8px;
transition: background 0.2s;
min-width: 100px;
display: inline-block;
}
.tag-active { background: #3471FF; color: #fff; }
</style>