议题优化

This commit is contained in:
李鹏宇
2026-08-20 18:16:28 +08:00
parent 690306fc4d
commit d2bcc07f81
3 changed files with 185 additions and 58 deletions
+114 -1
View File
@@ -6,4 +6,117 @@
.list_room_width2{
width: 120px !important;
max-width: 120px !important;
}
}
/* ===== 议题标题自动换行(room.booking 内嵌议题树) ===== */
/*
关键发现(调试后总结):
1. Odoo list 视图字段的 style 属性【不会】应用到单元格(list_renderer 只把字段 class 推到 <td>),
所以 <field style="..."> 直接死代码,写了等于没写。
2. 列宽由 <th> 决定,list 中字段的 class 同时落到 th 和 td(class = o_<widget>_cell),
因此可以同时锁表头和数据单元格的最大宽度。
3. many2one 显示态 DOM 是 <div class="o_field_many2one"><a class="o_form_uri"><span>标题</span></a></div>,
默认 display: inline-flex + 内嵌 nowrap。
4. 一旦有宽度约束,white-space:normal + word-break 即可让 inline 元素内的文字自然折行,
【不需要】把元素强制 block——display:block 反而会撑高每行很多空白。
修法(纯样式,零逻辑影响):
- 给议题列的 th/td 同时锁 max-width 320px(该类名仅 issue widget 使用,不会误伤其他列)
- 给最深的 <a>/<span> 加 white-space:normal + word-break,override Odoo 默认的 nowrap
- 保持行高/内边距走 Odoo 默认,不破坏表格视觉
*/
/* 锁列宽:议题列 - 用 !important 强制列宽生效 */
.o_issue_m2o_confirm_create_cell {
max-width: 320px !important;
width: 320px !important;
}
/* 强制换行 + 全面剥离 chip 容器样式:覆盖 Odoo 默认的 o-text-overflow mixin
以及 editable list 中 o_field_many2one_selection 的 input 框样式。
用 * 选择器对所有子元素都生效,确保不漏任何一层。 */
.o_issue_m2o_confirm_create_cell,
.o_issue_m2o_confirm_create_cell *,
.o_issue_m2o_confirm_create_cell .o_field_widget,
.o_issue_m2o_confirm_create_cell .o_field_many2one,
.o_issue_m2o_confirm_create_cell .o_field_many2one_selection,
.o_issue_m2o_confirm_create_cell .o_form_uri,
.o_issue_m2o_confirm_create_cell .o_form_uri > span,
.o_issue_m2o_confirm_create_cell a,
.o_issue_m2o_confirm_create_cell span,
.o_issue_m2o_confirm_create_cell input {
white-space: normal !important;
word-break: break-word !important;
overflow-wrap: break-word !important;
overflow: visible !important;
text-overflow: clip !important;
/* 全面去除可能产生"容器外观"的样式(边框/背景/圆角/阴影/内边距) */
background: transparent !important;
background-color: transparent !important;
border: 0 !important;
border-color: transparent !important;
border-style: none !important;
border-radius: 0 !important;
box-shadow: none !important;
outline: 0 !important;
padding: 0 !important;
margin: 0 !important;
}
/* 把 <a> 改为 display:contents,避开 inline-block 撑出的 chip-like 块盒;
让它对布局"透明",只贡献文字内容,避免任何视觉容器。 */
.o_issue_m2o_confirm_create_cell a {
display: contents !important;
}
/* 兜底:保证 td 自身不被任意内容撑高 */
.o_issue_m2o_confirm_create_cell {
line-height: normal !important;
vertical-align: middle;
}
/* ===== 会议室预定 form 默认折叠的"详细信息"块 ===== */
.o_inline_details {
border: 1px solid #e5e7eb;
border-radius: 6px;
background: #f9fafb;
padding: 0;
}
.o_inline_details_summary {
list-style: none;
cursor: pointer;
padding: 10px 14px;
border-radius: 6px 6px 0 0;
user-select: none;
background: #f3f4f6;
transition: background 0.15s ease;
}
.o_inline_details_summary:hover {
background: #e5e7eb;
}
.o_inline_details_summary::-webkit-details-marker {
display: none; /* 隐藏默认三角 */
}
.o_inline_details_summary::before {
content: '\25B8'; /* 右侧小三角 ▶ */
display: inline-block;
margin-right: 8px;
transition: transform 0.15s ease;
color: #6b7280;
font-size: 12px;
}
.o_inline_details[open] > .o_inline_details_summary::before {
transform: rotate(90deg); /* 展开时旋转 90° */
}
.o_inline_details[open] > .o_inline_details_summary {
border-radius: 6px 6px 0 0;
border-bottom: 1px solid #e5e7eb;
}
.o_inline_details > .o_inline_details_summary + * {
padding: 12px 14px;
}
.o_room_booking_more_info .o_field_widget {
margin-bottom: 4px !important; /* 字段之间更紧凑 */
}
.o_room_booking_core_fields .o_field_widget {
margin-bottom: 6px !important; /* 核心字段更宽松一点以便阅读 */
}
+60 -55
View File
@@ -151,67 +151,76 @@
<field name="urgency_level" readonly="1"/>
</group>
</group>
<div class="col-12 text-center">
<h1>
<field name="name_title" readonly="1"/>
</h1>
</div>
<!-- 标题 -->
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name" required="1" string="标题"/>
</h1>
<h1>
<field name="name" required="1" string="标题" placeholder="例如:2026-08-11 党总支部党员大会"/>
</h1>
</div>
<group col="2">
<group>
<!-- 核心三字段:会议时间 / 会议地点 / 会议类型(始终可见,主区域显示) -->
<group col="3" class="o_field_highlight o_room_booking_core_fields">
<group string="会议时间">
<field name="start_datetime" string="会议时间" widget="daterange"
options="{'end_date_field': 'stop_datetime'}"/>
<field name="stop_datetime" invisible="1"/>
<field name="start_datetime" string="会议时间" widget="daterange"
options="{'end_date_field': 'stop_datetime'}"/>
</group>
<group/>
</group>
<group>
<group>
<field name="user_id" invisible="1"/>
<field name="state" invisible="1"/>
<field name="is_back" invisible="1"/>
<field name="work_end" invisible="1"/>
<field name="organizer_id" options="{'no_create': True}"/>
<field name="meeting_type"/>
<field name="driver" invisible="meeting_type != 'exterior'"/>
<field name="fleet_id" invisible="meeting_type != 'exterior'"/>
<field name="meeting_place" invisible="meeting_type != 'exterior'"/>
<group string="会议地点">
<field name="room_id" string="会议地点" domain=""/>
</group>
<group>
<field name="department_id" widget="ztree_select" options="{'no_create': True}"/>
<field name="company_id" invisible="1"/>
<field name="meeting_type_id" required="1" domain="[('company_id', '=', company_id)]" options="{'no_create': True}"/>
<group string="会议类型">
<field name="meeting_type_id" required="1"
domain="[('company_id', '=', company_id)]"
options="{'no_create': True}"/>
</group>
</group>
<group col="2">
<group>
<field name="host" domain = "[('company_id', '=', company_id), ('user_id.name', '!=', 'Administrator')] if is_this_company else []" options="{'no_create': True}"/>
<!-- 其他次要字段折叠:使用 HTML5 <details> 默认收起。注意:open 是布尔属性,写 open="false" 也会展开,必须整段不写 open 才默认折叠 -->
<details class="o_inline_details mb-3">
<summary class="o_inline_details_summary">
<i class="fa fa-info-circle me-1"/>
<strong>详细信息</strong>
<span class="text-muted small ms-2">(默认折叠,点击展开:组织者、部门、参会人员、通知等)</span>
</summary>
<group col="2" class="o_room_booking_more_info">
<group string="组织与会议形式">
<!-- 隐藏字段 -->
<field name="user_id" invisible="1"/>
<field name="state" invisible="1"/>
<field name="is_back" invisible="1"/>
<field name="work_end" invisible="1"/>
<field name="company_id" invisible="1"/>
<field name="is_meeting" invisible="1"/>
<field name="partner_ids" widget="many2many_tags" force_save="1" invisible="1"/>
<field name="is_notice" invisible="1"/>
<!-- 可见字段 -->
<field name="organizer_id" options="{'no_create': True}"/>
<field name="department_id" widget="ztree_select" options="{'no_create': True}"/>
<field name="meeting_type"/>
<field name="driver" invisible="meeting_type != 'exterior'"/>
<field name="fleet_id" invisible="meeting_type != 'exterior'"/>
<field name="meeting_place" invisible="meeting_type != 'exterior'"/>
<field name="host"
domain="[('company_id', '=', company_id), ('user_id.name', '!=', 'Administrator')] if is_this_company else []"
options="{'no_create': True}"/>
<label for="stationed_group"/>
<div><field name="stationed_group"/></div>
<field name="other_company_user_ids" widget="many2many_tags" readonly="0"/>
</group>
<group string="参会与通知">
<field name="room_users_ids" widget="many2many_tags"
domain="[('company_id', '=', company_id), ('name', '!=', 'Administrator')] if is_this_company else []"
options="{'no_create': True}"/>
<field name="recorder_ids" widget="many2many_tags"
domain="[('user_role_ids.name', 'ilike', '会议记录员')]"
options="{'no_create': True}"/>
<label for="is_notice"/>
<div><field name="is_notice"/></div>
<label for="task_time_ids" invisible="not is_notice"/>
<div><field name="task_time_ids" invisible="not is_notice" widget="many2many_tags"/></div>
</group>
</group>
<group/>
</group>
<group>
<label for="stationed_group"/>
<div><field name="stationed_group"/></div>
</group>
<group>
<field name="room_users_ids" widget="many2many_tags" domain = "[('company_id', '=', company_id), ('name', '!=', 'Administrator')] if is_this_company else []" options="{'no_create': True}"/>
<field name="recorder_ids" widget="many2many_tags" domain="[('user_role_ids.name', 'ilike', '会议记录员')]" options="{'no_create': True}"/>
<field name="other_company_user_ids" widget="many2many_tags" readonly="0"/>
<field name="partner_ids" widget="many2many_tags" force_save="1" invisible="1"/>
<field name="is_meeting" invisible="1"/>
</group>
<group>
<label for="is_notice"/>
<div><field name="is_notice"/></div>
<label for="task_time_ids" invisible="not is_notice"/>
<div><field name="task_time_ids" invisible="not is_notice" widget="many2many_tags"/></div>
</group>
</details>
<!-- 签到详情/会议说明/附件 折叠为 notebook,notebook 默认折叠为 tab 形式 -->
<notebook>
<page name="sign" string="签到详情">
<group>
@@ -244,10 +253,6 @@
</page>
</notebook>
</sheet>
<!-- <div class="oe_chatter">-->
<!-- <field name="message_follower_ids"/>-->
<!-- <field name="message_ids"/>-->
<!-- </div>-->
</form>
</field>
</record>
+11 -2
View File
@@ -29,14 +29,23 @@
<button name="open_record" type="object" string="详情" class="oe_highlight"/>
<field name="sequence" widget="handle"/>
<field name="meeting_booking_id" column_invisible="1"/>
<field name="issue_library_id" class="o_m2o_mutil_line" widget="issue_m2o_confirm_create"/>
<!-- 议题标题列:列宽 + 换行双保险
说明:Odoo list 视图只有同时配 options + width 才把 width 当作绝对列宽(第 1965 行):
https://github.com/odoo/odoo/blob/17.0/addons/web/static/src/views/list/list_renderer.js
因此给议题字段同时配 options + width 来锁列宽;
CSS 再用 widget 独有的类名加 white-space 换行(不依赖 display:block,避免撑高单元格)。 -->
<field name="issue_library_id"
class="o_agenda_title_wrap"
options="{'width': '320px'}"
width="320px"
widget="issue_m2o_confirm_create"/>
<field name="employee_id" options="{'no_create': True}"/>
<field name="attendees_ids" widget="many2many_tags" options="{'no_create': True}"/>
<field name="users_role_group_ids" widget="many2many_tags" options="{'no_create': True}"/>
<field name="designated_person_ids" widget="many2many_tags" column_invisible="1"/>
<field name="is_sanda"/>
<field name="decision_results"/>
<field name="decision_details"/>
<field name="decision_details" class="o_agenda_title_wrap"/>
</tree>
</field>
</page>