Browse Source

工具页面样式修改2.0

mh
hanyuqing 3 months ago
parent
commit
33a8d8034a
  1. 42
      controller/GraphStyleController.py
  2. 107
      service/GraphStyleService.py
  3. 35
      vue/src/api/style.js
  4. 293
      vue/src/system/GraphStyle.vue

42
controller/GraphStyleController.py

@ -25,7 +25,7 @@ async def save_style_config(request):
canvas_name = body.get('canvas_name')
current_label = body.get('current_label')
styles = body.get('styles')
# 新增:接收分组名称(字符串)
# 接收分组名称(字符串)
group_name = body.get('group_name')
if not all([canvas_name, current_label, styles]):
@ -45,13 +45,51 @@ async def save_style_config(request):
async def get_grouped_style_list(request):
"""获取【分组嵌套】格式的配置列表(用于右侧折叠面板)"""
try:
# 调用 Service 的嵌套聚合方法
# 调用 Service 的嵌套聚合方法,现在内部已包含 is_active/is_default 逻辑
data = GraphStyleService.get_grouped_configs()
return create_response(200, {"code": 200, "data": data, "msg": "查询成功"})
except Exception as e:
return create_response(200, {"code": 500, "msg": f"查询异常: {str(e)}"})
@app.post("/api/graph/style/group/apply")
async def apply_style_group(request):
"""应用全案:将某个方案组设为当前激活状态"""
try:
body = request.json()
group_id = body.get('group_id')
if not group_id:
return create_response(200, {"code": 400, "msg": "缺少分组ID"})
success = GraphStyleService.apply_group_all(group_id)
if success:
return create_response(200, {"code": 200, "msg": "方案已成功应用全案"})
else:
return create_response(200, {"code": 500, "msg": "应用全案失败"})
except Exception as e:
return create_response(200, {"code": 500, "msg": f"操作异常: {str(e)}"})
@app.post("/api/graph/style/group/set_default")
async def set_default_style_group(request):
"""设为默认:将某个方案组设为页面初始化的默认配置"""
try:
body = request.json()
group_id = body.get('group_id')
if not group_id:
return create_response(200, {"code": 400, "msg": "缺少分组ID"})
success = GraphStyleService.set_default_group(group_id)
if success:
return create_response(200, {"code": 200, "msg": "已成功设为系统默认方案"})
else:
return create_response(200, {"code": 500, "msg": "设置默认方案失败"})
except Exception as e:
return create_response(200, {"code": 500, "msg": f"操作异常: {str(e)}"})
@app.get("/api/graph/style/groups")
async def get_group_names(request):
"""获取所有已存在的方案组列表(用于保存弹窗的下拉选择)"""

107
service/GraphStyleService.py

@ -2,15 +2,12 @@
import json
from util.mysql_utils import mysql_client
class GraphStyleService:
@staticmethod
def save_config(canvas_name: str, current_label: str, styles_dict: dict, group_name: str = None) -> bool:
"""
保存图谱样式配置增强版自动处理分组逻辑
:param canvas_name: 画布显示名称
:param current_label: 针对的标签名称
:param styles_dict: 样式字典
:param group_name: 分组名称前端传来的字符串
"""
# 1. 处理分组逻辑:查不到就建,查到了就用
if not group_name or group_name.strip() == "":
@ -21,13 +18,12 @@ class GraphStyleService:
existing_group = mysql_client.execute_query(check_group_sql, (group_name,))
if existing_group:
# 如果存在,直接使用已有 ID
target_group_id = existing_group[0]['id']
else:
# 如果不存在,新建一个组
create_group_sql = "INSERT INTO graph_style_groups (group_name) VALUES (%s)"
mysql_client.execute_update(create_group_sql, (group_name,))
# 获取新生成的 ID
# 如果不存在,新建一个组(is_active 和 is_default 默认为 false)
create_group_sql = "INSERT INTO graph_style_groups (group_name, is_active, is_default) VALUES (%s, %s, %s)"
mysql_client.execute_update(create_group_sql, (group_name, False, False))
get_id_sql = "SELECT LAST_INSERT_ID() as last_id"
id_res = mysql_client.execute_query(get_id_sql)
target_group_id = id_res[0]['last_id'] if id_res else 1
@ -35,7 +31,7 @@ class GraphStyleService:
# 2. 转换样式 JSON
config_json = json.dumps(styles_dict, ensure_ascii=False)
# 3. 插入配置表(关联 target_group_id)
# 3. 插入配置表
sql = """
INSERT INTO graph_configs (canvas_name, current_label, config_json, group_id)
VALUES (%s, %s, %s, %s)
@ -46,19 +42,22 @@ class GraphStyleService:
@staticmethod
def get_grouped_configs() -> list:
"""
核心优化获取嵌套结构的方案列表 (Group -> Configs)
用于前端右侧折叠面板展示
核心优化获取嵌套结构的方案列表
增加 is_active is_default 字段支持并按默认/激活状态排序
"""
# 1. 查询所有方案组:让默认方案排在最上面
groups_sql = """
SELECT id, group_name, is_active, is_default
FROM graph_style_groups
ORDER BY is_default DESC, id ASC
"""
# 1. 查询所有方案组
groups_sql = "SELECT id, group_name FROM graph_style_groups ORDER BY id ASC"
groups = mysql_client.execute_query(groups_sql) or []
# 2. 查询所有配置项
configs_sql = "SELECT id, group_id, canvas_name, current_label, config_json, create_time FROM graph_configs"
configs = mysql_client.execute_query(configs_sql) or []
# 3. 内存聚合:将配置项塞进对应的组
# 先处理配置项的 JSON 和 时间
# 3. 内存聚合
for conf in configs:
if conf.get('config_json'):
try:
@ -73,41 +72,88 @@ class GraphStyleService:
# 组装数据结构
result = []
for g in groups:
# 兼容 MySQL 布尔值转换 (某些驱动返回 0/1)
g['is_active'] = bool(g['is_active'])
g['is_default'] = bool(g['is_default'])
# 找到属于该组的所有配置
g_children = [c for c in configs if c['group_id'] == g['id']]
g['configs'] = g_children
# 增加一个前端控制开关用的字段
g['expanded'] = False
# 如果是激活状态,默认让它在前端展开
g['expanded'] = g['is_active']
result.append(g)
return result
@staticmethod
def apply_group_all(group_id: int) -> bool:
"""
核心新增应用全案
逻辑将该组设为 is_active=true其余所有组设为 false
"""
try:
# 1. 全部重置为非激活
reset_sql = "UPDATE graph_style_groups SET is_active = %s"
mysql_client.execute_update(reset_sql, (False,))
# 2. 激活指定组
apply_sql = "UPDATE graph_style_groups SET is_active = %s WHERE id = %s"
affected_rows = mysql_client.execute_update(apply_sql, (True, group_id))
return affected_rows > 0
except Exception as e:
print(f"Apply group error: {e}")
return False
@staticmethod
def set_default_group(group_id: int) -> bool:
"""
核心新增设为系统初始默认方案
逻辑唯一性切换
"""
try:
# 1. 全部取消默认
reset_sql = "UPDATE graph_style_groups SET is_default = %s"
mysql_client.execute_update(reset_sql, (False,))
# 2. 设置新的默认项
set_sql = "UPDATE graph_style_groups SET is_default = %s WHERE id = %s"
affected_rows = mysql_client.execute_update(set_sql, (True, group_id))
return affected_rows > 0
except Exception as e:
print(f"Set default error: {e}")
return False
@staticmethod
def get_all_configs() -> list:
"""保持原有的扁平查询功能,仅增加 group_id 字段返回"""
sql = "SELECT id, group_id, canvas_name, current_label, config_json, create_time FROM graph_configs ORDER BY create_time DESC"
"""获取扁平查询,增加关联方案的激活状态"""
sql = """
SELECT c.id, c.group_id, c.canvas_name, c.current_label, c.config_json, c.create_time, g.is_active
FROM graph_configs c
LEFT JOIN graph_style_groups g ON c.group_id = g.id
ORDER BY c.create_time DESC
"""
rows = mysql_client.execute_query(sql)
if not rows: return []
for row in rows:
if row.get('config_json'):
try: row['styles'] = json.loads(row['config_json'])
except: row['styles'] = {}
try:
row['styles'] = json.loads(row['config_json'])
except:
row['styles'] = {}
del row['config_json']
if row.get('create_time') and not isinstance(row['create_time'], str):
row['create_time'] = row['create_time'].strftime('%Y-%m-%d %H:%M:%S')
row['is_active'] = bool(row.get('is_active', False))
return rows
@staticmethod
def delete_group(group_id: int) -> bool:
"""
逻辑级联删除删除方案组及其关联的所有配置
"""
# 1. 删除组下的所有配置
"""逻辑级联删除"""
del_configs_sql = "DELETE FROM graph_configs WHERE group_id = %s"
mysql_client.execute_update(del_configs_sql, (group_id,))
# 2. 删除组本身
del_group_sql = "DELETE FROM graph_style_groups WHERE id = %s"
affected_rows = mysql_client.execute_update(del_group_sql, (group_id,))
return affected_rows > 0
@ -125,7 +171,8 @@ class GraphStyleService:
if not config_ids: return 0
try:
clean_ids = [int(cid) for cid in config_ids if str(cid).isdigit()]
except: return 0
except:
return 0
if not clean_ids: return 0
placeholders = ', '.join(['%s'] * len(clean_ids))
@ -134,6 +181,6 @@ class GraphStyleService:
@staticmethod
def get_group_list() -> list:
"""单独获取方案名称列表,供前端下拉框使用"""
sql = "SELECT id, group_name FROM graph_style_groups ORDER BY create_time DESC"
"""单独获取方案列表,增加状态返回"""
sql = "SELECT id, group_name, is_active, is_default FROM graph_style_groups ORDER BY is_default DESC, create_time DESC"
return mysql_client.execute_query(sql) or []

35
vue/src/api/style.js

@ -18,8 +18,9 @@ export function saveGraphStyle(data) {
}
/**
* 获取分组嵌套格式的样式配置列表 (核心新增)
* 获取分组嵌套格式的样式配置列表
* 用于右侧折叠面板渲染Group -> Configs
* 后端已按 is_default 排序并将 is_active 的项标记为 expanded
*/
export function getGroupedGraphStyleList() {
return request({
@ -29,6 +30,38 @@ export function getGroupedGraphStyleList() {
}
/**
* 应用全案
* @param {Number} group_id 分组ID
* 说明将该方案组设为 is_active=true其余设为 false
*/
export function applyGraphStyleGroup(group_id) {
return request({
url: '/api/graph/style/group/apply',
method: 'post',
data: { group_id },
headers: {
'Content-Type': 'application/json'
}
});
}
/**
* 设为默认方案
* @param {Number} group_id 分组ID
* 说明将该方案组设为系统初始加载时的默认配置
*/
export function setDefaultGraphStyleGroup(group_id) {
return request({
url: '/api/graph/style/group/set_default',
method: 'post',
data: { group_id },
headers: {
'Content-Type': 'application/json'
}
});
}
/**
* 获取所有已存在的方案组名称列表
* 用于保存配置弹窗中的下拉选择框
*/

293
vue/src/system/GraphStyle.vue

@ -199,11 +199,10 @@
style="margin-right: 8px;"/>
<span class="group-name-text">
{{ group.group_name }}
<span v-if="isGroupFullyApplied(group)" style="color: #1559f3; font-size: 10px; margin-left: 5px;">(已应用全案)</span>
</span>
<el-button
v-if="!isGroupFullyApplied(group)"
v-if="!group.is_active"
size="small"
type="primary"
plain
@ -213,8 +212,9 @@
v-else
size="small"
type="info"
disabled
plain
@click.stop="cancelWholeGroup(group)">取消全案
@click.stop>已应用
</el-button>
<i class="el-icon-delete group-del" @click.stop="deleteGroup(group.id)"></i>
@ -303,15 +303,18 @@ import {
getGraphStyleGroups,
deleteGraphStyle,
batchDeleteGraphStyle,
deleteGraphStyleGroup
deleteGraphStyleGroup,
applyGraphStyleGroup //
} from '@/api/style';
import {ElMessageBox, ElMessage} from 'element-plus';
import {markRaw} from 'vue';
const tagToLabelMap = {
'疾病': 'Disease', '症状': 'Symptom', '病因': 'Cause', '药品': 'Drug', '科室': 'Department', '检查': 'Check','其他':'Other'
'疾病': 'Disease', '症状': 'Symptom', '病因': 'Cause', '药品': 'Drug', '科室': 'Department', '检查': 'Check', '其他': 'Other'
};
const CORE_LABELS = ['Disease', 'Symptom', 'Drug', 'Check'];
const INITIAL_FILL_MAP = {
'Disease': '#EF4444', 'Drug': '#91cc75', 'Symptom': '#fac858', 'Check': '#336eee',
'Cause': '#59d1d4', 'Department': '#59d1d4', 'Other': '#59d1d4'
@ -361,7 +364,7 @@ export default {
edgeFontColor: '#666666',
edgeType: 'line',
edgeLineWidth: 2,
edgeStroke: '#EF4444', //
edgeStroke: '#EF4444',
defaultData: {
nodes: [
{id: "node1", data: {name: "霍乱", label: "Disease"}},
@ -392,23 +395,17 @@ export default {
}
},
watch: {
//
checkedGroupIds(newGroupIds) {
//
this.styleGroups.forEach(group => {
const isGroupChecked = newGroupIds.includes(group.id);
const childIds = group.configs.map(c => c.id);
if (isGroupChecked) {
// ID checkedConfigIds ()
this.checkedConfigIds = Array.from(new Set([...this.checkedConfigIds, ...childIds]));
} else {
// ID checkedConfigIds
this.checkedConfigIds = this.checkedConfigIds.filter(id => !childIds.includes(id));
}
});
},
// 线
nodeFill(newVal) {
this.edgeStroke = newVal;
},
@ -481,7 +478,7 @@ export default {
nodeShape: 'circle', nodeSize: 60, nodeFill: fill,
nodeStroke: INITIAL_STROKE_MAP[label] || '#40999b', nodeLineWidth: 2, edgeShowLabel: true, edgeEndArrow: true,
edgeFontFamily: 'Microsoft YaHei, sans-serif', edgeFontSize: 10, edgeFontColor: '#666666', edgeType: 'line',
edgeLineWidth: 2, edgeStroke: fill // 线
edgeLineWidth: 2, edgeStroke: fill
};
},
handleTagClick(tag) {
@ -518,8 +515,12 @@ export default {
this._graph = markRaw(graph);
this.updateAllElements();
},
getEffectiveStyleKey(label) {
return CORE_LABELS.includes(label) ? label : 'Other';
},
updateAllElements() {
if (!this._graph) return;
const labelToAppliedConfigMap = {};
this.styleGroups.forEach(group => {
group.configs.forEach(conf => {
@ -538,8 +539,10 @@ export default {
};
const nodes = this.defaultData.nodes.map(node => {
const labelEn = node.data?.label || '';
const s = labelToAppliedConfigMap[labelEn] || this.tagStyles[labelEn];
const rawLabel = node.data?.label || '';
const effectiveKey = this.getEffectiveStyleKey(rawLabel);
const s = labelToAppliedConfigMap[effectiveKey] || this.tagStyles[effectiveKey];
return {
...node, type: s?.nodeShape || 'circle',
style: {
@ -553,13 +556,11 @@ export default {
});
const edges = this.defaultData.edges.map(edge => {
const sLabel = this._nodeLabelMap.get(edge.source);
//
const s = labelToAppliedConfigMap[sLabel] || this.tagStyles[sLabel] || this;
const sRawLabel = this._nodeLabelMap.get(edge.source);
const effectiveKey = this.getEffectiveStyleKey(sRawLabel);
const s = labelToAppliedConfigMap[effectiveKey] || this.tagStyles[effectiveKey] || this;
// 线 edgeStroke
const strokeColor = hexToRgba(s.edgeStroke, 0.6);
return {
...edge, type: s.edgeType || 'line',
style: {
@ -589,10 +590,28 @@ export default {
const res = await getGroupedGraphStyleList();
if (res.code === 200) {
this.styleGroups = res.data.map(group => ({
...group, configs: group.configs.map(conf => ({
...conf, styles: typeof conf.styles === 'string' ? JSON.parse(conf.styles) : conf.styles
...group,
configs: group.configs.map(conf => ({
...conf,
styles: typeof conf.styles === 'string' ? JSON.parse(conf.styles) : conf.styles
}))
}));
// --- ---
this.activeCollapseNames = [];
this.usingConfigIds = [];
this.styleGroups.forEach(group => {
if (group.is_active) {
// 1.
this.activeCollapseNames.push(group.id);
// 2.
const ids = group.configs.map(c => c.id);
this.usingConfigIds = [...this.usingConfigIds, ...ids];
}
});
this.updateAllElements();
}
} catch (err) {
console.error("加载配置失败:", err);
@ -607,6 +626,7 @@ export default {
if (idx > -1) {
this.usingConfigIds.splice(idx, 1);
} else {
//
this.styleGroups.forEach(g => {
g.configs.forEach(c => {
if (this.usingConfigIds.includes(c.id) && c.current_label === item.current_label) {
@ -618,47 +638,48 @@ export default {
}
this.updateAllElements();
},
applyWholeGroup(group) {
const idsToApply = group.configs.map(c => c.id);
group.configs.forEach(conf => {
this.styleGroups.forEach(g => {
g.configs.forEach(c => {
if (c.current_label === conf.current_label) this.usingConfigIds = this.usingConfigIds.filter(id => id !== c.id);
});
});
});
this.usingConfigIds = Array.from(new Set([...this.usingConfigIds, ...idsToApply]));
this.updateAllElements();
ElMessage.success(`方案【${group.group_name}】已应用`);
},
cancelWholeGroup(group) {
const idsToCancel = group.configs.map(c => c.id);
this.usingConfigIds = this.usingConfigIds.filter(id => !idsToCancel.includes(id));
this.updateAllElements();
},
isGroupFullyApplied(group) {
if (!group.configs || group.configs.length === 0) return false;
return group.configs.every(c => this.usingConfigIds.includes(c.id));
async applyWholeGroup(group) {
try {
// 1.
const res = await applyGraphStyleGroup(group.id);
if (res.code === 200) {
// 2. fetchConfigs usingConfigIds expanded
await this.fetchConfigs();
ElMessage.success(`方案【${group.group_name}】已成功应用全案`);
}
} catch (err) {
ElMessage.error("应用全案失败");
}
},
handleSaveClick() {
this.fetchGroupNames();
// 使 Date.now() 13
this.saveForm.canvas_name = Date.now().toString();
this.saveDialogVisible = true;
},
async confirmSave() {
const payload = {
canvas_name: this.saveForm.canvas_name, group_name: this.saveForm.group_name, current_label: this.activeTags,
canvas_name: this.saveForm.canvas_name,
group_name: this.saveForm.group_name,
current_label: this.activeTags,
styles: {...this.tagStyles[tagToLabelMap[this.activeTags]]}
};
const res = await saveGraphStyle(payload);
if (res.code === 200) {
ElMessage.success("保存成功");
this.saveDialogVisible = false;
this.resetAllTagsToDefault();
this.fetchConfigs();
}
},
resetAllTagsToDefault() {
Object.keys(this.tagStyles).forEach(labelKey => {
this.tagStyles[labelKey] = this.getInitialTagParams(labelKey);
});
this.activeTags = '疾病';
const diseaseInitial = this.getInitialTagParams('Disease');
Object.assign(this, diseaseInitial);
this.updateAllElements();
},
resetStyle() {
const labelEn = tagToLabelMap[this.activeTags];
const initial = this.getInitialTagParams(labelEn);
@ -669,7 +690,7 @@ export default {
},
async deleteSingleConfig(id) {
try {
await ElMessageBox.confirm('确定删除此配置吗?');
await ElMessageBox.confirm('确定删除此配置吗?', '提示');
const res = await deleteGraphStyle(id);
if (res.code === 200) {
this.usingConfigIds = this.usingConfigIds.filter(cid => cid !== id);
@ -680,7 +701,7 @@ export default {
},
async deleteGroup(groupId) {
try {
await ElMessageBox.confirm('确定删除整个方案吗?');
await ElMessageBox.confirm('确定删除整个方案吗?', '提示');
const res = await deleteGraphStyleGroup(groupId);
if (res.code === 200) {
this.fetchConfigs();
@ -692,13 +713,11 @@ export default {
try {
await ElMessageBox.confirm(
'确定执行批量删除吗?',
'批量删除', //
'批量删除',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
//
distinguishCancelAndClose: true,
type: 'warning'
}
);
for (const gid of this.checkedGroupIds) await deleteGraphStyleGroup(gid);
@ -718,7 +737,6 @@ export default {
}
}
</script>
<style scoped>
/* 精准控制“应用全案”按钮 */
@ -754,14 +772,14 @@ export default {
}
.control-panel {
scrollbar-width: none !important; /* Firefox */
-ms-overflow-style: none !important; /* IE */
scrollbar-width: none !important;
-ms-overflow-style: none !important;
}
.knowledge-graph-container {
display: flex;
height: 100vh;
background-color: #f8fafc;
background-color: #f3f3f3; /* 全局背景改为 f3f3f3 */
overflow: hidden;
}
@ -777,9 +795,9 @@ export default {
}
.config-list-panel {
width: 280px;
width: 320px;
background: #ffffff;
border-left: 1px solid #e2e8f0;
border-left: 1px solid #ffffff;
padding: 18px;
display: flex;
flex-direction: column;
@ -798,11 +816,11 @@ export default {
margin-bottom: 8px;
}
.header-line {
/*.header-line {
height: 1px;
background-color: #e2e8f0;
width: 100%;
}
}*/
.custom-title-style {
font-size: 18px;
@ -810,7 +828,7 @@ export default {
color: #1157f3;
}
/* --- 修改后的标签过滤样式 --- */
/* 标签过滤样式 */
.tag-filters {
display: flex;
flex-wrap: nowrap;
@ -836,15 +854,8 @@ export default {
justify-content: center;
}
.tag-pill:hover {
filter: brightness(1.1);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
}
.tag-pill.is-active {
background-color: #4a68db; /* 选中颜色 */
transform: translateY(-1px);
box-shadow: 0 4px 10px rgba(74, 104, 219, 0.3);
background-color: #4a68db;
}
.section {
@ -921,7 +932,6 @@ export default {
gap: 12px;
}
/* 滑块轨道样式 */
.theme-slider {
-webkit-appearance: none;
appearance: none;
@ -932,7 +942,6 @@ export default {
outline: none;
}
/* 中间的小圆点样式 */
.theme-slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
@ -941,22 +950,8 @@ export default {
background: #1559f3;
border-radius: 50%;
cursor: pointer;
border: none;
box-shadow: none;
}
/* 中间的小圆点样式 */
.theme-slider::-moz-range-thumb {
width: 14px;
height: 14px;
background: #1559f3;
border-radius: 50%;
cursor: pointer;
border: none;
box-shadow: none;
}
/* 右侧数值样式 */
.val-text-black {
color: #000;
font-weight: bold;
@ -1015,90 +1010,120 @@ export default {
flex: 1;
overflow-y: auto;
padding-bottom: 100px;
scrollbar-width: none; /* 针对 Firefox */
-ms-overflow-style: none; /* 针对 IE 和 Edge */
}
:deep(.el-collapse-item__content) {
padding-left: 32px !important;
padding-right: 10px !important;
padding-bottom: 12px !important;
padding-top: 2px !important;
background-color: transparent !important;
}
.config-card {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px;
background: #f8fafc;
margin-bottom: 10px;
border-radius: 8px;
background-color: #f3f3f3 !important;
margin-bottom: 6px;
border-radius: 6px;
cursor: pointer;
border: 1px solid #e2e8f0;
border: none !important;
transition: all 0.2s;
position: relative;
border-bottom: 1px solid #d1d5db !important;
}
.config-card:hover {
border-color: #1559f3;
background-color: #e2e4e6 !important;
}
.card-using {
border-color: #1559f3;
background: #eff6ff !important;
border-width: 1.5px;
background-color: #eff6ff !important;
outline: 1.5px solid #1559f3;
}
.card-checked {
border-left: 4px solid #ef4444;
border-left: 4px solid #ef4444 !important;
}
.card-left {
display: flex;
align-items: flex-start;
flex: 1;
min-width: 0;
}
.checkbox-wrapper {
display: flex;
align-items: center;
justify-content: center;
margin-right: 12px;
padding-right: 8px;
border-right: 1px solid #e2e8f0;
padding-right: 10px;
border-right: 1px solid #d1d5db;
flex-shrink: 0;
height: 20px;
}
.config-checkbox {
width: 18px;
height: 18px;
accent-color: #ef4444;
margin: 0;
cursor: pointer;
}
.card-info {
display: flex;
flex-direction: column;
align-items: flex-start;
flex: 1;
min-width: 0;
gap: 4px;
}
.card-title-row {
display: flex;
align-items: center;
gap: 8px;
line-height: 20px;
}
.card-name {
font-weight: 600;
color: #1e293b;
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-right: 4px;
}
.status-badge {
font-size: 10px;
background: #1559f3;
color: white;
padding: 1px 6px;
border-radius: 10px;
padding: 0px 6px;
border-radius: 4px;
white-space: nowrap;
}
.card-tag {
font-size: 12px;
color: #64748b;
.card-right {
display: flex;
align-items: center;
height: 20px;
margin-left: 10px;
}
.delete-icon {
color: #94a3b8;
padding: 4px;
border-radius: 4px;
}
.delete-icon:hover {
color: #ef4444;
background: #fee2e2;
border-radius: 4px;
}
.batch-actions-fixed {
@ -1108,8 +1133,7 @@ export default {
right: 0;
background: #ffffff;
padding: 15px;
border-top: 2px solid #e2e8f0;
box-shadow: 0 -4px 10px rgba(0, 0, 0, 0.05);
z-index: 10;
display: flex;
flex-direction: column;
gap: 10px;
@ -1138,11 +1162,6 @@ export default {
font-weight: bold;
}
.btn-batch-delete-final:disabled {
background: #fca5a5;
cursor: not-allowed;
}
.btn-clear-selection {
flex: 1;
padding: 10px;
@ -1153,32 +1172,26 @@ export default {
cursor: pointer;
}
.empty-text {
text-align: center;
margin-top: 40px;
color: #94a3b8;
}
.refresh-icon {
cursor: pointer;
color: #94a3b8;
}
.refresh-icon:hover {
color: #1559f3;
}
.group-header-slot {
display: flex;
align-items: center;
width: 100%;
padding-right: 10px;
padding-right: 12px;
flex-wrap: nowrap;
}
.group-name-text {
flex: 1;
font-weight: bold;
color: #334155;
font-weight: 900;
font-size: 16px;
color: #0f172a;
margin-left: 4px;
text-align: left;
}
.group-del {
@ -1186,15 +1199,20 @@ export default {
color: #94a3b8;
}
.group-del:hover {
color: #ef4444;
}
:deep(.el-collapse-item__header) {
padding: 0 10px;
height: 54px;
line-height: 54px;
background-color: #ffffff !important;
border-top: none !important;
}
/* 统一修改所有弹窗和消息框的标题与取消按钮 */
:deep(.el-collapse-item__wrap) {
border-bottom: none;
background-color: transparent !important;
}
/* 统一对话框/消息框 */
:deep(.el-dialog__title),
:deep(.el-message-box__title) {
color: #000000 !important;
@ -1219,10 +1237,10 @@ export default {
</style>
<style>
.el-message-box__header {
text-align: left !important;
padding-top: 15px !important;
}
.el-message-box__header {
text-align: left !important;
padding-top: 15px !important;
}
.el-message-box__title {
color: #000000 !important;
@ -1230,9 +1248,8 @@ export default {
font-size: 18px !important;
}
/* 之前讨论过的按钮颜色也请确保保留在此 */
.el-message-box__btns .el-button--primary {
background-color: #1559f3 !important;
border-color: #1559f3 !important;
}
</style>
</style>
Loading…
Cancel
Save