Most frameworks can do what you need for this, but there will be a fair amount of custom code needed.
You can use Page Object Model with inheritance as JustARandomGuy has suggested. By creating a base login class with the common login functionality/features and using an inherited login page object for the aspects of login which are unique to the page you can keep your code much cleaner.
Another method that helps with this situation is to use a config file with your script runs - let the config file define all your objects and groups, e.g. if the functionality of the login page is the same across all sites but the field is named differently, you might build your config file something like this:
<site>
<sitename>Site1</sitename>
<pages>
<page>
<pageuri>/login</pageuri>
<username>txtUserId</username>
<password>txtPassWord</password>
<submit>cmdLogin</submit>
</page>
<!-- etc... -->
</pages>
</site>
There are other ways to store that kind of information - but if it lives in a user-editable location outside your code-base, it becomes much easier to handle any changes to page schema or field names.
Within your script, you'd reference variables that pull from the reference file for your site data, so instead of something like FindById('txtUserId')
you might use FindById(useridFieldName)
with the value of useridFieldName
set on load of the module.
I've used this approach in some very large (1/2 million lines of code, plus at least that many rows of data) automation projects, and had a lot of success with maintainability and extensibility. I've been able to add new functionality by adding four rows of data, and maybe a dozen lines of code.