Eventually, I found the reason of this weird behaviour.
It is caused by the JavaScript embedded in wp_admin_canonical_url()
(https://developer.wordpress.org/reference/functions/wp_admin_canonical_url/)
The URL is determined by this piece of code
$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']
where the latter one returns wp-admin
instead of hello/wp-admin
.
By manipulating the value in $_SERVER['REQUEST_URI']
, I can successfully get the correct behaviour in admin dashboard. But I still hope for an elegant solution without touching WordPress code.