Compare commits

...

7 Commits

Author SHA1 Message Date
YANG JIANKUAN
00f2dc98dd feat(skill): zentao-bug 新增 assign 命令,支持指派 Bug 并附备注
等同网页「指派」表单:--to 接受账号或姓名,状态保持激活,提交后回读校验指派人;
多行备注用 --comment-file,换行转 <br /> 以便网页分行显示。
SKILL.md 补充用法,约定转给后端时备注照搬《后端接口对接问题清单》对应行。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 11:44:31 +08:00
YANG JIANKUAN
2ff052c6e2 fix(phone): 卡片右上角箭头改为原型灰色
ULD 管理、出港查询、出港仓库、进港查询、进港仓库卡片右上角箭头改为 gray-500
(phone_text_body),出港计重改为 gray-400(phone_text_hint),与各页原型一致。
仅在各卡片布局上加 tint,公共图标 ic_phone_chevron_right 不变;
「查看详情 ›」的蓝色箭头保持原样。

Refs: 禅道 Bug #620

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 11:35:25 +08:00
YANG JIANKUAN
1b6f14da09 fix(gjc): 出港运抵已运抵卡片同样去掉海关放行与运单类型
此前只在「待运抵」隐藏该行,现两个 Tab 都不显示,直接从手机卡片布局移除。

Refs: 禅道 Bug #626

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 11:35:25 +08:00
YANG JIANKUAN
42c0e26bde fix(gjc): 出港运抵卡片无分单也显示「查看分单 0」,分单明细补空态
- 手机卡片「查看分单」按钮始终显示,分单数为空时按 0 显示
- 无分单的运单可进入分单明细页,补「暂无分单」空态,避免整页空白

Refs: 禅道 Bug #631

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 11:29:24 +08:00
YANG JIANKUAN
39b9669a87 fix(gjc): 出港移库编辑页手机卡片按原型重做样式
- 主信息卡去掉蓝色表头,改为白底 + 左侧 3dp 蓝色装饰条(clipToOutline 随圆角裁切)
- 移库信息 / 交接图片 / 补充信息三张分区卡:白底深色标题 + 分割线,替代彩色表头
- 字号、字重、颜色、圆角、描边按「移库编辑」HTML 原型逐项对齐
- 备注行改为本页自有输入行,去掉下划线
- 卡片阴影改用原型的蓝灰半透明色,容器 clipToPadding=false,避免阴影发脏与被截断

只改本页手机布局:页面专用色值与 drawable 以 move_edit_ 前缀放在 module_gjc,
公共颜色、组件与平板布局均未改动。

Refs: 禅道 Bug #632

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 11:29:24 +08:00
YANG JIANKUAN
1488547220 build: autosize 依赖固定为 1.2.1,消除每次构建的动态版本查询
`me.jessyan:autosize:1.2.+` 让 Gradle 每次构建都去所有仓库列版本,
其中私服 118.31.6.84:8081 连接后挂起再返回空响应,失败结果不缓存,
导致无改动构建也要约 7 分钟。固定为本地一直在用的 1.2.1 后,
联网的无改动构建降到 1~2 秒,运行行为不变。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 11:29:24 +08:00
YANG JIANKUAN
d738a4acfe feat(skill): zentao-bug 新增 resolve 命令,支持在禅道解决 Bug
- resolve <id...>:等同网页「解决」表单,默认解决方案 fixed、解决版本 trunk(主干),
  支持 --dry-run 预览;只处理激活状态,提交后回读校验
- 接口提交不会自动补默认值:解决日期与指派给先从解决表单 HTML 读取默认值
  (服务器北京时间 / 创建人)再原样提交,避免用本机时区时间
- SKILL.md 补写回说明,并注明 login 需在独立终端执行(! 前缀无 TTY)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 19:29:08 -07:00
19 changed files with 651 additions and 178 deletions

View File

@@ -1,6 +1,6 @@
---
name: zentao-bug
description: 读取禅道(njlkairport.chandao.net,开源版 18.8)中的 Bug 单——我的 Bug 列表、单个 Bug 的标题/描述/截图/评论/修改历史/附件——并按 AirLogistics 项目规范定位代码完成修复。禅道 18.8 没有 API 2.0,官方 zentao-cli / MCP 不可用,必须用本 skill 的 zentao.py。当用户提到"禅道"、"bug 单"、"我的 bug"、"修 bug"、"处理 bug"、给出 Bug 编号(如 "#632"、"bug 632")或禅道链接(bug-view-xxx.html / my-work-bug.html)时使用。
description: 读取禅道(njlkairport.chandao.net,开源版 18.8)中的 Bug 单——我的 Bug 列表、单个 Bug 的标题/描述/截图/评论/修改历史/附件——并按 AirLogistics 项目规范定位代码完成修复,也可在禅道上解决、指派 Bug(如转给后端并附问题说明)。禅道 18.8 没有 API 2.0,官方 zentao-cli / MCP 不可用,必须用本 skill 的 zentao.py。当用户提到"禅道"、"bug 单"、"我的 bug"、"修 bug"、"处理 bug"、给出 Bug 编号(如 "#632"、"bug 632")或禅道链接(bug-view-xxx.html / my-work-bug.html)时使用。
---
# 禅道 Bug 读取与修复
@@ -30,6 +30,7 @@ python3 $Z view 632 # Bug 详情(Markdown)
python3 .claude/skills/zentao-bug/zentao.py login --account <账号>
```
必须在**独立的终端窗口**里执行——Claude Code 的 `! <命令>` 没有 TTY,密码提示会直接 EOFError。
密码交互输入、不回显;默认存入 macOS 钥匙串,此后会话过期会自动重新登录(`--no-keychain` 则不保存)。
**不要向用户索要密码,也不要替用户在命令行里带密码登录。**
@@ -46,12 +47,37 @@ python3 .claude/skills/zentao-bug/zentao.py login --account <账号>
## 写回禅道
暂未实现(写操作会改动线上 Bug 状态,需用户确认后再加)。修复完成后由用户在禅道手动"解决",
可附上提交号与改动摘要供用户粘贴。
```bash
python3 $Z resolve 621 622 --comment 已解决 --dry-run # 先预览
python3 $Z resolve 621 622 --comment 已解决 # 提交
```
等同网页「解决」表单,默认:解决方案 `fixed`(已解决)、解决版本 `trunk`(主干);**解决日期与指派给取网页表单渲染出的默认值**
(服务器当前时间 / 创建人,可用 `--date` / `--assign-to` 覆盖),其余字段不动;备注默认留空,团队习惯只写「已解决」,不写业务细节。
只处理激活状态的单子,提交后回读校验状态。
- **写操作会改动线上状态,只在用户明确要求时执行**;只解决确实修好、且没有待确认疑问的单子。
无缺陷 / 需后端修复 / 有疑问的保持激活,并向用户列出原因(无缺陷应选「设计如此」等其他方案,不要标「已解决」)
- 接口提交**不会**自动补表单默认值,所以先 GET 解决表单 HTML 读出 `resolvedDate` 与 `assignedTo` 的选中项再原样提交;
解决日期不能用本机时间:本机可能在美西时区,禅道服务器是北京时间(#621 曾因此写成本机时间)
### 指派(转给后端等)
```bash
python3 $Z assign 627 --to 陶雨佳 --comment-file /path/c627.txt --dry-run # 先预览
python3 $Z assign 627 --to 陶雨佳 --comment-file /path/c627.txt # 提交
```
等同网页「指派」表单:`--to` 接受账号(如 `TYJ`)或姓名,状态保持激活,提交后回读校验指派人。
需后端修复的单子转给后端时,备注照搬 `documents/后端接口对接问题清单.xlsx` 对应行
(接口地址 / 问题类型 / 问题描述 / 期望调整 / 前端现状),并注明清单序号;多行备注用 `--comment-file`,换行会转成 `<br />`。
## 实现说明
- 认证:`POST /api.php/v1/tokens` 换 Token;数据走页面 JSON 模式(`.html` → `.json`),Cookie `zentaosid=<Token>`。
- 接口:`/my-work-bug-<type>-0-id_desc-0-<perPage>-<page>.json`、`/bug-view-<id>.json`、`/file-read-<fileID>.<ext>`。
- 接口:`/my-work-bug-<type>-0-id_desc-0-<perPage>-<page>.json`、`/bug-view-<id>.json`、`/file-read-<fileID>.<ext>`;
解决:GET `/bug-resolve-<id>.json` 取版本/用户选项,POST `/bug-resolve-<id>.html?onlybody=yes` 表单
(resolution/resolvedBuild/resolvedDate/assignedTo/status=resolved/comment);
指派:GET `/bug-assignTo-<id>.json` 取用户,POST `/bug-assignTo-<id>.html?onlybody=yes` 表单(assignedTo/status/mailto[]/comment)。
- REST v1 的 `/products/<id>/bugs` 只返回激活中的 Bug,不能替代"我的 Bug"页面。
- 凭据:Token 在 `~/.config/zentao-lite/config.json`(0600),密码只在钥匙串(服务名 `zentao-lite`)。`logout` 一并清除。

View File

@@ -173,6 +173,27 @@ class Client:
self._relogin()
raise AuthError("无法获取数据")
def post_form(self, path, fields):
"""提交页面表单(与网页点击「保存」相同);返回响应 HTML(禅道用 <script>alert/parent 跳转回执)。"""
body = urllib.parse.urlencode(fields).encode()
for _ in range(2):
req = urllib.request.Request(self.url + path, data=body, headers={
"Cookie": f"zentaosid={self.cfg['token']}", "Token": self.cfg["token"],
"Content-Type": "application/x-www-form-urlencoded",
"Referer": self.url + path,
})
try:
with urllib.request.urlopen(req, timeout=60) as resp:
text = resp.read().decode("utf-8", "replace")
except urllib.error.HTTPError as e:
if e.code != 401:
raise
text = "user-login"
if "user-login" not in text:
return text
self._relogin()
raise AuthError("无法提交表单")
def download(self, path, dest):
for _ in range(2):
try:
@@ -490,6 +511,117 @@ def cmd_view(args):
print(f"(已保存到 {out_dir / 'bug.md'},图片 {len(fetcher.files)} 张)")
def form_defaults(client, bug_id):
"""读取网页「解决」表单渲染出的默认值:解决日期(服务器时间,北京时间)与指派给(禅道默认选中创建人)。
接口提交不会自动补默认值,必须先取表单再原样带上;不能用本机时间,本机可能在其他时区。"""
with client._open(f"/bug-resolve-{bug_id}.html?onlybody=yes") as resp:
page = resp.read().decode("utf-8", "replace")
date = re.search(r"name='resolvedDate'[^>]*value='([^']+)'", page)
select = re.search(r"<select name='assignedTo'.*?</select>", page, re.S)
assigned = select and re.search(r"<option value='([^']*)' selected", select.group(0))
if not date or not assigned or not assigned.group(1):
die(f"#{bug_id} 未能从解决表单读取默认的解决日期 / 指派给,可用 --date / --assign-to 指定")
return date.group(1), assigned.group(1)
def cmd_resolve(args):
"""解决 Bug:等同网页「解决」表单。默认解决方案=已解决、解决版本=主干(trunk)、
解决日期与指派给取网页表单默认值(服务器时间 / 创建人);只处理激活状态的单子,提交后回读校验。"""
client = Client(load_config())
failed = 0
for bug_id in args.ids:
form = client.page(f"/bug-resolve-{bug_id}.json")
bug = (form or {}).get("bug")
if not bug:
print(f"#{bug_id} 跳过:不存在或无权查看")
failed += 1
continue
title = html.unescape(bug["title"])
if bug["status"] != "active":
print(f"#{bug_id} 跳过:当前状态为「{STATUS.get(bug['status'], bug['status'])}」,只解决激活的 Bug({title})")
continue
builds = form.get("builds") or {}
if args.build not in builds:
die(f"解决版本 {args.build} 不在可选列表中:{', '.join(k for k in builds if k)}")
default_date, default_assigned = form_defaults(client, bug_id)
assigned = args.assign_to or default_assigned
fields = {
"resolution": args.resolution, "duplicateBug": "", "buildExecution": "",
"resolvedBuild": args.build, "buildName": "",
"resolvedDate": args.date or default_date,
"assignedTo": assigned, "status": "resolved", "comment": args.comment or "",
}
desc = (f"#{bug_id} {title} → {RESOLUTIONS.get(args.resolution, args.resolution)},"
f"版本 {builds[args.build]},指派给 {(form.get('users') or {}).get(assigned, assigned)}")
if args.dry_run:
print(f"[dry-run] {desc}")
continue
resp = client.post_form(f"/bug-resolve-{bug_id}.html?onlybody=yes", fields)
after = client.page(f"/bug-view-{bug_id}.json").get("bug") or {}
if after.get("status") == "resolved":
print(f"已解决 {desc}")
else:
alerts = re.findall(r"alert\((['\"])(.*?)\1\)", resp)
print(f"#{bug_id} 失败:提交后状态仍为 {after.get('status')}"
+ (f",禅道提示:{'; '.join(html.unescape(a[1]) for a in alerts)}" if alerts else ""))
failed += 1
if failed:
sys.exit(1)
def resolve_user(users, who):
"""按账号或姓名定位用户:先精确匹配账号,再按「姓名」匹配(禅道显示名形如 T:陶雨佳)。"""
if who in users:
return who
hits = [k for k, v in users.items() if k and v.split(":", 1)[-1] == who]
if len(hits) == 1:
return hits[0]
die(f"找不到唯一的用户「{who}」" + (f",候选:{', '.join(hits)}" if hits else ""))
def comment_html(text):
"""备注是富文本,纯文本换行在网页上会被合并,逐行转义后用 <br /> 连接。"""
return "<br />".join(html.escape(line) for line in text.splitlines())
def cmd_assign(args):
"""指派 Bug:等同网页「指派」表单(指派给 + 备注),状态保持激活;提交后回读校验指派人。"""
client = Client(load_config())
comment = args.comment
if args.comment_file:
comment = Path(args.comment_file).read_text(encoding="utf-8").strip()
failed = 0
for bug_id in args.ids:
form = client.page(f"/bug-assignTo-{bug_id}.json")
bug = (form or {}).get("bug")
if not bug:
print(f"#{bug_id} 跳过:不存在或无权查看")
failed += 1
continue
users = form.get("users") or {}
account = resolve_user(users, args.to)
title = html.unescape(bug["title"])
desc = f"#{bug_id} {title} → 指派给 {users.get(account, account)}"
if args.dry_run:
print(f"[dry-run] {desc}")
if comment:
print(" 备注:\n " + comment.replace("\n", "\n "))
continue
fields = {"assignedTo": account, "status": bug["status"], "mailto[]": "",
"comment": comment_html(comment) if comment else ""}
resp = client.post_form(f"/bug-assignTo-{bug_id}.html?onlybody=yes", fields)
after = client.page(f"/bug-view-{bug_id}.json").get("bug") or {}
if after.get("assignedTo") == account:
print(f"已指派 {desc}")
else:
alerts = re.findall(r"alert\((['\"])(.*?)\1\)", resp)
print(f"#{bug_id} 失败:提交后指派人仍为 {after.get('assignedTo')}"
+ (f",禅道提示:{'; '.join(html.unescape(a[1]) for a in alerts)}" if alerts else ""))
failed += 1
if failed:
sys.exit(1)
def main():
ap = argparse.ArgumentParser(description="禅道 18.x Bug 读取工具")
sub = ap.add_subparsers(dest="cmd", required=True)
@@ -515,6 +647,24 @@ def main():
p.add_argument("--json", action="store_true")
p.set_defaults(func=cmd_view)
p = sub.add_parser("resolve", help="解决 Bug(写操作,会改动禅道线上状态)")
p.add_argument("ids", type=int, nargs="+")
p.add_argument("--resolution", choices=tuple(RESOLUTIONS), default="fixed", help="默认 fixed(已解决)")
p.add_argument("--build", default="trunk", help="解决版本,默认 trunk(主干)")
p.add_argument("--assign-to", help="指派给(账号),默认取表单默认值(即创建人)")
p.add_argument("--date", help="解决日期 YYYY-MM-DD HH:MM:SS,默认取服务器当前时间")
p.add_argument("--comment", default="", help="备注,默认留空")
p.add_argument("--dry-run", action="store_true", help="只打印将要做的修改,不提交")
p.set_defaults(func=cmd_resolve)
p = sub.add_parser("assign", help="指派 Bug 并附备注(写操作,会改动禅道线上状态)")
p.add_argument("ids", type=int, nargs="+")
p.add_argument("--to", required=True, help="指派给:账号(如 TYJ)或姓名(如 陶雨佳)")
p.add_argument("--comment", default="", help="备注,多行用换行分隔")
p.add_argument("--comment-file", help="从文件读取备注(多行内容推荐用这个)")
p.add_argument("--dry-run", action="store_true", help="只打印将要做的修改,不提交")
p.set_defaults(func=cmd_assign)
args = ap.parse_args()
try:
args.func(args)

View File

@@ -76,7 +76,8 @@
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="6dp"
android:src="@drawable/ic_phone_chevron_right" />
android:src="@drawable/ic_phone_chevron_right"
android:tint="@color/phone_text_body" />
</LinearLayout>

View File

@@ -149,7 +149,7 @@ dependencies {
api 'com.github.li-xiaojun:XPopup:2.9.19'
// 屏幕适配
api 'me.jessyan:autosize:1.2.+'
api 'me.jessyan:autosize:1.2.1'
// 佳博打印SDK
api(name: 'sdk2-2.0.4', ext: 'aar') {

View File

@@ -41,6 +41,9 @@ class IntExpMoveEditActivity :
binding.viewModel = viewModel
// 手机主信息卡:按圆角裁切子 View,让左侧蓝色装饰条贴合卡片圆角(平板布局无该 id)
binding.cardWaybill?.clipToOutline = true
// 绑定图片 RecyclerView 引用
viewModel.rvImages = binding.rvImages

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 出港移库编辑页(手机)分区卡片:白底 + 12dp 圆角 + 1dp 描边 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/white" />
<corners android:radius="12dp" />
<stroke
android:width="1dp"
android:color="@color/move_edit_card_border" />
</shape>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 出港移库编辑页(手机)主信息卡:白底 + 12dp 圆角 + 1dp 描边;左侧装饰条由布局叠加,靠 clipToOutline 裁圆角 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/white" />
<corners android:radius="12dp" />
<stroke
android:width="1dp"
android:color="@color/move_edit_card_border_main" />
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 出港移库编辑页(手机)移交状态圆点 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/move_edit_dot_done" />
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 出港移库编辑页(手机)移交状态圆点 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/move_edit_dot_pending" />
</shape>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 出港移库编辑页(手机)运单类型标签:红底 + 4dp 圆角 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/move_edit_tag_red" />
<corners android:radius="4dp" />
</shape>

View File

@@ -18,6 +18,8 @@
<data>
<import type="android.view.View" />
<variable
name="viewModel"
type="com.lukouguoji.gjc.viewModel.IntExpArriveSubOrderViewModel" />
@@ -60,21 +62,52 @@
</LinearLayout>
<!-- ==================== 列表 ==================== -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
<!-- ==================== 列表 + 空态 ==================== -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:clipToPadding="false"
android:overScrollMode="never"
android:paddingTop="4dp"
android:paddingBottom="12dp"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="3"
tools:listitem="@layout/item_int_exp_arrive_sub_order" />
android:layout_weight="1">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:overScrollMode="never"
android:paddingTop="4dp"
android:paddingBottom="12dp"
itemLayoutId="@{viewModel.itemLayoutId}"
viewHolder="@{viewModel.itemViewHolder}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="3"
tools:listitem="@layout/item_int_exp_arrive_sub_order" />
<!-- 空态(Bug #631:无分单的运单也可进入本页) -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:orientation="vertical"
android:visibility="@{viewModel.displayList.empty ? View.VISIBLE : View.GONE}">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/ic_phone_clipboard"
android:tint="@color/phone_text_hint" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="暂无分单"
android:textColor="@color/phone_text_hint"
android:textSize="14sp" />
</LinearLayout>
</FrameLayout>
<!-- ==================== 底部操作条 ==================== -->
<com.lukouguoji.module_base.ui.weight.phone.PhoneBottomBar

View File

@@ -5,17 +5,16 @@
详情(DetailsPageType.Details):列表卡片「查看详情」进入,全部只读;
编辑(DetailsPageType.Modify):列表卡片「编辑」进入(对应平板侧滑「编辑」),仅备注与交接图片可改。
样式沿用设计稿 05_出港移库「运单详情」:蓝色表头卡片 + 两列字段网格;移库人/移库时间取列表数据(listBean)。
样式取自「移库编辑」HTML 原型:主信息卡左侧蓝色装饰条,分区卡白底表头 + 分割线,两列字段网格;移库人/移库时间取列表数据(listBean)。
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="com.lukouguoji.module_base.common.DetailsPageType" />
<import type="com.lukouguoji.module_base.ui.weight.phone.PhoneFormRowType" />
<import type="android.view.View" />
<variable
@@ -38,150 +37,292 @@
android:fillViewport="true"
android:overScrollMode="never">
<!-- clipToPadding=false:卡片阴影要画进 16dp 内边距,否则在卡片左右边缘被裁齐 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:orientation="vertical"
android:padding="16dp">
<!-- ==================== 卡片一:运单基本信息 ==================== -->
<!-- ==================== 卡片一:运单基本信息(白底 + 左侧蓝色装饰条,样式取自「移库编辑」原型) ==================== -->
<!-- 横向:左侧 3dp 装饰条(高度随内容)+ 内容;clipToOutline 由 Activity 设置,让装饰条随卡片圆角裁切。
卡片阴影:系统默认黑色短阴影会和描边叠成一圈脏边,改用原型的蓝灰半透明阴影色(API 28+ 生效) -->
<LinearLayout
android:id="@+id/card_waybill"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card"
android:orientation="vertical">
android:background="@drawable/bg_move_edit_card_main"
android:elevation="6dp"
android:outlineAmbientShadowColor="@color/move_edit_shadow_main"
android:outlineSpotShadowColor="@color/move_edit_shadow_main"
tools:targetApi="28"
android:orientation="horizontal">
<View
android:layout_width="3dp"
android:layout_height="match_parent"
android:background="@color/move_edit_accent" />
<!-- 蓝色表头:运单号 + 移交状态 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card_header_blue"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="16dp"
android:paddingVertical="12dp">
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="0dp"
<!-- 表头:运单号 + 移交状态 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@{viewModel.dataBean.wbNo}"
android:textColor="@color/white"
android:textSize="17sp"
android:textStyle="bold" />
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingVertical="12dp"
android:paddingStart="17dp"
android:paddingEnd="16dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:letterSpacing="0.04"
android:maxLines="1"
android:text="@{viewModel.dataBean.wbNo}"
android:textColor="@color/move_edit_wb_no"
android:textSize="19sp"
android:textStyle="bold" />
<View
android:layout_width="8dp"
android:layout_height="8dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="6dp"
android:background="@{viewModel.dataBean.moveState == 1 ? @drawable/bg_move_edit_dot_done : @drawable/bg_move_edit_dot_pending}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-medium"
android:text="@{viewModel.dataBean.moveStateText}"
android:textColor="@color/move_edit_status"
android:textSize="12sp" />
</LinearLayout>
<View
android:layout_width="8dp"
android:layout_height="8dp"
android:layout_marginEnd="6dp"
android:background="@{viewModel.dataBean.moveState == 1 ? @drawable/bg_phone_dot_green : @drawable/bg_phone_dot_gray}" />
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/move_edit_card_border" />
<TextView
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{viewModel.dataBean.moveStateText}"
android:textColor="@color/white"
android:textSize="14sp" />
android:orientation="vertical"
android:paddingStart="17dp"
android:paddingTop="16dp"
android:paddingEnd="16dp"
android:paddingBottom="16dp">
</LinearLayout>
<!-- 运单类型(红标签) -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/bg_move_edit_tag_red"
android:fontFamily="sans-serif-medium"
android:paddingHorizontal="10dp"
android:paddingVertical="4dp"
android:text='@{viewModel.dataBean.awbTypeName == null || viewModel.dataBean.awbTypeName.empty ? "-" : viewModel.dataBean.awbTypeName}'
android:textColor="@android:color/white"
android:textSize="12sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- 品名 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text='@{viewModel.dataBean.goods == null || viewModel.dataBean.goods.empty ? "-" : viewModel.dataBean.goods}'
android:textColor="@color/move_edit_heading"
android:textSize="22sp"
android:textStyle="bold" />
<!-- 运单类型(红标签) -->
<TextView
android:layout_width="wrap_content"
android:layout_height="22dp"
android:background="@drawable/bg_phone_tag_red"
android:gravity="center"
android:paddingHorizontal="8dp"
android:text='@{viewModel.dataBean.awbTypeName == null || viewModel.dataBean.awbTypeName.empty ? "-" : viewModel.dataBean.awbTypeName}'
android:textColor="@color/phone_tag_red_text"
android:textSize="12sp"
android:textStyle="bold" />
<!-- 两列字段:件数/重量、特码/代理人、出运路径/承运人 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="vertical">
<!-- 品名(主字段大字) -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:text='@{viewModel.dataBean.goods == null || viewModel.dataBean.goods.empty ? "-" : viewModel.dataBean.goods}'
android:textColor="@color/phone_text_strong"
android:textSize="22sp"
android:textStyle="bold" />
<!-- 第 1 行:件数 / 重量 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
title='@{"件数"}'
value='@{viewModel.dataBean.pc == null ? "" : String.valueOf(viewModel.dataBean.pc)}' />
android:orientation="vertical">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="件数"
android:textColor="@color/move_edit_label"
android:textSize="12sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:fontFamily="sans-serif-medium"
android:text='@{viewModel.dataBean.pc == null ? "-" : String.valueOf(viewModel.dataBean.pc)}'
android:textColor="@color/move_edit_heading"
android:textSize="15sp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_weight="1"
title='@{"重量"}'
value='@{viewModel.dataBean.weight == null ? "" : String.valueOf(viewModel.dataBean.weight) + " kg"}' />
android:layout_marginStart="16dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="重量"
android:textColor="@color/move_edit_label"
android:textSize="12sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:fontFamily="sans-serif-medium"
android:text='@{viewModel.dataBean.weight == null ? "-" : String.valueOf(viewModel.dataBean.weight) + " kg"}'
android:textColor="@color/move_edit_heading"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>
<!-- 第 2 行:特码 / 代理人 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
title='@{"特码"}'
value="@{viewModel.dataBean.spCode}" />
android:orientation="vertical">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="特码"
android:textColor="@color/move_edit_label"
android:textSize="12sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:fontFamily="sans-serif-medium"
android:text='@{viewModel.dataBean.spCode == null || viewModel.dataBean.spCode.empty ? "-" : viewModel.dataBean.spCode}'
android:textColor="@color/move_edit_heading"
android:textSize="15sp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_weight="1"
title='@{"代理人"}'
value="@{viewModel.dataBean.agentCode}" />
android:layout_marginStart="16dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="代理人"
android:textColor="@color/move_edit_label"
android:textSize="12sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:fontFamily="sans-serif-medium"
android:text='@{viewModel.dataBean.agentCode == null || viewModel.dataBean.agentCode.empty ? "-" : viewModel.dataBean.agentCode}'
android:textColor="@color/move_edit_heading"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>
<!-- 第 3 行:出运路径 / 承运人 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
title='@{"出运路径"}'
value="@{viewModel.dataBean.range}" />
android:orientation="vertical">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="出运路径"
android:textColor="@color/move_edit_label"
android:textSize="12sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:fontFamily="sans-serif-medium"
android:text='@{viewModel.dataBean.range == null || viewModel.dataBean.range.empty ? "-" : viewModel.dataBean.range}'
android:textColor="@color/move_edit_heading"
android:textSize="15sp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_weight="1"
title='@{"承运人"}'
value="@{viewModel.dataBean.by}" />
android:layout_marginStart="16dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="承运人"
android:textColor="@color/move_edit_label"
android:textSize="12sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:fontFamily="sans-serif-medium"
android:text='@{viewModel.dataBean.by == null || viewModel.dataBean.by.empty ? "-" : viewModel.dataBean.by}'
android:textColor="@color/move_edit_heading"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
@@ -194,66 +335,122 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/bg_phone_card"
android:background="@drawable/bg_move_edit_card"
android:elevation="2dp"
android:outlineAmbientShadowColor="@color/move_edit_shadow"
android:outlineSpotShadowColor="@color/move_edit_shadow"
tools:targetApi="28"
android:orientation="vertical"
android:visibility="@{viewModel.listBean != null &amp;&amp; viewModel.listBean.isMoved ? View.VISIBLE : View.GONE}">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card_header_green"
android:paddingHorizontal="16dp"
android:paddingVertical="10dp"
android:paddingVertical="12dp"
android:text="移库信息"
android:textColor="@color/white"
android:textColor="@color/move_edit_heading"
android:textSize="15sp"
android:textStyle="bold" />
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/move_edit_card_border" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="16dp"
android:paddingVertical="12dp">
android:orientation="vertical"
android:padding="16dp">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
title='@{"移库人"}'
value="@{viewModel.listBean.opUserDisplay}" />
android:orientation="horizontal">
<com.lukouguoji.module_base.ui.weight.phone.PhoneKvItem
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_weight="1"
title='@{"移库时间"}'
value="@{viewModel.listBean.opdate}" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="移库人"
android:textColor="@color/move_edit_label"
android:textSize="12sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:fontFamily="sans-serif-medium"
android:text='@{viewModel.listBean.opUserDisplay == null || viewModel.listBean.opUserDisplay.empty ? "-" : viewModel.listBean.opUserDisplay}'
android:textColor="@color/move_edit_heading"
android:textSize="15sp" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="16dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="移库时间"
android:textColor="@color/move_edit_label"
android:textSize="12sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:fontFamily="sans-serif-medium"
android:text='@{viewModel.listBean.opdate == null || viewModel.listBean.opdate.empty ? "-" : viewModel.listBean.opdate}'
android:textColor="@color/move_edit_heading"
android:textSize="15sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
<!-- ==================== 卡片三:交接图片(Bug #632:样式与进港移库「异常照片」一致——橙色表头 + 三列虚线加号槽位,长按图片出删除角标) ==================== -->
<!-- ==================== 卡片三:交接图片(Bug #632:白底表头 + 分割线,三列加号槽位,长按图片出删除角标) ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/bg_phone_card"
android:background="@drawable/bg_move_edit_card"
android:elevation="2dp"
android:outlineAmbientShadowColor="@color/move_edit_shadow"
android:outlineSpotShadowColor="@color/move_edit_shadow"
tools:targetApi="28"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card_header_orange"
android:paddingHorizontal="16dp"
android:paddingVertical="10dp"
android:paddingVertical="12dp"
android:text="交接图片"
android:textColor="@color/white"
android:textColor="@color/move_edit_heading"
android:textSize="15sp"
android:textStyle="bold" />
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/move_edit_card_border" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_images"
android:layout_width="match_parent"
@@ -272,42 +469,71 @@
android:layout_height="48dp"
android:gravity="center"
android:text="暂无图片"
android:textColor="@color/phone_text_hint"
android:textColor="@color/move_edit_hint"
android:textSize="14sp"
android:visibility="@{viewModel.showNoImage ? View.VISIBLE : View.GONE}" />
</LinearLayout>
<!-- ==================== 卡片四:补充信息(Bug #632:备注录入与保存,表头底色 #F3F4F6) ==================== -->
<!-- ==================== 卡片四:补充信息(Bug #632:备注录入与保存,无下划线) ==================== -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/bg_phone_card"
android:background="@drawable/bg_move_edit_card"
android:elevation="2dp"
android:outlineAmbientShadowColor="@color/move_edit_shadow"
android:outlineSpotShadowColor="@color/move_edit_shadow"
tools:targetApi="28"
android:orientation="vertical">
<!-- 表头文字色:Bug 单写的是白色,但白字在 #F3F4F6 上不可读,暂用标题深色,待确认 -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_phone_card_header_gray"
android:paddingHorizontal="16dp"
android:paddingVertical="10dp"
android:paddingVertical="12dp"
android:text="补充信息"
android:textColor="@color/phone_text_title"
android:textColor="@color/move_edit_heading"
android:textSize="15sp"
android:textStyle="bold" />
<com.lukouguoji.module_base.ui.weight.phone.PhoneFormRow
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/move_edit_card_border" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingBottom="4dp"
enable="@{viewModel.pageType != DetailsPageType.Details}"
hint='@{"请输入备注"}'
title='@{"备注"}'
type="@{viewModel.pageType == DetailsPageType.Details ? PhoneFormRowType.TEXT : PhoneFormRowType.INPUT}"
value="@={viewModel.remark}" />
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="16dp">
<TextView
android:layout_width="40dp"
android:layout_height="wrap_content"
android:text="备注"
android:textColor="@color/move_edit_form"
android:textSize="14sp" />
<EditText
android:layout_width="0dp"
android:layout_height="32dp"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:background="@null"
android:enabled="@{viewModel.pageType != DetailsPageType.Details}"
android:hint='@{viewModel.pageType == DetailsPageType.Details ? "--" : "请输入备注"}'
android:importantForAutofill="no"
android:inputType="text"
android:maxLines="1"
android:padding="0dp"
android:text="@={viewModel.remark}"
android:textColor="@color/move_edit_form"
android:textColorHint="@color/move_edit_hint"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>

View File

@@ -104,7 +104,8 @@
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="6dp"
android:src="@drawable/ic_phone_chevron_right" />
android:src="@drawable/ic_phone_chevron_right"
android:tint="@color/phone_text_body" />
</LinearLayout>

View File

@@ -64,7 +64,8 @@
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="6dp"
android:src="@drawable/ic_phone_chevron_right" />
android:src="@drawable/ic_phone_chevron_right"
android:tint="@color/phone_text_hint" />
</LinearLayout>

View File

@@ -185,35 +185,7 @@
</LinearLayout>
<!-- 字段网格:海关放行 / 运单类型(Bug #626:待运抵不显示,仅已运抵显示,与原型一致) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="horizontal"
android:visibility="@{`shipped`.equals(viewModel.currentTab) ? View.VISIBLE : View.GONE}">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"海关放行: " + bean.orDash(bean.cmdStatus)}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="海关放行: 已放行" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text='@{"运单类型: " + bean.orDash(bean.awbName)}'
android:textColor="@color/phone_text_body"
android:textSize="13sp"
tools:text="运单类型: 普通" />
</LinearLayout>
<!-- 查看分单(无分单数据时不显示) -->
<!-- 查看分单(Bug #631:无分单也显示,数量为 0) -->
<TextView
android:layout_width="match_parent"
android:layout_height="36dp"
@@ -221,10 +193,9 @@
android:background="@drawable/bg_phone_btn_weak"
android:gravity="center"
android:onClick="@{()-> activity.openSubOrder(bean)}"
android:text='@{"查看分单 " + bean.haWbNumber}'
android:text='@{"查看分单 " + (bean.haWbNumber == null ? 0 : bean.haWbNumber)}'
android:textColor="@color/phone_primary"
android:textSize="14sp"
android:visibility="@{bean.haWbNumber != null &amp;&amp; bean.haWbNumber > 0 ? View.VISIBLE : View.GONE}"
tools:text="查看分单 3" />
</androidx.appcompat.widget.LinearLayoutCompat>

View File

@@ -95,7 +95,8 @@
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="6dp"
android:src="@drawable/ic_phone_chevron_right" />
android:src="@drawable/ic_phone_chevron_right"
android:tint="@color/phone_text_body" />
</LinearLayout>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 出港移库编辑页(手机版 activity_int_exp_move_edit)专用色值,取自「移库编辑」HTML 原型,仅该页使用 -->
<resources>
<color name="move_edit_accent">#3B6FE0</color> <!-- 主信息卡左侧装饰条 -->
<color name="move_edit_card_border">#E6EBF2</color> <!-- 分区卡描边 / 表头分割线 -->
<color name="move_edit_card_border_main">#DCE4F0</color> <!-- 主信息卡描边 -->
<color name="move_edit_wb_no">#1B3F8F</color> <!-- 运单号 -->
<color name="move_edit_heading">#132239</color> <!-- 卡片标题 / 品名 / 字段值 -->
<color name="move_edit_label">#6B7A8D</color> <!-- 字段标签 -->
<color name="move_edit_status">#5A6B84</color> <!-- 状态文字 -->
<color name="move_edit_form">#1F2A3C</color> <!-- 备注标签与输入 -->
<color name="move_edit_hint">#6B7280</color> <!-- 备注占位文字 -->
<color name="move_edit_tag_red">#D93025</color> <!-- 运单类型标签 -->
<color name="move_edit_dot_pending">#F5A623</color> <!-- 未移交圆点 -->
<color name="move_edit_dot_done">#10B981</color> <!-- 已移交圆点 -->
<!-- 卡片阴影色(原型 rgba(16,30,51,…));系统还会再乘主题阴影透明度,故这里给半透明 -->
<color name="move_edit_shadow_main">#80101E33</color>
<color name="move_edit_shadow">#50101E33</color>
</resources>

View File

@@ -104,7 +104,8 @@
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="6dp"
android:src="@drawable/ic_phone_chevron_right" />
android:src="@drawable/ic_phone_chevron_right"
android:tint="@color/phone_text_body" />
</LinearLayout>

View File

@@ -95,7 +95,8 @@
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="6dp"
android:src="@drawable/ic_phone_chevron_right" />
android:src="@drawable/ic_phone_chevron_right"
android:tint="@color/phone_text_body" />
</LinearLayout>