| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923 |
- <template>
- <div class="rounded-lg p-4 bg-[var(--p-content-background)]">
- <DataTable
- :value="tableData.content"
- :paginator="true"
- paginatorTemplate="CurrentPageReport FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown JumpToPageInput"
- currentPageReportTemplate="{totalRecords} 条记录 "
- :rows="tableData.metadata.size"
- :rowsPerPageOptions="[10, 20, 50, 100]"
- :totalRecords="tableData.metadata.total"
- @page="handlePageChange"
- lazy
- scrollable
- class="members-table"
- >
- <template #header>
- <div class="flex flex-wrap items-center gap-2">
- <InputText
- v-if="isAdmin"
- v-model="searchForm.id"
- placeholder="ID"
- size="small"
- class="w-32"
- @keyup.enter="handleSearch"
- />
- <InputText
- v-model="searchForm.name"
- placeholder="成员名称"
- size="small"
- class="w-32"
- @keyup.enter="handleSearch"
- />
- <Select
- v-if="isAdmin"
- v-model="searchForm.teamId"
- :options="teamOptions"
- optionLabel="label"
- optionValue="value"
- placeholder="选择团队"
- size="small"
- class="w-40"
- showClear
- />
- <Button icon="pi pi-search" @click="handleSearch" label="搜索" size="small" severity="secondary" />
- <Button icon="pi pi-refresh" @click="handleRefresh" label="刷新" size="small" />
- <Button icon="pi pi-plus" @click="openAddDialog" label="新增成员" size="small" severity="success" />
- <div class="flex-1"></div>
- <!-- 团队用户统计信息提示 -->
- <div v-if="isTeam" class="text-sm text-gray-600">
- <span class="font-medium">团队统计:</span>
- <span v-if="teamStats" class="text-green-600 ml-1">已加载</span>
- <span v-else class="text-orange-600 ml-1">未加载</span>
- </div>
- </div>
- </template>
- <Column field="id" header="ID" style="width: 80px" frozen>
- <template #body="slotProps">
- <span
- class="font-mono text-sm copyable-text"
- :title="slotProps.data.id"
- @click="copyToClipboard(slotProps.data.id)"
- >
- {{ slotProps.data.id }}
- </span>
- </template>
- </Column>
- <Column field="name" header="成员名称" style="min-width: 150px; max-width: 200px">
- <template #body="slotProps">
- <span
- class="font-medium member-name-text copyable-text"
- :title="slotProps.data.name"
- @click="copyToClipboard(slotProps.data.name)"
- >
- {{ slotProps.data.name }}
- </span>
- </template>
- </Column>
- <Column v-if="isAdmin" field="teamId" header="所属团队" style="min-width: 120px">
- <template #body="slotProps">
- <span class="team-name-text font-medium">
- {{ getTeamName(slotProps.data.teamId) }}
- </span>
- </template>
- </Column>
- <Column field="commissionRate" header="分成比例" style="min-width: 120px">
- <template #body="slotProps">
- <span class="commission-rate-text font-semibold">
- {{ slotProps.data.commissionRate || 0 }}%
- </span>
- </template>
- </Column>
- <!-- 团队用户可见的收入统计列 -->
- <Column v-if="isTeam" field="totalRevenue" header="总收入" style="min-width: 120px">
- <template #body="slotProps">
- <span class="total-revenue-text font-semibold text-blue-600">
- ¥{{ formatAmount(getMemberTotalRevenue(slotProps.data.id)) }}
- </span>
- </template>
- </Column>
- <Column v-if="isTeam" field="todayRevenue" header="今日收入" style="min-width: 120px">
- <template #body="slotProps">
- <span class="today-revenue-text font-semibold text-green-600">
- ¥{{ formatAmount(getMemberTodayRevenue(slotProps.data.id)) }}
- </span>
- </template>
- </Column>
- <!-- 团队用户可见的销售额统计列 -->
- <Column v-if="isTeam" field="totalSales" header="总销售额" style="min-width: 120px">
- <template #body="slotProps">
- <span class="total-sales-text font-semibold text-purple-600">
- ¥{{ formatAmount(getMemberTotalSales(slotProps.data.id)) }}
- </span>
- </template>
- </Column>
- <Column v-if="isTeam" field="todaySales" header="今日销售额" style="min-width: 120px">
- <template #body="slotProps">
- <span class="today-sales-text font-semibold text-orange-600">
- ¥{{ formatAmount(getMemberTodaySales(slotProps.data.id)) }}
- </span>
- </template>
- </Column>
- <!-- 实际收入(比例)列 -->
- <Column v-if="isTeam" field="actualIncome" header="队长收入(比例)" style="min-width: 150px">
- <template #body="slotProps">
- <div class="flex flex-col">
- <span v-if="isTeamLeader(slotProps.data.id)" class="team-leader-income-text font-semibold text-red-600">
- ¥{{ formatAmount(getTeamLeaderTotalIncome(slotProps.data.id)) }}({{ getMemberActualRate(slotProps.data.id) }}%)
- </span>
- <span v-else class="actual-rate-text font-semibold text-blue-600">
- ¥{{ formatAmount(getMemberTotalRevenue(slotProps.data.id)) }}({{ getMemberActualRate(slotProps.data.id) }}%)
- </span>
- </div>
- </template>
- </Column>
- <!-- 今日实际收入(比例)列 -->
- <Column v-if="isTeam" field="todayActualIncome" header="队长今日收入(比例)" style="min-width: 150px">
- <template #body="slotProps">
- <div class="flex flex-col">
- <span v-if="isTeamLeader(slotProps.data.id)" class="team-leader-today-income-text font-semibold text-red-600">
- ¥{{ formatAmount(getTeamLeaderTodayIncome(slotProps.data.id)) }}({{ getMemberActualRate(slotProps.data.id) }}%)
- </span>
- <span v-else class="today-revenue-text font-semibold text-green-600">
- ¥{{ formatAmount(getMemberTodayRevenue(slotProps.data.id)) }}({{ getMemberActualRate(slotProps.data.id) }}%)
- </span>
- </div>
- </template>
- </Column>
- <Column field="createdAt" header="创建时间" style="min-width: 150px">
- <template #body="slotProps">
- <span class="text-sm">
- {{ formatDateTime(slotProps.data.createdAt) }}
- </span>
- </template>
- </Column>
- <Column
- header="操作"
- style="min-width: 280px; width: 280px"
- align-frozen="right"
- frozen
- :pt="{
- columnHeaderContent: {
- class: 'justify-center'
- }
- }"
- >
- <template #body="slotProps">
- <div class="flex justify-center gap-1">
- <Button
- icon="pi pi-link"
- severity="success"
- size="small"
- text
- rounded
- aria-label="生成链接"
- title="生成推广链接"
- @click="handleGenerateLink(slotProps.data)"
- />
- <Button
- icon="pi pi-qrcode"
- severity="warning"
- size="small"
- text
- rounded
- aria-label="生成推广码"
- title="生成推广码"
- @click="handleGeneratePromoCode(slotProps.data)"
- />
- <Button
- icon="pi pi-pencil"
- severity="info"
- size="small"
- text
- rounded
- aria-label="编辑"
- @click="openEditDialog(slotProps.data)"
- />
- <Button
- icon="pi pi-trash"
- severity="danger"
- size="small"
- text
- rounded
- aria-label="删除"
- @click="confirmDelete(slotProps.data)"
- />
- </div>
- </template>
- </Column>
- </DataTable>
- <!-- 新增/编辑弹窗 -->
- <Dialog
- v-model:visible="editDialog"
- :modal="true"
- :header="isEdit ? '编辑成员' : '新增成员'"
- :style="{ width: '500px' }"
- position="center"
- >
- <div class="p-fluid">
- <div class="field">
- <label for="edit-name" class="font-medium text-sm mb-2 block">成员名称</label>
- <InputText id="edit-name" v-model="editForm.name" class="w-full" />
- </div>
- <div v-if="isAdmin" class="field mt-4">
- <label for="edit-teamId" class="font-medium text-sm mb-2 block">选择团队</label>
- <Select
- id="edit-teamId"
- v-model="editForm.teamId"
- :options="teamSelectOptions"
- optionLabel="label"
- optionValue="value"
- placeholder="请选择团队"
- class="w-full"
- showClear
- />
- </div>
- <div v-if="!isEdit" class="field mt-4">
- <label for="edit-password" class="font-medium text-sm mb-2 block">密码</label>
- <Password
- id="edit-password"
- v-model="editForm.password"
- :feedback="false"
- toggleMask
- class="w-full"
- placeholder="请输入密码"
- inputClass="w-full"
- />
- </div>
- <div v-if="!isEdit" class="field mt-4">
- <label for="edit-confirmPassword" class="font-medium text-sm mb-2 block">确认密码</label>
- <Password
- id="edit-confirmPassword"
- v-model="editForm.confirmPassword"
- :feedback="false"
- toggleMask
- class="w-full"
- placeholder="请再次输入密码"
- inputClass="w-full"
- />
- </div>
- <div class="field mt-4">
- <label for="edit-commissionRate" class="font-medium text-sm mb-2 block">分成比例 (%)</label>
- <InputNumber
- id="edit-commissionRate"
- v-model="editForm.commissionRate"
- :min="0"
- :max="100"
- :step="0.1"
- suffix=" %"
- class="w-full"
- placeholder="请输入分成比例"
- :useGrouping="false"
- :allowEmpty="true"
- :showButtons="false"
- />
- </div>
- </div>
- <template #footer>
- <div class="flex justify-end gap-3">
- <Button label="取消" severity="secondary" @click="editDialog = false" />
- <Button label="保存" severity="success" @click="saveEdit" :loading="editLoading" />
- </div>
- </template>
- </Dialog>
- <!-- 推广码/链接展示弹窗 -->
- <Dialog
- v-model:visible="promoDialog"
- :modal="true"
- :header="promoDialogTitle"
- :style="{ width: '500px' }"
- position="center"
- >
- <div class="p-fluid">
- <div v-if="promoData.promoCode" class="field">
- <label class="font-medium text-sm mb-2 block">推广码</label>
- <div class="flex items-center gap-2">
- <InputText :value="promoData.promoCode" readonly class="flex-1" />
- <Button
- icon="pi pi-copy"
- size="small"
- @click="copyToClipboard(promoData.promoCode)"
- title="复制推广码"
- />
- </div>
- </div>
- <div v-if="promoData.promotionLink" class="field mt-4">
- <label class="font-medium text-sm mb-2 block">推广链接</label>
- <div class="flex items-center gap-2">
- <InputText :value="promoData.promotionLink" readonly class="flex-1" />
- <Button
- icon="pi pi-copy"
- size="small"
- @click="copyToClipboard(promoData.promotionLink)"
- title="复制推广链接"
- />
- </div>
- </div>
- </div>
- <template #footer>
- <div class="flex justify-end gap-3">
- <Button label="关闭" severity="secondary" @click="promoDialog = false" />
- </div>
- </template>
- </Dialog>
- </div>
- </template>
- <script setup>
- import { ref, onMounted, computed, inject } from 'vue'
- import Button from 'primevue/button'
- import Column from 'primevue/column'
- import DataTable from 'primevue/datatable'
- import Dialog from 'primevue/dialog'
- import Select from 'primevue/select'
- import InputText from 'primevue/inputtext'
- import InputNumber from 'primevue/inputnumber'
- import Password from 'primevue/password'
- import { useConfirm } from 'primevue/useconfirm'
- import { useToast } from 'primevue/usetoast'
- import { listMembers, createMember, updateMember, deleteMember, getTeamLeaderStats, generatePromoCode, getPromotionLink } from '@/services/api'
- import { useTeamStore } from '@/stores/team'
- const toast = useToast()
- const confirm = useConfirm()
- const teamStore = useTeamStore()
- const isAdmin = inject('isAdmin')
- const isTeam = inject('isTeam')
- // 团队选项
- const teamOptions = computed(() => {
- return [
- { label: '全部团队', value: null },
- ...teamStore.teams.map((team) => ({
- label: team.name,
- value: team.id
- }))
- ]
- })
- const teamSelectOptions = computed(() => {
- return teamStore.teams.map((team) => ({
- label: team.name,
- value: team.id
- }))
- })
- const getTeamName = (teamId) => {
- if (!teamId) return '-'
- const team = teamStore.teams.find((t) => t.id === teamId)
- return team ? team.name : '-'
- }
- const getTeamUserId = (teamId) => {
- if (!teamId) return null
- const team = teamStore.teams.find((t) => t.id === teamId)
- return team ? team.userId : null
- }
- // 表格数据
- const tableData = ref({
- content: [],
- metadata: {
- page: 0,
- size: 20,
- total: 0
- }
- })
- // 加载状态
- const loading = ref(false)
- const statsLoading = ref(false)
- // 团队统计数据
- const teamStats = ref(null)
- // 编辑相关
- const editDialog = ref(false)
- const editLoading = ref(false)
- const isEdit = ref(false)
- const editForm = ref({
- id: null,
- name: null,
- teamId: null,
- commissionRate: null
- })
- // 推广码/链接弹窗相关
- const promoDialog = ref(false)
- const promoDialogTitle = ref('')
- const promoData = ref({
- promoCode: null,
- promotionLink: null
- })
- // 搜索表单
- const searchForm = ref({
- id: null,
- name: null,
- teamId: null
- })
- // 格式化金额
- const formatAmount = (amount) => {
- if (!amount) return '0.00'
- return Number(amount).toFixed(2)
- }
- // 格式化日期时间
- const formatDateTime = (dateString) => {
- if (!dateString) return '-'
- const date = new Date(dateString)
- const year = date.getFullYear()
- const month = String(date.getMonth() + 1).padStart(2, '0')
- const day = String(date.getDate()).padStart(2, '0')
- const hours = String(date.getHours()).padStart(2, '0')
- const minutes = String(date.getMinutes()).padStart(2, '0')
- const seconds = String(date.getSeconds()).padStart(2, '0')
- return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
- }
- // 获取成员的实际比例
- const getMemberActualRate = (memberId) => {
- if (!teamStats.value?.membersStats) return 0
- const member = teamStats.value.membersStats.find(m => m.memberId === memberId)
- return member?.actualRate || 0
- }
- // 获取成员的总收入
- const getMemberTotalRevenue = (memberId) => {
- if (!teamStats.value?.membersStats) return 0
- const member = teamStats.value.membersStats.find(m => m.memberId === memberId)
- return member?.totalRevenue || 0
- }
- // 获取成员的今日收入
- const getMemberTodayRevenue = (memberId) => {
- if (!teamStats.value?.membersStats) return 0
- const member = teamStats.value.membersStats.find(m => m.memberId === memberId)
- return member?.todayRevenue || 0
- }
- // 获取成员的总销售额
- const getMemberTotalSales = (memberId) => {
- if (!teamStats.value?.membersStats) return 0
- const member = teamStats.value.membersStats.find(m => m.memberId === memberId)
- return member?.totalSales || 0
- }
- // 获取成员的今日销售额
- const getMemberTodaySales = (memberId) => {
- if (!teamStats.value?.membersStats) return 0
- const member = teamStats.value.membersStats.find(m => m.memberId === memberId)
- return member?.todaySales || 0
- }
- // 判断是否为队长
- const isTeamLeader = (memberId) => {
- if (!teamStats.value?.membersStats) return false
- const member = teamStats.value.membersStats.find(m => m.memberId === memberId)
- return member?.teamLeaderTotalIncome !== undefined || member?.teamLeaderTodayIncome !== undefined
- }
- // 获取队长的实际总收入
- const getTeamLeaderTotalIncome = (memberId) => {
- if (!teamStats.value?.membersStats) return 0
- const member = teamStats.value.membersStats.find(m => m.memberId === memberId)
- return member?.teamLeaderTotalIncome || 0
- }
- // 获取队长的实际今日收入
- const getTeamLeaderTodayIncome = (memberId) => {
- if (!teamStats.value?.membersStats) return 0
- const member = teamStats.value.membersStats.find(m => m.memberId === memberId)
- return member?.teamLeaderTodayIncome || 0
- }
- // 获取数据
- const fetchData = async () => {
- loading.value = true
- try {
- const response = await listMembers(
- tableData.value.metadata.page,
- tableData.value.metadata.size,
- searchForm.value.name || undefined,
- searchForm.value.teamId || undefined
- )
- tableData.value = response
- } catch {
- toast.add({
- severity: 'error',
- summary: '错误',
- detail: '获取成员列表失败',
- life: 3000
- })
- } finally {
- loading.value = false
- }
- }
- // 获取团队统计数据
- const fetchTeamStats = async () => {
- if (!isTeam.value) return
-
- statsLoading.value = true
- try {
- const response = await getTeamLeaderStats()
- teamStats.value = response
- } catch (error) {
- console.error('获取团队统计数据失败:', error)
- if (error.status === 403) {
- toast.add({
- severity: 'warn',
- summary: '权限不足',
- detail: '只有团队用户才能访问统计数据',
- life: 3000
- })
- } else {
- toast.add({
- severity: 'error',
- summary: '错误',
- detail: '获取团队统计数据失败',
- life: 3000
- })
- }
- } finally {
- statsLoading.value = false
- }
- }
- // 分页处理
- const handlePageChange = (event) => {
- tableData.value.metadata.page = event.page
- tableData.value.metadata.size = event.rows
- fetchData()
- }
- // 搜索处理
- const handleSearch = () => {
- tableData.value.metadata.page = 0
- fetchData()
- }
- // 刷新处理
- const handleRefresh = () => {
- searchForm.value = {
- id: null,
- name: null,
- teamId: null
- }
- tableData.value.metadata.page = 0
- fetchData()
- }
- // 确认删除
- const confirmDelete = (member) => {
- confirm.require({
- message: `确定要删除成员 "${member.name}" 吗?`,
- header: '确认删除',
- icon: 'pi pi-exclamation-triangle',
- accept: () => deleteMemberRecord(member.id)
- })
- }
- // 删除成员
- const deleteMemberRecord = async (id) => {
- try {
- await deleteMember(id)
- toast.add({
- severity: 'success',
- summary: '成功',
- detail: '删除成功',
- life: 3000
- })
- fetchData()
- } catch (error) {
- const errorMessage = error?.message || error?.detail || '删除失败'
- toast.add({
- severity: 'error',
- summary: '错误',
- detail: errorMessage,
- life: 3000
- })
- }
- }
- // 复制到剪贴板
- const copyToClipboard = async (text) => {
- try {
- await navigator.clipboard.writeText(text)
- toast.add({
- severity: 'success',
- summary: '成功',
- detail: '已复制到剪贴板',
- life: 2000
- })
- } catch {
- const textArea = document.createElement('textarea')
- textArea.value = text
- document.body.appendChild(textArea)
- textArea.select()
- document.execCommand('copy')
- document.body.removeChild(textArea)
- toast.add({
- severity: 'success',
- summary: '成功',
- detail: '已复制到剪贴板',
- life: 2000
- })
- }
- }
- // 打开新增弹窗
- const openAddDialog = () => {
- isEdit.value = false
- editForm.value = {
- id: null,
- name: null,
- teamId: null,
- commissionRate: null
- }
- editDialog.value = true
- }
- // 打开编辑弹窗
- const openEditDialog = (member) => {
- isEdit.value = true
- editForm.value = {
- id: member.id,
- name: member.name || null,
- teamId: member.teamId || null,
- commissionRate: member.commissionRate || null
- }
- editDialog.value = true
- }
- // 保存编辑
- const saveEdit = async () => {
- editLoading.value = true
- try {
- const formData = {}
- if (editForm.value.name !== null && editForm.value.name !== '') {
- formData.name = editForm.value.name
- }
- if (editForm.value.commissionRate !== null && editForm.value.commissionRate !== '') {
- formData.commissionRate = editForm.value.commissionRate
- }
- if (editForm.value.teamId !== null && editForm.value.teamId !== '') {
- formData.teamId = editForm.value.teamId
- // 只有在创建新成员时才设置userId,编辑时保持原有userId
- if (!isEdit.value) {
- formData.userId = getTeamUserId(editForm.value.teamId)
- }
- }
- if (isEdit.value) {
- await updateMember(editForm.value.id, formData)
- } else {
- await createMember(formData)
- }
- toast.add({
- severity: 'success',
- summary: '成功',
- detail: isEdit.value ? '更新成功' : '创建成功',
- life: 3000
- })
- editDialog.value = false
- fetchData()
- } catch (error) {
- const errorMessage = error?.message || error?.detail || (isEdit.value ? '更新失败' : '创建失败')
- toast.add({
- severity: 'error',
- summary: '错误',
- detail: errorMessage,
- life: 3000
- })
- } finally {
- editLoading.value = false
- }
- }
- // 生成推广码
- const handleGeneratePromoCode = async (member) => {
- try {
- const response = await generatePromoCode(member.id)
- promoData.value = {
- promoCode: response.promoCode,
- promotionLink: null
- }
- promoDialogTitle.value = `推广码 - ${member.name}`
- promoDialog.value = true
- toast.add({
- severity: 'success',
- summary: '成功',
- detail: response.message || '推广码生成成功',
- life: 3000
- })
- // 刷新数据以更新推广码
- fetchData()
- } catch (error) {
- const errorMessage = error?.message || error?.detail || '生成推广码失败'
- toast.add({
- severity: 'error',
- summary: '错误',
- detail: errorMessage,
- life: 3000
- })
- }
- }
- // 生成推广链接
- const handleGenerateLink = async (member) => {
- try {
- const response = await getPromotionLink(member.id)
- promoData.value = {
- promoCode: response.promoCode,
- promotionLink: response.promotionLink
- }
- promoDialogTitle.value = `推广链接 - ${member.name}`
- promoDialog.value = true
- toast.add({
- severity: 'success',
- summary: '成功',
- detail: '获取推广链接成功',
- life: 3000
- })
- } catch (error) {
- const errorMessage = error?.message || error?.detail || '获取推广链接失败'
- toast.add({
- severity: 'error',
- summary: '错误',
- detail: errorMessage,
- life: 3000
- })
- }
- }
- onMounted(() => {
- fetchData()
- // 如果是团队用户,预加载统计数据
- if (isTeam.value) {
- fetchTeamStats()
- }
- })
- </script>
- <style scoped>
- .p-datatable-sm .p-datatable-tbody > tr > td {
- padding: 0.5rem;
- vertical-align: top;
- }
- .p-datatable-sm .p-datatable-thead > tr > th {
- padding: 0.5rem;
- }
- .members-table {
- width: 100%;
- }
- .members-table .p-datatable-wrapper {
- overflow-x: auto;
- }
- .members-table .p-datatable-thead th {
- white-space: nowrap;
- min-width: 100px;
- }
- .font-mono {
- font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
- }
- .member-name-text {
- word-wrap: break-word;
- word-break: break-all;
- white-space: normal;
- line-height: 1.4;
- }
- .team-name-text {
- color: #7c3aed;
- font-weight: 500;
- }
- .team-id-text {
- word-wrap: break-word;
- word-break: break-all;
- white-space: normal;
- line-height: 1.4;
- }
- .user-id-text {
- word-wrap: break-word;
- word-break: break-all;
- white-space: normal;
- line-height: 1.4;
- }
- .total-revenue-text {
- color: #2563eb;
- font-weight: 600;
- }
- .today-revenue-text {
- color: #059669;
- font-weight: 600;
- }
- .commission-rate-text {
- color: #7c3aed;
- font-weight: 600;
- }
- .actual-rate-text {
- color: #2563eb;
- font-weight: 600;
- }
- .total-sales-text {
- color: #7c3aed;
- font-weight: 600;
- }
- .today-sales-text {
- color: #ea580c;
- font-weight: 600;
- }
- .team-leader-income-text {
- color: #dc2626;
- font-weight: 600;
- }
- .team-leader-today-income-text {
- color: #dc2626;
- font-weight: 600;
- }
- .font-medium {
- font-weight: 500;
- }
- .text-sm {
- font-size: 0.875rem;
- }
- .copyable-text {
- cursor: pointer;
- transition: all 0.2s ease;
- user-select: none;
- }
- .copyable-text:hover {
- background-color: #e5e7eb;
- border-radius: 4px;
- }
- .copyable-text:active {
- background-color: #d1d5db;
- transform: scale(0.98);
- }
- /* Password组件样式修复 */
- .p-password {
- width: 100%;
- }
- .p-password .p-inputtext {
- width: 100%;
- }
- .p-password .p-password-input {
- width: 100%;
- }
- </style>
|