Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
0
01SaaS-test
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
吴珊婧
01SaaS-test
Commits
07a54ea1
Commit
07a54ea1
authored
Jul 02, 2026
by
wushanjing
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
补齐智能接单页面支持
parent
98fbb8ed
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
153 additions
and
2 deletions
+153
-2
wanzhanggui_order_page.py
e2e/pages/wanzhanggui_order_page.py
+153
-2
No files found.
e2e/pages/wanzhanggui_order_page.py
View file @
07a54ea1
...
...
@@ -43,6 +43,7 @@ class ManualOrderData:
dispatch_price
:
str
=
"70"
dispatch_price_mode
:
str
=
"percent"
dispatch_price_percent
:
str
=
"90"
sub_order_title
:
str
=
""
service_hours
:
str
=
"14"
boss_phone
:
str
=
"13800138000"
contact_phone
:
str
=
"13800138000"
...
...
@@ -4155,7 +4156,7 @@ class WanzhangguiOrderPage(TenantAuthPage):
except
Exception
as
exc
:
raise
AssertionError
(
f
"未找到可填写的子单信息行;modal_fields={self.modal_field_values(frame)}"
)
from
exc
self
.
fill_row_input
(
row
,
"请输入订单标题"
,
order
.
order_title
)
self
.
fill_row_input
(
row
,
"请输入订单标题"
,
order
.
sub_order_title
or
order
.
order_title
)
if
price_mode
==
"percent"
:
self
.
fill_row_input_any
(
row
,
[
"请输入价格百分比"
,
"价格百分比"
,
"请输入百分比"
,
"百分比"
],
price_value
)
else
:
...
...
@@ -4383,7 +4384,7 @@ class WanzhangguiOrderPage(TenantAuthPage):
};
}"""
,
{
"orderTitle"
:
order
.
order_title
,
"orderTitle"
:
order
.
sub_order_title
or
order
.
order_title
,
"strategyName"
:
order
.
strategy_name
,
"priceMode"
:
price_mode
,
"priceLabel"
:
"百分比发单价"
if
price_mode
==
"percent"
else
"固定发单价"
,
...
...
@@ -9219,6 +9220,156 @@ class WanyoujiFulfillmentPage(TenantAuthPage):
)
return
frame
def
ensure_auto_accept_assignment
(
self
,
merchant_name
:
str
,
enabled
:
bool
)
->
str
:
frame
=
self
.
open_auto_accept_assignment_config
()
self
.
search_auto_accept_assignment
(
frame
,
merchant_name
)
row_text
=
self
.
auto_accept_assignment_row_text
(
frame
,
merchant_name
)
if
self
.
auto_accept_assignment_enabled_from_row
(
row_text
)
==
enabled
:
return
row_text
action_texts
=
[
"开启自动接单"
,
"开启智能接单"
,
"开启接单"
,
"启用"
]
if
enabled
else
[
"关闭自动接单"
,
"关闭智能接单"
,
"关闭接单"
,
"停用"
,
]
clicked
=
self
.
click_auto_accept_assignment_action
(
frame
,
merchant_name
,
action_texts
)
assert
clicked
,
(
f
"智能接单配置列表未找到切换操作;merchant={merchant_name}; expected_enabled={enabled}; "
f
"row_text={row_text}; text={frame.locator('body').inner_text(timeout=5000)[:1500]}"
)
self
.
confirm_open_dialog
(
frame
)
self
.
page
.
wait_for_timeout
(
2500
)
self
.
search_auto_accept_assignment
(
frame
,
merchant_name
)
row_text
=
self
.
auto_accept_assignment_row_text
(
frame
,
merchant_name
)
assert
self
.
auto_accept_assignment_enabled_from_row
(
row_text
)
==
enabled
,
(
f
"智能接单开关切换后不符合预期;merchant={merchant_name}; expected={enabled}; row_text={row_text}"
)
return
row_text
def
open_auto_accept_assignment_config
(
self
)
->
Frame
:
self
.
goto
(
WANYOUJI_CONSOLE_URL
)
self
.
wait_for_enterprise_console_shell
()
menu_paths
=
[
(
"工作室履约应用"
,
"智能接单配置"
),
(
"工作室履约应用"
,
"自动接单配置"
),
(
"工作室履约应用"
,
"接单配置"
),
(
"工作室履约应用"
,
"接单设置"
),
(
"工作室管理"
,
"智能接单配置"
),
(
"工作室管理"
,
"自动接单配置"
),
(
"工作室管理"
,
"接单配置"
),
]
for
parent_text
,
child_text
in
menu_paths
:
try
:
self
.
click_sidebar_text
(
parent_text
,
right_edge
=
True
)
except
AssertionError
:
self
.
click_sidebar_visible_text
(
parent_text
,
right_edge
=
True
)
or
self
.
click_left_sidebar_text_contains
(
parent_text
,
right_edge
=
True
)
self
.
page
.
wait_for_timeout
(
700
)
if
self
.
click_sidebar_visible_text
(
child_text
)
or
self
.
click_left_sidebar_text_contains
(
child_text
):
self
.
page
.
wait_for_timeout
(
2500
)
self
.
retry_if_app_load_timeout
()
return
self
.
best_wanyouji_frame
([
"自动接单"
,
"智能接单"
,
"接单配置"
,
"商家"
,
"工作室"
])
page_text
=
self
.
page
.
locator
(
"body"
)
.
inner_text
(
timeout
=
5000
)
raise
AssertionError
(
f
"未找到丸友集智能接单配置入口;text={page_text[:1500]}"
)
def
search_auto_accept_assignment
(
self
,
frame
:
Frame
,
merchant_name
:
str
)
->
None
:
last_text
=
""
for
attempt
in
range
(
4
):
if
attempt
:
self
.
click_optional_text
(
frame
,
"重 置"
)
or
self
.
click_optional_text
(
frame
,
"重置"
)
self
.
page
.
wait_for_timeout
(
800
)
filled
=
False
for
label
in
[
"商家名称"
,
"上游商家"
,
"店铺名称"
,
"工作室名称"
,
"供应链名称"
,
"关键字"
]:
if
self
.
fill_input_near_label
(
frame
,
label
,
merchant_name
):
filled
=
True
break
if
not
filled
:
inputs
=
frame
.
locator
(
"input:visible"
)
if
inputs
.
count
():
inputs
.
first
.
fill
(
merchant_name
)
filled
=
True
if
filled
and
not
(
self
.
click_optional_text
(
frame
,
"查 询"
)
or
self
.
click_optional_text
(
frame
,
"查询"
)):
frame
.
locator
(
"input:visible"
)
.
first
.
press
(
"Enter"
)
self
.
page
.
wait_for_timeout
(
1800
+
attempt
*
600
)
last_text
=
frame
.
locator
(
"body"
)
.
inner_text
(
timeout
=
5000
)
if
merchant_name
in
last_text
:
return
raise
AssertionError
(
f
"智能接单配置搜索后未找到商家:{merchant_name};text={last_text[:1500]}"
)
def
auto_accept_assignment_row_text
(
self
,
frame
:
Frame
,
merchant_name
:
str
)
->
str
:
for
_
in
range
(
4
):
row_text
=
str
(
frame
.
evaluate
(
"""merchantName => {
const rows = Array.from(document.querySelectorAll('tbody tr, .ant-table-row, [class*="table"] [class*="row"]'))
.map(row => ({ text: (row.innerText || row.textContent || '').trim(), r: row.getBoundingClientRect() }))
.filter(item => item.r.width > 0 && item.r.height > 0)
.filter(item => item.text.includes(merchantName));
return rows[0]?.text || '';
}"""
,
merchant_name
,
)
)
if
row_text
:
return
row_text
self
.
page
.
wait_for_timeout
(
1000
)
raise
AssertionError
(
f
"智能接单配置列表未找到商家:{merchant_name};text={frame.locator('body').inner_text(timeout=5000)[:1500]}"
)
@
staticmethod
def
auto_accept_assignment_enabled_from_row
(
row_text
:
str
)
->
bool
:
compact
=
re
.
sub
(
r"\s+"
,
""
,
row_text
or
""
)
if
any
(
key
in
compact
for
key
in
[
"关闭自动接单"
,
"关闭智能接单"
,
"关闭接单"
,
"已开启"
,
"开启中"
]):
return
True
if
any
(
key
in
compact
for
key
in
[
"开启自动接单"
,
"开启智能接单"
,
"开启接单"
,
"已关闭"
,
"未开启"
]):
return
False
lines
=
[
line
.
strip
()
for
line
in
row_text
.
splitlines
()
if
line
.
strip
()]
for
index
,
line
in
enumerate
(
lines
):
if
any
(
key
in
line
for
key
in
[
"自动接单"
,
"智能接单"
,
"是否开启"
]):
nearby
=
""
.
join
(
lines
[
index
:
index
+
3
])
if
"是"
in
nearby
or
"开启"
in
nearby
:
return
True
if
"否"
in
nearby
or
"关闭"
in
nearby
:
return
False
return
False
def
click_auto_accept_assignment_action
(
self
,
frame
:
Frame
,
merchant_name
:
str
,
action_texts
:
list
[
str
])
->
bool
:
clicked
=
frame
.
evaluate
(
"""({ merchantName, actionTexts }) => {
const visible = el => {
const r = el.getBoundingClientRect();
return r.width > 0 && r.height > 0;
};
const rows = Array.from(document.querySelectorAll('tbody tr, .ant-table-row, [class*="table"] [class*="row"]'))
.map(row => ({ row, text: (row.innerText || row.textContent || '').trim(), r: row.getBoundingClientRect() }))
.filter(item => item.r.width > 0 && item.r.height > 0)
.filter(item => item.text.includes(merchantName));
const row = rows[0]?.row;
if (!row) return false;
const nodes = Array.from(row.querySelectorAll('button, a, span, [role="button"]'))
.map(el => ({ el, text: (el.innerText || el.textContent || '').trim(), r: el.getBoundingClientRect() }))
.filter(item => visible(item.el));
for (const actionText of actionTexts) {
const target = nodes.find(item => item.text === actionText) ||
nodes.find(item => item.text.includes(actionText));
if (!target) continue;
const clickable = target.el.closest('button, a, [role="button"]') || target.el;
const r = target.r;
clickable.dispatchEvent(new MouseEvent('mouseover', { bubbles: true, clientX: r.x + r.width / 2, clientY: r.y + r.height / 2 }));
clickable.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, clientX: r.x + r.width / 2, clientY: r.y + r.height / 2 }));
clickable.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, clientX: r.x + r.width / 2, clientY: r.y + r.height / 2 }));
clickable.click();
return true;
}
return false;
}"""
,
{
"merchantName"
:
merchant_name
,
"actionTexts"
:
action_texts
},
)
self
.
page
.
wait_for_timeout
(
1000
)
return
bool
(
clicked
)
def
open_workshop_appeal_work_order
(
self
)
->
Frame
:
self
.
goto
(
WANYOUJI_CONSOLE_URL
)
self
.
wait_for_enterprise_console_shell
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment