feat: 管理端团队名称统一改成团队下拉框

This commit is contained in:
yys 2026-04-23 17:52:50 +08:00
parent 24f518acd1
commit 413a3b118a
9 changed files with 188 additions and 82 deletions

View File

@ -73,6 +73,9 @@ export function listSubteamUserBalance(query) {
return request({ url: '/subteam/user-balance/list', method: 'get', params: query }) return request({ url: '/subteam/user-balance/list', method: 'get', params: query })
} }
/** 导出POST /subteam/user-balance/export与列表相同查询参数 + beginTime/endTime */
export const subteamUserBalanceExportUrl = 'subteam/user-balance/export'
export function getSubteamUserBalance(id) { export function getSubteamUserBalance(id) {
return request({ url: '/subteam/user-balance/' + id, method: 'get' }) return request({ url: '/subteam/user-balance/' + id, method: 'get' })
} }

View File

@ -0,0 +1,31 @@
import { listDept as listAiDept } from "@/api/ai/dept"
/**
* 统计数据ai/data一致仅启用状态 ancestors 深度为 2 的团队供筛选下拉使用
* 系统团队页system/dept请覆写 secondLevelDeptListRequest改为调用 /system/dept/list
*/
export default {
data() {
return {
secondLevelDeptOptions: []
}
},
methods: {
/** @param {object} params 如 { status: '0' } */
secondLevelDeptListRequest(params) {
return listAiDept(params)
},
loadSecondLevelDeptOptions() {
this.secondLevelDeptListRequest({ status: "0" }).then(response => {
const allDeptList = response.data || []
this.secondLevelDeptOptions = allDeptList.filter(item => this.isSecondLevelDept(item))
})
},
isSecondLevelDept(dept) {
if (!dept || !dept.ancestors) {
return false
}
return String(dept.ancestors).split(",").filter(Boolean).length === 2
}
}
}

View File

@ -17,14 +17,20 @@
/> />
</el-form-item> </el-form-item>
<el-form-item label="团队" prop="deptId"> <el-form-item label="团队" prop="deptId">
<treeselect <el-select
v-model="queryParams.deptId" v-model="queryParams.deptId"
:options="deptOptions" placeholder="全部团队(可选)"
:normalizer="deptNormalizer"
placeholder="全部"
clearable clearable
filterable
style="width: 220px" style="width: 220px"
>
<el-option
v-for="item in secondLevelDeptOptions"
:key="item.deptId"
:label="item.deptName"
:value="item.deptId"
/> />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="操作类型" prop="type"> <el-form-item label="操作类型" prop="type">
<el-select <el-select
@ -151,13 +157,11 @@ import {
addRecord, addRecord,
updateRecord updateRecord
} from "@/api/ai/balanceChangeRecord"; } from "@/api/ai/balanceChangeRecord";
import { listDept } from "@/api/ai/dept"; import secondLevelDeptFilter from "@/mixins/secondLevelDeptFilter";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default { export default {
name: "Record", name: "Record",
components: { Treeselect }, mixins: [secondLevelDeptFilter],
data() { data() {
return { return {
// //
@ -197,7 +201,6 @@ export default {
title: "", title: "",
// //
open: false, open: false,
deptOptions: [],
// //
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
@ -218,25 +221,10 @@ export default {
}; };
}, },
created() { created() {
this.loadDeptTree(); this.loadSecondLevelDeptOptions();
this.getList(); this.getList();
}, },
methods: { methods: {
loadDeptTree() {
listDept().then(res => {
this.deptOptions = this.handleTree(res.data, "deptId");
});
},
deptNormalizer(node) {
if (node.children && !node.children.length) {
delete node.children;
}
return {
id: node.deptId,
label: node.deptName,
children: node.children
};
},
/** 西式千分位en-US积分为整数 */ /** 西式千分位en-US积分为整数 */
formatPointsWestern(value) { formatPointsWestern(value) {
if (value === null || value === undefined || value === "") { if (value === null || value === undefined || value === "") {

View File

@ -22,7 +22,7 @@
style="width: 220px" style="width: 220px"
> >
<el-option <el-option
v-for="item in deptOptions" v-for="item in secondLevelDeptOptions"
:key="item.deptId" :key="item.deptId"
:label="item.deptName" :label="item.deptName"
:value="item.deptId" :value="item.deptId"
@ -114,10 +114,11 @@
<script> <script>
import { listData } from "@/api/ai/data" import { listData } from "@/api/ai/data"
import { listDept } from "@/api/ai/dept" import secondLevelDeptFilter from "@/mixins/secondLevelDeptFilter"
export default { export default {
name: "TeamConsumeData", name: "TeamConsumeData",
mixins: [secondLevelDeptFilter],
data() { data() {
return { return {
loading: false, loading: false,
@ -125,7 +126,6 @@ export default {
total: 0, total: 0,
dataList: [], dataList: [],
aggregate: null, aggregate: null,
deptOptions: [],
dateRange: [], dateRange: [],
queryParams: { queryParams: {
pageNum: 1, pageNum: 1,
@ -194,18 +194,6 @@ export default {
initDefaultDateRange() { initDefaultDateRange() {
this.dateRange = this.buildLastMonthDateRange() this.dateRange = this.buildLastMonthDateRange()
}, },
loadSecondLevelDeptOptions() {
listDept({ status: "0" }).then(response => {
const allDeptList = response.data || []
this.deptOptions = allDeptList.filter(item => this.isSecondLevelDept(item))
})
},
isSecondLevelDept(dept) {
if (!dept || !dept.ancestors) {
return false
}
return String(dept.ancestors).split(",").filter(Boolean).length === 2
},
syncDateRangeToQuery() { syncDateRangeToQuery() {
if (Array.isArray(this.dateRange) && this.dateRange.length === 2) { if (Array.isArray(this.dateRange) && this.dateRange.length === 2) {
this.queryParams.startDate = this.dateRange[0] this.queryParams.startDate = this.dateRange[0]

View File

@ -1,16 +1,24 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="团队名称" prop="deptName"> <el-form-item label="团队" prop="deptId">
<el-input <el-select
v-model="queryParams.deptName" v-model="queryParams.deptId"
placeholder="请输入团队名称" placeholder="全部团队(可选)"
clearable clearable
@keyup.enter.native="handleQuery" filterable
style="width: 220px"
>
<el-option
v-for="item in secondLevelDeptOptions"
:key="item.deptId"
:label="item.deptName"
:value="item.deptId"
/> />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="状态" prop="status"> <el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="状态" clearable> <el-select v-model="queryParams.status" placeholder="团队状态" clearable>
<el-option <el-option
v-for="dict in dict.type.sys_normal_disable" v-for="dict in dict.type.sys_normal_disable"
:key="dict.value" :key="dict.value"
@ -233,11 +241,13 @@
import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from "@/api/ai/dept" import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from "@/api/ai/dept"
import Treeselect from "@riophae/vue-treeselect" import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css" import "@riophae/vue-treeselect/dist/vue-treeselect.css"
import secondLevelDeptFilter from "@/mixins/secondLevelDeptFilter"
export default { export default {
name: "AiDept", name: "AiDept",
dicts: ['sys_normal_disable'], dicts: ['sys_normal_disable'],
components: { Treeselect }, components: { Treeselect },
mixins: [secondLevelDeptFilter],
data() { data() {
return { return {
loading: true, loading: true,
@ -249,7 +259,7 @@ export default {
isExpandAll: true, isExpandAll: true,
refreshTable: true, refreshTable: true,
queryParams: { queryParams: {
deptName: undefined, deptId: null,
status: undefined status: undefined
}, },
form: {}, form: {},
@ -282,6 +292,7 @@ export default {
} }
}, },
created() { created() {
this.loadSecondLevelDeptOptions()
this.getList() this.getList()
}, },
computed: { computed: {
@ -299,11 +310,30 @@ export default {
methods: { methods: {
getList() { getList() {
this.loading = true this.loading = true
listDept(this.queryParams).then(response => { const { deptId, ...deptListQuery } = this.queryParams
this.deptList = this.handleTree(response.data, "deptId") listDept(deptListQuery).then(response => {
let raw = response.data || []
if (deptId != null && deptId !== "") {
const rootId = Number(deptId)
raw = raw.filter(d => this.deptRowInSubtree(d, rootId))
}
this.deptList = this.handleTree(raw, "deptId")
this.loading = false this.loading = false
}) })
}, },
deptRowInSubtree(d, rootId) {
if (d.deptId != null && Number(d.deptId) === rootId) {
return true
}
if (!d.ancestors) {
return false
}
return String(d.ancestors)
.split(",")
.filter(Boolean)
.map(s => Number(s))
.includes(rootId)
},
normalizer(node) { normalizer(node) {
if (node.children && !node.children.length) { if (node.children && !node.children.length) {
delete node.children delete node.children

View File

@ -9,13 +9,21 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="团队名称" prop="deptName"> <el-form-item label="团队" prop="deptId">
<el-input <el-select
v-model="queryParams.deptName" v-model="queryParams.deptId"
placeholder="支持模糊搜索" placeholder="全部团队(可选)"
clearable clearable
@keyup.enter.native="handleQuery" filterable
style="width: 220px"
>
<el-option
v-for="item in secondLevelDeptOptions"
:key="item.deptId"
:label="item.deptName"
:value="item.deptId"
/> />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="类型" prop="orderType"> <el-form-item label="类型" prop="orderType">
<el-select v-model="queryParams.orderType" placeholder="全部" clearable style="width: 110px"> <el-select v-model="queryParams.orderType" placeholder="全部" clearable style="width: 110px">
@ -138,9 +146,11 @@ import {
addGroupChargeOrder, addGroupChargeOrder,
updateGroupChargeOrder updateGroupChargeOrder
} from "@/api/ai/groupChargeOrder" } from "@/api/ai/groupChargeOrder"
import secondLevelDeptFilter from "@/mixins/secondLevelDeptFilter"
export default { export default {
name: "GroupChargeOrder", name: "GroupChargeOrder",
mixins: [secondLevelDeptFilter],
data() { data() {
return { return {
loading: true, loading: true,
@ -154,7 +164,7 @@ export default {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
orderNum: null, orderNum: null,
deptName: null, deptId: null,
orderType: null orderType: null
}, },
form: {}, form: {},
@ -181,6 +191,7 @@ export default {
} }
}, },
created() { created() {
this.loadSecondLevelDeptOptions()
this.getList() this.getList()
}, },
methods: { methods: {

View File

@ -18,13 +18,21 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="团队名称" prop="deptName"> <el-form-item label="团队" prop="deptId">
<el-input <el-select
v-model="queryParams.deptName" v-model="queryParams.deptId"
placeholder="支持模糊搜索" placeholder="全部团队(可选)"
clearable clearable
@keyup.enter.native="handleQuery" filterable
style="width: 220px"
>
<el-option
v-for="item in secondLevelDeptOptions"
:key="item.deptId"
:label="item.deptName"
:value="item.deptId"
/> />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="用户名称" prop="userName"> <el-form-item label="用户名称" prop="userName">
<el-input <el-input
@ -135,9 +143,11 @@
<script> <script>
import { listOrder } from "@/api/ai/order" import { listOrder } from "@/api/ai/order"
import secondLevelDeptFilter from "@/mixins/secondLevelDeptFilter"
export default { export default {
name: "TeamChargeOrder", name: "TeamChargeOrder",
mixins: [secondLevelDeptFilter],
data() { data() {
return { return {
loading: true, loading: true,
@ -162,13 +172,14 @@ export default {
orderNum: null, orderNum: null,
thirdPartyOrderNum: null, thirdPartyOrderNum: null,
userName: null, userName: null,
deptName: null, deptId: null,
orderType: null, orderType: null,
status: null status: null
} }
} }
}, },
created() { created() {
this.loadSecondLevelDeptOptions()
this.initDefaultDateRange() this.initDefaultDateRange()
this.getList() this.getList()
}, },

View File

@ -10,14 +10,21 @@
@keyup.enter.native="handleQuery" @keyup.enter.native="handleQuery"
/> />
</el-form-item> </el-form-item>
<el-form-item label="团队名称" prop="deptName"> <el-form-item label="团队" prop="deptId">
<el-input <el-select
v-model="queryParams.deptName" v-model="queryParams.deptId"
placeholder="请输入团队名称" placeholder="全部团队(可选)"
clearable clearable
style="width: 140px" filterable
@keyup.enter.native="handleQuery" style="width: 220px"
>
<el-option
v-for="item in secondLevelDeptOptions"
:key="item.deptId"
:label="item.deptName"
:value="item.deptId"
/> />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="类型" prop="type"> <el-form-item label="类型" prop="type">
<el-select v-model="queryParams.type" clearable placeholder="全部类型" style="width: 112px"> <el-select v-model="queryParams.type" clearable placeholder="全部类型" style="width: 112px">
@ -93,9 +100,11 @@
<script> <script>
import { listRecord } from "@/api/ai/record" import { listRecord } from "@/api/ai/record"
import secondLevelDeptFilter from "@/mixins/secondLevelDeptFilter"
export default { export default {
name: "Record", name: "Record",
mixins: [secondLevelDeptFilter],
data() { data() {
return { return {
loading: true, loading: true,
@ -114,12 +123,13 @@ export default {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
relationOrderNo: null, relationOrderNo: null,
deptName: null, deptId: null,
type: null type: null
} }
} }
}, },
created() { created() {
this.loadSecondLevelDeptOptions()
this.getList() this.getList()
}, },
methods: { methods: {

View File

@ -1,13 +1,21 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"> <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="团队名称" prop="deptName"> <el-form-item label="团队" prop="deptId">
<el-input <el-select
v-model="queryParams.deptName" v-model="queryParams.deptId"
placeholder="请输入团队名称" placeholder="全部团队(可选)"
clearable clearable
@keyup.enter.native="handleQuery" filterable
style="width: 220px"
>
<el-option
v-for="item in secondLevelDeptOptions"
:key="item.deptId"
:label="item.deptName"
:value="item.deptId"
/> />
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="状态" prop="status"> <el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="团队状态" clearable> <el-select v-model="queryParams.status" placeholder="团队状态" clearable>
@ -399,11 +407,13 @@ import {
} from "@/utils/westernNumberFormat" } from "@/utils/westernNumberFormat"
import Treeselect from "@riophae/vue-treeselect" import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css" import "@riophae/vue-treeselect/dist/vue-treeselect.css"
import secondLevelDeptFilter from "@/mixins/secondLevelDeptFilter"
export default { export default {
name: "Dept", name: "Dept",
dicts: ['sys_normal_disable'], dicts: ['sys_normal_disable'],
components: { Treeselect }, components: { Treeselect },
mixins: [secondLevelDeptFilter],
data() { data() {
return { return {
// //
@ -502,7 +512,7 @@ export default {
refreshTable: true, refreshTable: true,
// //
queryParams: { queryParams: {
deptName: undefined, deptId: null,
status: undefined status: undefined
}, },
// //
@ -547,6 +557,7 @@ export default {
} }
}, },
created() { created() {
this.loadSecondLevelDeptOptions()
this.getList() this.getList()
}, },
computed: { computed: {
@ -801,11 +812,34 @@ export default {
this.resetArkForm() this.resetArkForm()
}) })
}, },
/** 二级团队下拉:走系统部门接口(与页面列表权限一致) */
secondLevelDeptListRequest(params) {
return listDept(params)
},
deptRowInSubtree(d, rootId) {
if (d.deptId != null && Number(d.deptId) === rootId) {
return true
}
if (!d.ancestors) {
return false
}
return String(d.ancestors)
.split(",")
.filter(Boolean)
.map(s => Number(s))
.includes(rootId)
},
/** 查询部门列表 */ /** 查询部门列表 */
getList() { getList() {
this.loading = true this.loading = true
listDept(this.queryParams).then(response => { const { deptId, ...deptListQuery } = this.queryParams
this.deptList = this.handleTree(response.data, "deptId") listDept(deptListQuery).then(response => {
let raw = response.data || []
if (deptId != null && deptId !== "") {
const rootId = Number(deptId)
raw = raw.filter(d => this.deptRowInSubtree(d, rootId))
}
this.deptList = this.handleTree(raw, "deptId")
this.loading = false this.loading = false
}) })
}, },