import { parse , stringify } from 'qs' ; import BaseRouter , { Query } from './BaseRouter' ; export interface IStackItem { path : string ; query : Query ; } export function parseUrl ( url ) { const urlSplit = url . split ( '?' ) ; const query = parse ( urlSplit [ 1 ] || '' ) as Query ; const path = urlSplit [ 0 ] ; return { path , query , } ; } /**
 * 格式化
 */ export function format ( url , params ? ) { const { path , query } = parseUrl ( url ) ; const realQuery = { ... query , ... ( params || { } ) , } ; const queryStr = stringify ( realQuery ) ; const realQueryStr = queryStr ? `?${ queryStr }` : '' ; return `${ path }${ realQueryStr }` ; } export default abstract class StackedRouter extends BaseRouter { protected fromuKey = 'fromu' ; param { string } url param { Object ? } params public redirect ( url , params ? ) { const { path , query } = parseUrl ( url ) ; this . change ( path , { ... query , ... params , [ this . fromuKey ] : format ( this . getPath ( ) , this . getQuery ( ) ) , } ) ; } param { number } n public back ( n = 1 , defaultUrl = '/' ) { if ( n < 0 ) { throw new Error ( 'The back steps must be a positive integer.' ) ; } if ( n === 0 ) { return ; } const normalizedN = n - 1 ; const stack = this . parseFromuStack ( this . getQuery ( ) ) ; const targetUrl = stack [ normalizedN ] ; const { path , query } = parseUrl ( targetUrl || defaultUrl ) ; this . change ( path , query ) ; } param { string } url param { number ? } removeStackLength param { Object ? } params public backTo ( url , { removeStackLength = 1 , params = { } , } = { } ) { const normalizedRemovedStackLength = removeStackLength - 1 ; const stack = this . parseFromuStack ( this . getQuery ( ) ) ; const { path , query } = parseUrl ( url ) ; const realQuery = { ... query , ... params } ; if ( stack . length > normalizedRemovedStackLength ) { realQuery [ this . fromuKey ] = stack [ normalizedRemovedStackLength ] ; } this . change ( path , realQuery ) ; } public replace ( url , params ? ) { this . backTo ( url , { params , removeStackLength : Number . POSITIVE_INFINITY } ) ; } public destroy ( ) { super . destroy ( ) ; } param { string } queryString param { Array < string > ? } stack return { Array < string > } private parseFromuStack ( query , stack = [ ] ) { if ( query [ this . fromuKey ] ) { const fromu = query [ this . fromuKey ] ; if ( Array . isArray ( fromu ) ) { throw new Error ( `do not use multiple fromu: ${ JSON . stringify ( query ) }` ) ; } stack . push ( fromu ) ; return this . parseFromuStack ( parse ( fromu . split ( '?' ) [ 1 ] ) as Query , stack ) ; } return stack ; } }