admin_new P0+P1 全批次合并 (84 commits) #2

Merged
direv merged 85 commits from develop into main 2026-08-07 11:27:17 +08:00
7 changed files with 110 additions and 309 deletions
Showing only changes of commit a8be2d0b35 - Show all commits

View File

@ -12,6 +12,7 @@ import { ref, onMounted, watch, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { httpGet } from '@/utils/request' import { httpGet } from '@/utils/request'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
interface Inquiry { interface Inquiry {
id: string id: string
@ -122,9 +123,9 @@ watch(inquiryId, load)
<template> <template>
<div class="rr-page"> <div class="rr-page">
<div class="rr-page-header"> <PageHeader title="询价详情" :sub="`询价单号: ${detail?.id || ''} · 发布时间: ${detail ? fmtDate(detail.createDate) : ''}`">
<el-button text @click="onBack">← 返回询价列表</el-button> <el-button text @click="onBack">← 返回询价列表</el-button>
</div> </PageHeader>
<div v-if="loading" class="rr-loading"><el-skeleton :rows="6" animated /></div> <div v-if="loading" class="rr-loading"><el-skeleton :rows="6" animated /></div>
<div v-else-if="!detail" class="rr-empty"><el-empty description="询价不存在" /></div> <div v-else-if="!detail" class="rr-empty"><el-empty description="询价不存在" /></div>
@ -212,7 +213,6 @@ watch(inquiryId, load)
<style scoped lang="scss"> <style scoped lang="scss">
.rr-page { max-width: 1400px; } .rr-page { max-width: 1400px; }
.rr-page-header { margin-bottom: 16px; }
.rr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 16px; } .rr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 16px; }
.rr-card-header { padding: 16px 20px; border-bottom: 1px solid var(--border); } .rr-card-header { padding: 16px 20px; border-bottom: 1px solid var(--border); }
.rr-card-title { font-size: 15px; font-weight: 600; color: var(--ink); margin: 0; } .rr-card-title { font-size: 15px; font-weight: 600; color: var(--ink); margin: 0; }

View File

@ -11,6 +11,8 @@ import { onMounted, computed, ref } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import DataTable from '@/components/DataTable/DataTable.vue' import DataTable from '@/components/DataTable/DataTable.vue'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
import { useInquiryStore, STATUS_OPTIONS } from '@/stores/inquiry' import { useInquiryStore, STATUS_OPTIONS } from '@/stores/inquiry'
import { httpGet } from '@/utils/request' import { httpGet } from '@/utils/request'
@ -120,15 +122,9 @@ onMounted(() => { load() })
<template> <template>
<div class="rr-inquiry-list"> <div class="rr-inquiry-list">
<div class="rr-page-header"> <PageHeader title="询价管理" :sub="`共 ${total} 条询价`">
<div class="rr-page-titles"> <el-button @click="onReset">重置</el-button>
<h2 class="rr-page-title">询价管理</h2> </PageHeader>
<p class="rr-page-sub">共 {{ total }} 条询价</p>
</div>
<div class="rr-page-actions">
<el-button @click="onReset" class="rr-btn-secondary">重置</el-button>
</div>
</div>
<div class="rr-tabs-row"> <div class="rr-tabs-row">
<div class="rr-tabs"> <div class="rr-tabs">
@ -140,20 +136,15 @@ onMounted(() => { load() })
@click="onStatusTab(t.value)" @click="onStatusTab(t.value)"
>{{ t.label }}</div> >{{ t.label }}</div>
</div> </div>
<div class="rr-filters">
<el-input
v-model="filters.searchKey"
placeholder="搜索单号/客户/商品"
clearable
class="rr-search-input"
size="small"
:prefix-icon="'Search'"
@keyup.enter="onSearch"
/>
<el-button class="rr-btn-secondary" size="small" @click="onSearch">查询</el-button>
</div>
</div> </div>
<SearchBar
v-model:filters="filters"
:fields='[{ key: "searchKey", label: "", type: "text", placeholder: "搜索单号/客户/商品", clearable: true }]'
:show-reset="false"
@search="onSearch"
/>
<div class="rr-list-card"> <div class="rr-list-card">
<DataTable <DataTable
:columns="columns" :columns="columns"
@ -190,41 +181,10 @@ onMounted(() => { load() })
padding: 16px; padding: 16px;
} }
.rr-page-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 14px;
}
.rr-page-titles {
display: flex;
flex-direction: column;
gap: 2px;
}
.rr-page-title {
margin: 0;
font-size: 18px;
font-weight: 600;
color: var(--el-text-color-primary);
}
.rr-page-sub {
margin: 0;
font-size: 12px;
color: var(--el-text-color-secondary);
}
.rr-page-actions {
display: flex;
gap: 8px;
}
.rr-tabs-row { .rr-tabs-row {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: flex-start;
margin-bottom: 12px; margin-bottom: 12px;
gap: 16px; gap: 16px;
} }
@ -261,14 +221,6 @@ onMounted(() => { load() })
border-radius: 1px; border-radius: 1px;
} }
.rr-filters {
display: flex;
gap: 8px;
flex-shrink: 0;
}
.rr-search-input { width: 240px; }
.rr-list-card { .rr-list-card {
background: var(--el-bg-color); background: var(--el-bg-color);
border-radius: 12px; border-radius: 12px;

View File

@ -26,6 +26,8 @@ import { onMounted, ref, reactive, computed } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { httpGet } from '@/utils/request' import { httpGet } from '@/utils/request'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
import DataTable from '@/components/DataTable/DataTable.vue' import DataTable from '@/components/DataTable/DataTable.vue'
interface AuditLog { interface AuditLog {
@ -293,16 +295,9 @@ onMounted(() => {
<template> <template>
<div class="rr-openapi-audit"> <div class="rr-openapi-audit">
<div class="rr-page-header"> <PageHeader title="审计日志" :sub="`共 ${total} 条调用记录`">
<div class="rr-page-titles"> <el-button @click="onReset">重置</el-button>
<h2 class="rr-page-title">审计日志</h2> </PageHeader>
<p class="rr-page-sub">共 {{ total }} 条调用记录</p>
</div>
<div class="rr-page-actions">
<el-button @click="onReset" class="rr-btn-secondary">重置</el-button>
<el-button type="primary" class="rr-btn-primary" @click="onSearch">查询</el-button>
</div>
</div>
<div class="rr-tabs-row"> <div class="rr-tabs-row">
<div class="rr-tabs"> <div class="rr-tabs">
@ -314,59 +309,23 @@ onMounted(() => {
@click="onStatusTab(t.value)" @click="onStatusTab(t.value)"
>{{ t.label }}</div> >{{ t.label }}</div>
</div> </div>
<div class="rr-filters">
<el-input
v-model="filters.searchKey"
placeholder="搜索 工具 / 请求ID / 摘要"
clearable
class="rr-search-input"
size="small"
:prefix-icon="'Search'"
@keyup.enter="onSearch"
/>
<el-select
v-model="filters.customerCode"
placeholder="客户"
class="rr-customer-select"
clearable
filterable
size="small"
>
<el-option
v-for="opt in customerOptions"
:key="opt.value"
:label="opt.label"
:value="opt.value"
/>
</el-select>
<el-select
v-model="filters.appId"
placeholder="App"
class="rr-app-select"
clearable
filterable
size="small"
>
<el-option
v-for="opt in appOptions"
:key="opt.value"
:label="opt.label"
:value="opt.value"
/>
</el-select>
<el-select
v-model="filters.callType"
placeholder="类型"
class="rr-type-select"
clearable
size="small"
>
<el-option value="MCP" label="MCP" />
<el-option value="REST" label="REST" />
</el-select>
</div>
</div> </div>
<SearchBar
v-model:filters="filters"
:fields='[
{ key: "searchKey", label: "", type: "text", placeholder: "搜索 工具 / 请求ID / 摘要", clearable: true },
{ key: "customerCode", label: "客户", type: "select", placeholder: "客户", clearable: true,
options: customerOptions.map(o => ({ value: o.value, label: o.label })) },
{ key: "appId", label: "App", type: "select", placeholder: "App", clearable: true,
options: appOptions.map(o => ({ value: o.value, label: o.label })) },
{ key: "callType", label: "类型", type: "select", placeholder: "类型", clearable: true,
options: [{ value: "MCP", label: "MCP" }, { value: "REST", label: "REST" }] }
]'
:show-reset="false"
@search="onSearch"
/>
<div class="rr-list-card"> <div class="rr-list-card">
<DataTable <DataTable
:columns="[ :columns="[
@ -533,36 +492,15 @@ onMounted(() => {
padding: 16px; padding: 16px;
} }
.rr-page-header { /* PageHeader/SearchBar 接管 */
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 14px;
}
.rr-page-titles { /* PageHeader/SearchBar 接管 */
display: flex;
flex-direction: column;
gap: 2px;
}
.rr-page-title { /* PageHeader/SearchBar 接管 */
margin: 0;
font-size: 18px;
font-weight: 600;
color: var(--el-text-color-primary);
}
.rr-page-sub { /* PageHeader/SearchBar 接管 */
margin: 0;
font-size: 12px;
color: var(--el-text-color-secondary);
}
.rr-page-actions { /* PageHeader/SearchBar 接管 */
display: flex;
gap: 8px;
}
.rr-tabs-row { .rr-tabs-row {
display: flex; display: flex;
@ -604,16 +542,12 @@ onMounted(() => {
border-radius: 1px; border-radius: 1px;
} }
.rr-filters { /* PageHeader/SearchBar 接管 */
display: flex;
gap: 8px;
flex-shrink: 0;
}
.rr-search-input { width: 240px; } /* PageHeader/SearchBar 接管 */
.rr-customer-select { width: 180px; } /* PageHeader/SearchBar 接管 */
.rr-app-select { width: 180px; } /* PageHeader/SearchBar 接管 */
.rr-type-select { width: 90px; } /* PageHeader/SearchBar 接管 */
.rr-list-card { .rr-list-card {
background: var(--el-bg-color); background: var(--el-bg-color);

View File

@ -21,6 +21,8 @@ import { onMounted, ref, reactive } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { httpGet, httpPost } from '@/utils/request' import { httpGet, httpPost } from '@/utils/request'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
import DataTable from '@/components/DataTable/DataTable.vue' import DataTable from '@/components/DataTable/DataTable.vue'
interface CompanyAccount { interface CompanyAccount {
@ -239,34 +241,20 @@ onMounted(() => { load(); loadCustomers() })
<template> <template>
<div class="rr-openapi-company"> <div class="rr-openapi-company">
<div class="rr-page-header"> <PageHeader title="公司账号管理" :sub="`共 ${total} 个公司账号`">
<div class="rr-page-titles"> <el-button @click="onReset">重置</el-button>
<h2 class="rr-page-title">公司账号管理</h2> </PageHeader>
<p class="rr-page-sub">共 {{ total }} 个公司账号</p>
</div>
<div class="rr-page-actions">
<el-button @click="onReset" class="rr-btn-secondary">重置</el-button>
</div>
</div>
<div class="rr-filters-row"> <SearchBar
<el-select v-model:filters="filters"
v-model="filters.customerCode" :fields='[{
placeholder="选择客户筛选" key: "customerCode", label: "客户筛选", type: "select",
class="rr-customer-select" placeholder: "选择客户筛选", clearable: true,
clearable options: customerOptions.map(o => ({ value: o.value, label: o.label }))
filterable }]'
size="small" @search="onSearch"
> @reset="load"
<el-option />
v-for="opt in customerOptions"
:key="opt.value"
:label="opt.label"
:value="opt.value"
/>
</el-select>
<el-button class="rr-btn-secondary" size="small" @click="onSearch">查询</el-button>
</div>
<div class="rr-list-card"> <div class="rr-list-card">
<DataTable <DataTable
@ -421,50 +409,19 @@ onMounted(() => { load(); loadCustomers() })
padding: 16px; padding: 16px;
} }
.rr-page-header { /* PageHeader 接管 */
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 14px;
}
.rr-page-titles { /* PageHeader 接管 */
display: flex;
flex-direction: column;
gap: 2px;
}
.rr-page-title { /* PageHeader 接管 */
margin: 0;
font-size: 18px;
font-weight: 600;
color: var(--el-text-color-primary);
}
.rr-page-sub { /* PageHeader 接管 */
margin: 0;
font-size: 12px;
color: var(--el-text-color-secondary);
}
.rr-page-actions { /* PageHeader 接管 */
display: flex;
gap: 8px;
}
.rr-filters-row { /* SearchBar 接管 */
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 14px;
padding: 12px 16px;
background: var(--el-fill-color-light);
border-radius: 8px;
}
.rr-customer-select { /* SearchBar 接管 */
width: 280px;
}
.rr-list-card { .rr-list-card {
background: var(--el-bg-color); background: var(--el-bg-color);

View File

@ -23,6 +23,8 @@
import { onMounted, ref, reactive, computed } from 'vue' import { onMounted, ref, reactive, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { httpGet, httpPost } from '@/utils/request' import { httpGet, httpPost } from '@/utils/request'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
import DataTable from '@/components/DataTable/DataTable.vue' import DataTable from '@/components/DataTable/DataTable.vue'
import ApplyApiKeyDialog from './ApplyApiKeyDialog.vue' import ApplyApiKeyDialog from './ApplyApiKeyDialog.vue'
@ -321,16 +323,10 @@ onMounted(() => { load(); loadCustomers() })
<template> <template>
<div class="rr-openapi-app"> <div class="rr-openapi-app">
<div class="rr-page-header"> <PageHeader title="应用列表" :sub="`共 ${total} 个集成应用`">
<div class="rr-page-titles"> <el-button @click="onReset">重置</el-button>
<h2 class="rr-page-title">应用列表</h2> <el-button type="primary" @click="onApplyDialogOpen">+ 申请新 APIKey</el-button>
<p class="rr-page-sub">共 {{ total }} 个集成应用</p> </PageHeader>
</div>
<div class="rr-page-actions">
<el-button @click="onReset" class="rr-btn-secondary">重置</el-button>
<el-button type="primary" class="rr-btn-primary" @click="onApplyDialogOpen">+ 申请新 APIKey</el-button>
</div>
</div>
<div class="rr-tabs-row"> <div class="rr-tabs-row">
<div class="rr-tabs"> <div class="rr-tabs">
@ -342,33 +338,19 @@ onMounted(() => { load(); loadCustomers() })
@click="onStatusTab(t.value)" @click="onStatusTab(t.value)"
>{{ t.label }}</div> >{{ t.label }}</div>
</div> </div>
<div class="rr-filters">
<el-input
v-model="filters.searchKey"
placeholder="搜索 app 名称 / app_id / 客户名"
clearable
class="rr-search-input"
:prefix-icon="'Search'"
@keyup.enter="onSearch"
/>
<el-select
v-model="filters.customerCode"
placeholder="客户"
class="rr-customer-select"
clearable
filterable
>
<el-option
v-for="opt in customerOptions"
:key="opt.value"
:label="opt.label"
:value="opt.value"
/>
</el-select>
<el-button class="rr-btn-secondary" @click="onSearch">查询</el-button>
</div>
</div> </div>
<SearchBar
v-model:filters="filters"
:fields='[
{ key: "searchKey", label: "", type: "text", placeholder: "搜索 app 名称 / app_id / 客户名", clearable: true },
{ key: "customerCode", label: "客户", type: "select", placeholder: "客户", clearable: true,
options: customerOptions.map(o => ({ value: o.value, label: o.label })) }
]'
@search="onSearch"
@reset="load"
/>
<div class="rr-list-card"> <div class="rr-list-card">
<DataTable <DataTable
:columns="columns" :columns="columns"
@ -573,17 +555,11 @@ onMounted(() => { load(); loadCustomers() })
<style scoped lang="scss"> <style scoped lang="scss">
.rr-openapi-app { max-width: 1400px; } .rr-openapi-app { max-width: 1400px; }
.rr-page-header { /* PageHeader/SearchBar 接管 */
display: flex; align-items: flex-start; justify-content: space-between; /* PageHeader/SearchBar 接管 */
margin-bottom: 20px; /* PageHeader/SearchBar 接管 */
} /* PageHeader/SearchBar 接管 */
.rr-page-titles { display: flex; flex-direction: column; gap: 4px; } /* PageHeader/SearchBar 接管 */
.rr-page-title {
font-size: 22px; font-weight: 600; letter-spacing: -0.02em;
color: var(--ink); margin: 0;
}
.rr-page-sub { color: var(--ink-3); font-size: 13px; margin: 0; }
.rr-page-actions { display: flex; gap: 8px; flex-shrink: 0; }
.rr-list-card { .rr-list-card {
background: var(--surface); background: var(--surface);
@ -610,9 +586,9 @@ onMounted(() => { load(); loadCustomers() })
height: 2px; background: var(--brand); border-radius: 1px; height: 2px; background: var(--brand); border-radius: 1px;
} }
} }
.rr-filters { display: flex; gap: 8px; flex-shrink: 0; } /* PageHeader/SearchBar 接管 */
.rr-search-input { width: 280px; } /* PageHeader/SearchBar 接管 */
.rr-customer-select { width: 160px; } /* PageHeader/SearchBar 接管 */
/* 状态徽章(浅底色块 - 4 种状态) */ /* 状态徽章(浅底色块 - 4 种状态) */
.rr-badge { .rr-badge {

View File

@ -484,13 +484,9 @@ onMounted(load)
<style scoped lang="scss"> <style scoped lang="scss">
.rr-page { max-width: 1500px; } .rr-page { max-width: 1500px; }
.rr-page-header { margin-bottom: 16px; display: flex; justify-content: space-between; align-items: flex-start; } /* PageHeader 复用通用组件样式 */
.rr-page-title { font-size: 22px; font-weight: 600; letter-spacing: -0.02em; color: var(--ink); margin: 0 0 4px 0; }
.rr-page-sub { color: var(--ink-3); font-size: 13px; margin: 0; }
.rr-page-actions { display: flex; gap: 8px; }
.rr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 16px; } .rr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 16px; }
.rr-search { padding: 16px 20px; } /* search 由 SearchBar 接管 */
.rr-search :deep(.el-form-item) { margin-bottom: 0; margin-right: 12px; }
.rr-tabs-row { margin-bottom: 16px; display: flex; align-items: center; } .rr-tabs-row { margin-bottom: 16px; display: flex; align-items: center; }
.rr-tabs { display: flex; gap: 4px; padding: 4px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); } .rr-tabs { display: flex; gap: 4px; padding: 4px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); }
.rr-tab { padding: 6px 16px; border-radius: var(--radius); font-size: 13px; color: var(--ink-2); cursor: pointer; transition: all 0.15s; } .rr-tab { padding: 6px 16px; border-radius: var(--radius); font-size: 13px; color: var(--ink-2); cursor: pointer; transition: all 0.15s; }

View File

@ -13,6 +13,8 @@
import { ref, onMounted, reactive } from 'vue' import { ref, onMounted, reactive } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { httpGet } from '@/utils/request' import { httpGet } from '@/utils/request'
import PageHeader from '@/components/PageHeader/PageHeader.vue'
import SearchBar from '@/components/SearchBar/SearchBar.vue'
interface ServiceGood { interface ServiceGood {
id: string id: string
@ -122,31 +124,20 @@ onMounted(load)
<template> <template>
<div class="rr-page"> <div class="rr-page">
<div class="rr-page-header"> <PageHeader title="服务商品管理" :sub="`共 ${total} 个服务商品`">
<div> <el-button @click="onExport">导出</el-button>
<h2 class="rr-page-title">服务商品管理</h2> <el-button type="primary" @click="onAdd">新增服务</el-button>
<p class="rr-page-sub">共 {{ total }} 个服务商品</p> </PageHeader>
</div>
<div class="rr-page-actions">
<el-button @click="onExport">导出</el-button>
<el-button type="primary" @click="onAdd">新增服务</el-button>
</div>
</div>
<div class="rr-card rr-search"> <SearchBar
<el-form :inline="true" @keyup.enter="onSearch"> v-model:filters="filters"
<el-form-item label="服务名称"> :fields='[
<el-input v-model="filters.title" placeholder="服务名称" clearable style="width: 200px" /> { key: "title", label: "服务名称", type: "text", placeholder: "服务名称", clearable: true },
</el-form-item> { key: "enterpriseName", label: "供应商", type: "text", placeholder: "供应商", clearable: true }
<el-form-item label="供应商"> ]'
<el-input v-model="filters.enterpriseName" placeholder="供应商" clearable style="width: 200px" /> @search="onSearch"
</el-form-item> @reset="load"
<el-form-item> />
<el-button type="primary" @click="onSearch">查询</el-button>
<el-button @click="onReset">重置</el-button>
</el-form-item>
</el-form>
</div>
<div class="rr-tabs-row"> <div class="rr-tabs-row">
<div class="rr-tabs"> <div class="rr-tabs">
@ -284,12 +275,7 @@ onMounted(load)
<style scoped lang="scss"> <style scoped lang="scss">
.rr-page { max-width: 1500px; } .rr-page { max-width: 1500px; }
.rr-page-header { margin-bottom: 16px; display: flex; justify-content: space-between; align-items: flex-start; }
.rr-page-title { font-size: 22px; font-weight: 600; color: var(--ink); margin: 0 0 4px 0; }
.rr-page-sub { color: var(--ink-3); font-size: 13px; margin: 0; }
.rr-page-actions { display: flex; gap: 8px; }
.rr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 16px; } .rr-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 16px; }
.rr-search { padding: 16px 20px; }
.rr-tabs-row { margin-bottom: 16px; } .rr-tabs-row { margin-bottom: 16px; }
.rr-tabs { display: flex; gap: 4px; padding: 4px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); width: fit-content; } .rr-tabs { display: flex; gap: 4px; padding: 4px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); width: fit-content; }
.rr-tab { padding: 6px 16px; border-radius: var(--radius); font-size: 13px; color: var(--ink-2); cursor: pointer; } .rr-tab { padding: 6px 16px; border-radius: var(--radius); font-size: 13px; color: var(--ink-2); cursor: pointer; }