refactor(pc): 从 Gi Admin Pro + Arco 重搭为纯 Vue 3 + Naive UI
旧模板的 193 个文件整体删除,换成纯 Vue 3.5 + Naive UI 2.42 的树。
- 去掉 auto-import(组件与 API 全显式 import)、v-hasPerm(改 user.has('码'),全库 8 处)、
Stylelint;n-tag 的 type 统一过 utils/tag.ts 转换(Arco 色词直接透传会静默变灰)
- 图标改为构建期抽取:scripts/extract-pc-icons.py -> icons/icon-data.ts(37 个),
内网离线部署不会白屏
- 重搭后修掉 6 类"编译 / lint / typecheck 全绿、界面上就是坏的"故障:
① NGrid 的 cols 写成像素值(不是断点名 -> 永远只 1 列,工作台因此错乱)
② n-tab-pane 用 tab 属性(只渲染空注释节点,整排 tab 一个字都不显示)
③ 漏 import 被当未知自定义元素(样式整块丢) ④ .n-card__content 类名不存在
(高度链第一环失效,表格行在 DOM 里但屏幕上没有) ⑤ 填报单状态映射错位一格
⑥ 有标题的卡片没有上内边距(naive 的 padding-top 只给"内容区是长子"的卡片)
- 卡片式版面提成全局基线:styles/index.scss 的 xt-* 令牌 + .page-card / .toolbar /
.section-title,页面只引用、不再各写一套
- 品牌:改名「深学在线」,文字标换成几何标(方 = 卷宗 / 环 = 在线,不用文字字形);
index.html 的页签图标从 404 的 /favicon.ico 改指真实存在的 /favicon.svg
This commit is contained in:
@@ -1,118 +1,64 @@
|
||||
<template>
|
||||
<a-drawer v-model:visible="visible" :width="820" :mask-closable="false" unmount-on-close
|
||||
:ok-loading="saving" ok-text="保存" @ok="save" @cancel="close">
|
||||
<template #title>
|
||||
<span>配置覆盖班级</span>
|
||||
<span class="org-drawer__task">{{ taskName }}</span>
|
||||
</template>
|
||||
|
||||
<a-alert v-if="readonly" type="normal" :show-icon="false" class="org-drawer__readonly">
|
||||
任务已{{ readonlyReason }},覆盖范围不可再修改,只能查看。
|
||||
</a-alert>
|
||||
|
||||
<a-spin :loading="loading" class="org-drawer__body">
|
||||
<div class="org-drawer__panes">
|
||||
<!-- 左:组织树 -->
|
||||
<div class="org-drawer__tree">
|
||||
<div class="org-drawer__pane-title">
|
||||
选择班级
|
||||
<!-- 只让班级可勾选:把「学校」或「专业部」当成一个班会选错范围,
|
||||
而且错误很隐蔽 —— 界面上只多一行,实际却把整校学生算进了应填范围 -->
|
||||
<span class="org-drawer__pane-hint">只能勾选到班级一层</span>
|
||||
</div>
|
||||
<a-spin :loading="treeLoading" class="org-drawer__tree-spin">
|
||||
<a-tree v-if="treeData.length" v-model:checked-keys="checkedKeys" :data="treeData"
|
||||
:field-names="treeFieldNames" checkable check-strictly :default-expand-all="true"
|
||||
:disabled="readonly" />
|
||||
<a-empty v-else description="还没有班级,请先在「组织架构」里建班级" />
|
||||
</a-spin>
|
||||
</div>
|
||||
|
||||
<!-- 右:已选班级 -->
|
||||
<div class="org-drawer__list">
|
||||
<div class="org-drawer__pane-title">
|
||||
已选 <strong>{{ rows.length }}</strong> 个班
|
||||
<span class="org-drawer__pane-hint">主班主任留空 = 由该班负责人初审</span>
|
||||
</div>
|
||||
|
||||
<a-empty v-if="!rows.length" description="左侧勾选本次收集涉及的班级" />
|
||||
|
||||
<div v-for="row in rows" :key="row.orgId" class="org-drawer__row">
|
||||
<div class="org-drawer__row-head">
|
||||
<span class="org-drawer__org">{{ orgName(row.orgId) }}</span>
|
||||
<a-link v-if="!readonly" status="danger" @click="removeRow(row)">移除</a-link>
|
||||
</div>
|
||||
|
||||
<a-row :gutter="12">
|
||||
<a-col :span="11">
|
||||
<div class="org-drawer__label">主班主任(初审人)</div>
|
||||
<a-select v-model="row.headUserId" placeholder="留空 = 取班级负责人" allow-clear
|
||||
:options="teacherOptions" :disabled="readonly" size="small" />
|
||||
<div v-if="!row.headUserId" class="org-drawer__fallback">
|
||||
{{ leaderHint(row.orgId) }}
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<div class="org-drawer__label">应填人数</div>
|
||||
<a-input-number v-model="row.expectedCount" placeholder="未设置" :min="0"
|
||||
:disabled="readonly" size="small" class="org-drawer__num" />
|
||||
<div class="org-drawer__fallback">留空表示不比对,填了才与名册比</div>
|
||||
</a-col>
|
||||
<a-col :span="5">
|
||||
<div class="org-drawer__label">副班主任</div>
|
||||
<a-select v-model="row.deputyUserIds" multiple placeholder="无" allow-clear
|
||||
:options="deputyOptionsOf(row)" :disabled="readonly" size="small" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-spin>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { TreeFieldNames, TreeNodeData } from '@arco-design/web-vue'
|
||||
import type { OrgTreeVO } from '@/apis/xt/org'
|
||||
import type { TaskOrgItem } from '@/apis/xt/task'
|
||||
import { Message } from '@arco-design/web-vue'
|
||||
import * as orgApi from '@/apis/xt/org'
|
||||
import * as taskApi from '@/apis/xt/task'
|
||||
|
||||
/**
|
||||
* 任务「覆盖班级与班主任」配置抽屉(《03-接口设计》§7.6)。
|
||||
* 任务「覆盖班级与初审人」配置抽屉(《03-接口设计》§7.6)。
|
||||
*
|
||||
* 三处刻意的设计:
|
||||
*
|
||||
* 1. **主班主任留空 ≠ 没配**。留空表示"取该班负责人",所以留空时下面会显示出
|
||||
* 负责人是谁。不这么做,管理员会以为漏配了,然后在几百个班上机械地点几百次 ——
|
||||
* 而它们本来就等于班级负责人。这是本产品"少让人做无意义操作"的一个具体体现。
|
||||
* 1. **初审人留空 ≠ 没配**。留空表示"取该班负责人"(服务端回退到 `sys_org.leader_user_id`),
|
||||
* 所以留空时下面会显示出负责人是谁。不这么做,管理员会以为漏配了,
|
||||
* 然后在几百个班上机械地点几百次 —— 而它们本来就等于班级负责人。
|
||||
* 这是本产品"少让人做无意义操作"的一个具体体现。
|
||||
*
|
||||
* 2. **只让班级可勾选**。把「学校」或「专业部」当成一个班会选错范围,而且错误很隐蔽:
|
||||
* 界面上只多一行,实际却把整校学生算进了应填范围。服务端也会拒,但让它在界面上
|
||||
* 就点不动,比事后报错好。
|
||||
* 界面上只多一行,实际却把整校学生算进了应填范围。服务端也会拒,
|
||||
* 但让它在界面上就点不动,比事后报错好。
|
||||
*
|
||||
* 3. **应填人数留空 = 未设置,不是 0**。0 是"预期 0 人",是个有意义的业务值;
|
||||
* 拿 0 兼职表示"没填"会让每个没填的班都触发"应填 0 人、实际 31 人"的假告警,
|
||||
* 告警变噪音后就没人看了,真正对不上的那次反而被漏掉。
|
||||
*
|
||||
* ⚠️ 2026-10 需求收敛:**副班主任角色已删除**(后端 `TaskOrgSaveReq` 里也没有这个字段了),
|
||||
* 所以这里只有"初审人"一列。多留一个选了不生效的下拉,比没有它更糟。
|
||||
*/
|
||||
import type { TreeOption } from 'naive-ui'
|
||||
import type { OrgTreeVO } from '@/apis/xt/org'
|
||||
import type { TaskOrgItem, TaskVO } from '@/apis/xt/task'
|
||||
import {
|
||||
NAlert,
|
||||
NButton,
|
||||
NDrawer,
|
||||
NDrawerContent,
|
||||
NEmpty,
|
||||
NInputNumber,
|
||||
NSelect,
|
||||
NSpace,
|
||||
NSpin,
|
||||
NTree,
|
||||
useMessage
|
||||
} from 'naive-ui'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import * as orgApi from '@/apis/xt/org'
|
||||
import * as taskApi from '@/apis/xt/task'
|
||||
|
||||
defineOptions({ name: 'TaskOrgDrawer' })
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'save-success'): void
|
||||
}>()
|
||||
|
||||
const message = useMessage()
|
||||
|
||||
const visible = ref(false)
|
||||
const loading = ref(false)
|
||||
const treeLoading = ref(false)
|
||||
const saving = ref(false)
|
||||
const taskId = ref<number | null>(null)
|
||||
const taskName = ref('')
|
||||
const readonly = ref(false)
|
||||
const readonlyReason = ref('')
|
||||
|
||||
const treeData = ref<TreeNodeData[]>([])
|
||||
const checkedKeys = ref<number[]>([])
|
||||
const treeData = ref<TreeOption[]>([])
|
||||
/** Naive 的勾选键是 `(string | number)[]`,所以这里不能窄化成 number[] */
|
||||
const checkedKeys = ref<Array<string | number>>([])
|
||||
const teacherOptions = ref<Array<{ id: number, label: string }>>([])
|
||||
|
||||
/** 班级 id → 组织节点,用于取名与取"该班负责人" */
|
||||
@@ -120,41 +66,31 @@ const orgIndex = ref<Map<number, OrgTreeVO>>(new Map())
|
||||
|
||||
interface Row {
|
||||
orgId: number
|
||||
/**
|
||||
* 主班主任。
|
||||
*
|
||||
* ⚠️ 用 `undefined` 而不是 `null` 表示"未指定":Arco 的 `a-select` 的 v-model
|
||||
* 只接受 `string | number | (string|number)[] | undefined`,
|
||||
* 绑 `number | null` 会报 TS2322。提交时再转回 `null`(接口约定的"清空"值)。
|
||||
*/
|
||||
headUserId: number | undefined
|
||||
deputyUserIds: number[]
|
||||
/** undefined = 未设置(提交时不传/传 null),不要用 0 代替 —— 0 是"预期 0 人" */
|
||||
expectedCount: number | undefined
|
||||
/** null = 未指定,界面上显示占位符;提交时原样传 null(接口约定的"清空"值) */
|
||||
headUserId: number | null
|
||||
/** null = 未设置(提交时不传/传 null),**不要用 0 代替** —— 0 是"预期 0 人" */
|
||||
expectedCount: number | null
|
||||
}
|
||||
|
||||
const rows = ref<Row[]>([])
|
||||
|
||||
const treeFieldNames: TreeFieldNames = {
|
||||
key: 'key',
|
||||
title: 'title',
|
||||
children: 'children',
|
||||
disableCheckbox: 'disableCheckbox'
|
||||
}
|
||||
const teacherSelectOptions = computed(
|
||||
() => teacherOptions.value.map((t) => ({ label: t.label, value: t.id }))
|
||||
)
|
||||
|
||||
function flatten(nodes: OrgTreeVO[], into: Map<number, OrgTreeVO>) {
|
||||
for (const n of nodes || []) {
|
||||
for (const n of nodes ?? []) {
|
||||
into.set(n.id, n)
|
||||
flatten(n.children ?? [], into)
|
||||
}
|
||||
}
|
||||
|
||||
function toTreeData(nodes: OrgTreeVO[]): TreeNodeData[] {
|
||||
function toTreeData(nodes: OrgTreeVO[]): TreeOption[] {
|
||||
return (nodes ?? []).map((n) => ({
|
||||
key: n.id,
|
||||
title: n.orgName,
|
||||
// 只有班级可以勾选
|
||||
disableCheckbox: n.orgType !== 3,
|
||||
label: n.orgName,
|
||||
// 只有班级可以勾选;只读时整棵树都点不动
|
||||
checkboxDisabled: readonly.value || n.orgType !== 3,
|
||||
children: toTreeData(n.children ?? [])
|
||||
}))
|
||||
}
|
||||
@@ -166,35 +102,32 @@ function orgName(orgId: number) {
|
||||
/** 留空时告诉用户"将由谁审",而不是留一句让人怀疑的空白 */
|
||||
function leaderHint(orgId: number) {
|
||||
const org = orgIndex.value.get(orgId)
|
||||
return org?.leaderName ? `将由班级负责人 ${org.leaderName} 初审` : '该班未设负责人,建议指定初审人'
|
||||
}
|
||||
|
||||
/** 副班主任选项里排除掉本行已选为主班主任的人(同一人不能既主又副,服务端会拒) */
|
||||
function deputyOptionsOf(row: Row) {
|
||||
return teacherOptions.value.filter((o) => o.id !== row.headUserId)
|
||||
return org?.leaderName
|
||||
? `将由班级负责人 ${org.leaderName} 初审`
|
||||
: '该班未设负责人,建议指定初审人'
|
||||
}
|
||||
|
||||
/** 勾选变化 → 行列表变化。rows 是唯一事实来源,勾选框只是它的一个视图 */
|
||||
watch(checkedKeys, (keys) => {
|
||||
const set = new Set(keys as number[])
|
||||
const set = new Set(keys.map((k) => Number(k)))
|
||||
rows.value = rows.value.filter((r) => set.has(r.orgId))
|
||||
for (const id of set) {
|
||||
if (!rows.value.some((r) => r.orgId === id)) {
|
||||
rows.value.push({ orgId: id, headUserId: undefined, deputyUserIds: [], expectedCount: undefined })
|
||||
rows.value.push({ orgId: id, headUserId: null, expectedCount: null })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function removeRow(row: Row) {
|
||||
rows.value = rows.value.filter((r) => r.orgId !== row.orgId)
|
||||
checkedKeys.value = checkedKeys.value.filter((k) => k !== row.orgId)
|
||||
checkedKeys.value = checkedKeys.value.filter((k) => Number(k) !== row.orgId)
|
||||
}
|
||||
|
||||
async function open(task: { id: number, taskName: string, status: number }) {
|
||||
async function open(task: TaskVO) {
|
||||
taskId.value = task.id
|
||||
taskName.value = task.taskName
|
||||
// 与后端 EDITABLE_TASK_STATUS 一致:草稿/收集中/已暂停可改,已截止/已归档只读
|
||||
const reason = { 2: '截止', 3: '归档' }[task.status] ?? ''
|
||||
const reason = ({ 2: '截止', 3: '归档' } as Record<number, string>)[task.status] ?? ''
|
||||
readonly.value = !!reason
|
||||
readonlyReason.value = reason
|
||||
visible.value = true
|
||||
@@ -202,37 +135,36 @@ async function open(task: { id: number, taskName: string, status: number }) {
|
||||
checkedKeys.value = []
|
||||
|
||||
loading.value = true
|
||||
treeLoading.value = true
|
||||
try {
|
||||
const [treeRes, orgRes] = await Promise.all([
|
||||
const [tree, orgs] = await Promise.all([
|
||||
orgApi.getOrgTree(),
|
||||
taskApi.getTaskOrgs(task.id)
|
||||
])
|
||||
const tree = treeRes.data ?? []
|
||||
treeData.value = toTreeData(tree)
|
||||
const nodes = tree ?? []
|
||||
const index = new Map<number, OrgTreeVO>()
|
||||
flatten(tree, index)
|
||||
flatten(nodes, index)
|
||||
orgIndex.value = index
|
||||
treeData.value = toTreeData(nodes)
|
||||
|
||||
for (const o of orgRes.data ?? []) {
|
||||
for (const o of orgs ?? []) {
|
||||
rows.value.push({
|
||||
// 后端回 null 表示"未指定";界面上显示占位符、提交时再回 null
|
||||
orgId: o.orgId,
|
||||
// 后端回 null 表示"未指定";界面上用 undefined 让它显示占位符
|
||||
headUserId: o.headUserId ?? undefined,
|
||||
deputyUserIds: o.deputyUserIds ?? [],
|
||||
expectedCount: o.expectedCount ?? undefined
|
||||
headUserId: o.headUserId ?? null,
|
||||
expectedCount: o.expectedCount ?? null
|
||||
})
|
||||
}
|
||||
checkedKeys.value = rows.value.map((r) => r.orgId)
|
||||
} finally {
|
||||
loading.value = false
|
||||
treeLoading.value = false
|
||||
}
|
||||
|
||||
// 班主任选项不影响主流程,单独加载,失败也不该让抽屉打不开
|
||||
taskApi.getTeacherOptions()
|
||||
.then((opts) => { teacherOptions.value = opts })
|
||||
.catch(() => { teacherOptions.value = [] })
|
||||
// 初审人选项不影响主流程,单独加载,失败也不该让抽屉打不开
|
||||
try {
|
||||
teacherOptions.value = await taskApi.getTeacherOptions()
|
||||
} catch {
|
||||
teacherOptions.value = []
|
||||
}
|
||||
}
|
||||
|
||||
function close() {
|
||||
@@ -240,19 +172,20 @@ function close() {
|
||||
}
|
||||
|
||||
async function save() {
|
||||
if (!taskId.value) return
|
||||
if (!taskId.value) {
|
||||
return
|
||||
}
|
||||
const orgs: TaskOrgItem[] = rows.value.map((r) => ({
|
||||
orgId: r.orgId,
|
||||
headUserId: r.headUserId ?? null,
|
||||
deputyUserIds: r.deputyUserIds ?? [],
|
||||
headUserId: r.headUserId,
|
||||
// 未填就传 null("未设置"),不要传 0
|
||||
expectedCount: r.expectedCount ?? null
|
||||
expectedCount: r.expectedCount
|
||||
}))
|
||||
|
||||
saving.value = true
|
||||
try {
|
||||
await taskApi.saveTaskOrgs(taskId.value, orgs)
|
||||
Message.success(orgs.length ? `已保存 ${orgs.length} 个班的覆盖范围` : '已清空覆盖范围')
|
||||
message.success(orgs.length ? `已保存 ${orgs.length} 个班的覆盖范围` : '已清空覆盖范围')
|
||||
visible.value = false
|
||||
emit('save-success')
|
||||
} finally {
|
||||
@@ -263,24 +196,126 @@ async function save() {
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NDrawer v-model:show="visible" :width="820" :mask-closable="false" placement="right">
|
||||
<NDrawerContent :native-scrollbar="false" closable>
|
||||
<template #header>
|
||||
<span>配置覆盖班级</span>
|
||||
<span class="org-drawer__task">{{ taskName }}</span>
|
||||
</template>
|
||||
|
||||
<NAlert v-if="readonly" type="default" :show-icon="false" :bordered="false" class="org-drawer__readonly">
|
||||
任务已{{ readonlyReason }},覆盖范围不可再修改,只能查看。
|
||||
</NAlert>
|
||||
|
||||
<NSpin :show="loading">
|
||||
<div class="org-drawer__panes">
|
||||
<!-- 左:组织树 -->
|
||||
<div class="org-drawer__tree">
|
||||
<div class="org-drawer__pane-title">
|
||||
<!--
|
||||
⚠️ 标题必须整个包在一个元素里:`.org-drawer__pane-title` 是
|
||||
`display:flex + justify-content:space-between`,
|
||||
而 flex 会把**裸文本节点各自变成一个 flex item** ——
|
||||
写「已选 <strong>1</strong> 个班」会变成三个 item 被摊到整行两端,
|
||||
看起来就是"已选 1 个班"这种散开的错乱排版。
|
||||
-->
|
||||
<span>选择班级</span>
|
||||
<span class="org-drawer__pane-hint">只能勾选到班级一层</span>
|
||||
</div>
|
||||
<div class="org-drawer__tree-body">
|
||||
<NTree
|
||||
v-if="treeData.length"
|
||||
v-model:checked-keys="checkedKeys"
|
||||
:data="treeData"
|
||||
checkable
|
||||
:cascade="false"
|
||||
:selectable="false"
|
||||
:default-expand-all="true"
|
||||
block-line
|
||||
/>
|
||||
<NEmpty v-else description="还没有班级,请先在「组织架构」里建班级" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右:已选班级 -->
|
||||
<div class="org-drawer__list">
|
||||
<div class="org-drawer__pane-title">
|
||||
<span>已选 <strong>{{ rows.length }}</strong> 个班</span>
|
||||
<span class="org-drawer__pane-hint">初审人留空 = 由该班负责人初审</span>
|
||||
</div>
|
||||
|
||||
<NEmpty v-if="!rows.length" description="左侧勾选本次收集涉及的班级" />
|
||||
|
||||
<div v-for="row in rows" :key="row.orgId" class="org-drawer__row">
|
||||
<div class="org-drawer__row-head">
|
||||
<span class="org-drawer__org">{{ orgName(row.orgId) }}</span>
|
||||
<NButton v-if="!readonly" text size="tiny" type="error" @click="removeRow(row)">
|
||||
移除
|
||||
</NButton>
|
||||
</div>
|
||||
|
||||
<div class="org-drawer__fields">
|
||||
<div class="org-drawer__field org-drawer__field--head">
|
||||
<div class="org-drawer__label">初审人(班主任)</div>
|
||||
<NSelect
|
||||
v-model:value="row.headUserId"
|
||||
size="small"
|
||||
clearable
|
||||
placeholder="留空 = 取班级负责人"
|
||||
:options="teacherSelectOptions"
|
||||
:disabled="readonly"
|
||||
/>
|
||||
<div v-if="!row.headUserId" class="org-drawer__fallback">
|
||||
{{ leaderHint(row.orgId) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="org-drawer__field org-drawer__field--count">
|
||||
<div class="org-drawer__label">应填人数</div>
|
||||
<NInputNumber
|
||||
v-model:value="row.expectedCount"
|
||||
size="small"
|
||||
placeholder="未设置"
|
||||
:min="0"
|
||||
:disabled="readonly"
|
||||
/>
|
||||
<div class="org-drawer__fallback">
|
||||
留空表示不比对,填了才与名册比
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</NSpin>
|
||||
|
||||
<template #footer>
|
||||
<NSpace justify="end" :size="8">
|
||||
<NButton :disabled="saving" @click="close">
|
||||
取消
|
||||
</NButton>
|
||||
<NButton type="primary" :loading="saving" :disabled="readonly" @click="save">
|
||||
保存
|
||||
</NButton>
|
||||
</NSpace>
|
||||
</template>
|
||||
</NDrawerContent>
|
||||
</NDrawer>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.org-drawer {
|
||||
&__task {
|
||||
margin-left: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
color: var(--color-text-3);
|
||||
color: var(--xt-text-3);
|
||||
}
|
||||
|
||||
&__readonly {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
&__body {
|
||||
display: block;
|
||||
min-height: 420px;
|
||||
}
|
||||
|
||||
&__panes {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
@@ -290,12 +325,11 @@ defineExpose({ open })
|
||||
flex: none;
|
||||
width: 250px;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--color-border-2);
|
||||
border: 1px solid var(--xt-card-border);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&__tree-spin {
|
||||
display: block;
|
||||
&__tree-body {
|
||||
max-height: 520px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
@@ -312,20 +346,22 @@ defineExpose({ open })
|
||||
margin-bottom: 10px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-2);
|
||||
color: var(--xt-text);
|
||||
}
|
||||
|
||||
&__pane-hint {
|
||||
font-size: 11px;
|
||||
font-weight: 400;
|
||||
color: var(--color-text-3);
|
||||
color: var(--xt-text-3);
|
||||
}
|
||||
|
||||
&__row {
|
||||
padding: 10px 12px;
|
||||
margin-bottom: 10px;
|
||||
background: var(--color-fill-1);
|
||||
border-radius: 4px;
|
||||
/* 抽屉里的"卡片内小格子":浅灰底 + 弱描边(见 styles/index.scss 的卡片式规矩) */
|
||||
background: var(--xt-band-bg);
|
||||
border: 1px solid var(--xt-card-border-weak);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
&__row-head {
|
||||
@@ -337,24 +373,37 @@ defineExpose({ open })
|
||||
|
||||
&__org {
|
||||
font-weight: 500;
|
||||
color: var(--color-text-1);
|
||||
color: #1f2229;
|
||||
}
|
||||
|
||||
&__fields {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
&__field {
|
||||
&--head {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
&--count {
|
||||
flex: none;
|
||||
width: 160px;
|
||||
}
|
||||
}
|
||||
|
||||
&__label {
|
||||
margin-bottom: 4px;
|
||||
font-size: 12px;
|
||||
color: var(--color-text-3);
|
||||
color: var(--xt-text-3);
|
||||
}
|
||||
|
||||
&__fallback {
|
||||
margin-top: 3px;
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
color: var(--color-text-3);
|
||||
}
|
||||
|
||||
&__num {
|
||||
width: 100%;
|
||||
color: var(--xt-text-3);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user