The pattern that you tried, consists of all optional parts because all the quantifiers are either ? for optional, or * for 0 or more times. As the / is also optional, you will match 12.12.12
You could make the part with the / part optional without making the / itself optional.
If you want to match at least a digit and prevent matching empty strings you can use a positive lookahead to match a least a digit.
^(?=[^\d\r\n]*\d)\d*\.?\d*(?:\/\d*\.?\d*)?[a-z]*$
Regex demo
The pattern matches
^ Start of string
(?=[^\d\r\n]*\d) Assert at least a digit
\d*\.?\d* Match optional digits and .
(?: Non capture group
\/\d*\.?\d* Match / and optional digits and .
)? Close non capture group and make it optional
[a-z]* Optionally match chars a-z
$ End of string
If there should be at least a digit on each side of the / to not match for example ./.
^(?:\d*\.?\d+|\d+\.)(?:\/\d*\.?\d+|\d+\.)?[a-z]*$
The pattern matches
^ Start of string
(?:\d*\.?\d+|\d+\.) Match either optional digits, optional . and 1+ digits OR match 1+ digits and .
(?: Non capture group
\/\d*\.?\d+|\d+\. Match / and the same as the first pattern again
)? Close non capture group and make it optional
[a-z]* Optionally match chars a-z
$ End of string
Regex demo