diff --git a/README.md b/README.md index fd90013..a06ba91 100644 --- a/README.md +++ b/README.md @@ -31,11 +31,12 @@ 二进制编译无需Docker容器 -目前仅支持客户端:v2ray clash +目前仅支持客户端:v2ray clash surge v2ray为base64通用格式 clash支持协议:ss ssr trojan vmess vless hy hy2 tuic +surge支持协议:ss trojan vmess hy2 tuic ## [项目预览] diff --git a/api/clients.go b/api/clients.go index 2077cc1..e822282 100644 --- a/api/clients.go +++ b/api/clients.go @@ -6,6 +6,7 @@ import ( "io" "log" "net/http" + "net/url" "strings" "sublink/models" "sublink/node" @@ -29,9 +30,6 @@ func GetV2ray(c *gin.Context) { return } baselist := "" - // for _, v := range sub.Nodes { - // baselist += v.Link + "\n" - // } for _, v := range sub.Nodes { switch { // 如果包含多条节点 @@ -55,9 +53,10 @@ func GetV2ray(c *gin.Context) { baselist += v.Link + "\n" } } - Content_Disposition := fmt.Sprintf("inline; filename=%s.txt", subname) c.Set("subname", subname) - c.Writer.Header().Set("Content-Disposition", Content_Disposition) + filename := fmt.Sprintf("%s.txt", subname) + encodedFilename := url.QueryEscape(filename) + c.Writer.Header().Set("Content-Disposition", "inline; filename*=utf-8''"+encodedFilename) c.Writer.Header().Set("Content-Type", "text/html; charset=utf-8") c.Writer.WriteString(node.Base64Encode(baselist)) } @@ -114,6 +113,72 @@ func GetClash(c *gin.Context) { return } c.Set("subname", subname) - c.Writer.Header().Set("Content-Type", "text/yaml; charset=utf-8") + filename := fmt.Sprintf("%s.yaml", subname) + encodedFilename := url.QueryEscape(filename) + c.Writer.Header().Set("Content-Disposition", "inline; filename*=utf-8''"+encodedFilename) + c.Writer.Header().Set("Content-Type", "text/plain; charset=utf-8") c.Writer.WriteString(string(DecodeClash)) } +func GetSurge(c *gin.Context) { + var sub models.Subcription + subname := c.Param("subname") + subname = node.Base64Decode(subname) + sub.Name = subname + err := sub.Find() + if err != nil { + c.Writer.WriteString("找不到这个订阅:" + subname) + return + } + err = sub.GetSub() + if err != nil { + c.Writer.WriteString("读取错误") + return + } + urls := []string{} + for _, v := range sub.Nodes { + switch { + // 如果包含多条节点 + case strings.Contains(v.Link, ","): + links := strings.Split(v.Link, ",") + urls = append(urls, links...) + continue + //如果是订阅转换 + case strings.Contains(v.Link, "http://") || strings.Contains(v.Link, "https://"): + resp, err := http.Get(v.Link) + if err != nil { + log.Println(err) + return + } + defer resp.Body.Close() + body, _ := io.ReadAll(resp.Body) + nodes := node.Base64Decode(string(body)) + links := strings.Split(nodes, "\n") + urls = append(urls, links...) + // 默认 + default: + urls = append(urls, v.Link) + } + } + + var configs node.SqlConfig + err = json.Unmarshal([]byte(sub.Config), &configs) + if err != nil { + c.Writer.WriteString("配置读取错误") + return + } + // log.Println("surge路径:", configs) + DecodeClash, err := node.EncodeSurge(urls, configs) + if err != nil { + c.Writer.WriteString(err.Error()) + return + } + c.Set("subname", subname) + filename := fmt.Sprintf("%s.conf", subname) + encodedFilename := url.QueryEscape(filename) + c.Writer.Header().Set("Content-Disposition", "inline; filename*=utf-8''"+encodedFilename) + c.Writer.Header().Set("Content-Type", "text/plain; charset=utf-8") + host := c.Request.Host + url := c.Request.URL.String() + interval := fmt.Sprintf("#!MANAGED-CONFIG %s interval=86400 strict=false", host+url) + c.Writer.WriteString(string(interval + "\n" + DecodeClash)) +} diff --git a/main.go b/main.go index e0ba2a2..d3ccffc 100644 --- a/main.go +++ b/main.go @@ -20,27 +20,50 @@ import ( //go:embed static/index.html var embeddedFiles embed.FS -//go:embed template/clash.yaml -var clashTemplate []byte +//go:embed template +var Template embed.FS func Templateinit() { // 设置template路径 // 检查目录是否创建 - _, err := os.Stat("./template/clash.yaml") + Template, err := fs.Sub(embeddedFiles, "template") if err != nil { - if os.IsNotExist(err) { - os.MkdirAll("./template", os.ModePerm) - } + log.Println(err) } - _, err = os.Stat("./template/clash.yaml") - if os.IsNotExist(err) { - err = os.WriteFile("./template/clash.yaml", clashTemplate, 0666) - if err != nil { - log.Println(err) - return + Templates, err := fs.ReadDir(Template, ".") + if err != nil { + log.Println(err) + } + for _, v := range Templates { + _, err := os.Stat("./template/" + v.Name()) + //如果文件不存在则写入默认模板 + if os.IsNotExist(err) { + data, err := fs.ReadFile(Template, v.Name()) + if err != nil { + log.Println(err) + continue + } + err = os.WriteFile("./template/"+v.Name(), data, 0666) + if err != nil { + log.Println(err) + } } } + // _, err := os.Stat("./template/clash.yaml") + // if err != nil { + // if os.IsNotExist(err) { + // os.MkdirAll("./template", os.ModePerm) + // } + // } + // _, err = os.Stat("./template/clash.yaml") + // if os.IsNotExist(err) { + // err = os.WriteFile("./template/clash.yaml", clashTemplate, 0666) + // if err != nil { + // log.Println(err) + // return + // } + // } } func main() { diff --git a/node/clash.go b/node/clash.go index 2880143..69e73bb 100644 --- a/node/clash.go +++ b/node/clash.go @@ -53,11 +53,6 @@ type Config struct { Proxies []Proxy `yaml:"proxies"` Proxy_groups []ProxyGroup `yaml:"proxy-groups"` } -type SqlConfig struct { - Clash string `json:"clash"` - Udp bool `json:"udp"` - Cert bool `json:"cert"` -} // 删除opts中的空值 func DeleteOpts(opts map[string]interface{}) { diff --git a/node/common.go b/node/common.go index 1347de0..65c65c1 100644 --- a/node/common.go +++ b/node/common.go @@ -8,6 +8,13 @@ import ( "strings" ) +type SqlConfig struct { + Clash string `json:"clash"` + Surge string `json:"surge"` + Udp bool `json:"udp"` + Cert bool `json:"cert"` +} + // ipv6地址匹配规则 func ValRetIPv6Addr(s string) string { pattern := `\[([0-9a-fA-F:]+)\]` diff --git a/node/surge.go b/node/surge.go new file mode 100644 index 0000000..cbed908 --- /dev/null +++ b/node/surge.go @@ -0,0 +1,161 @@ +package node + +import ( + "fmt" + "log" + "os" + "regexp" + "strings" +) + +func EncodeSurge(urls []string, sqlconfig SqlConfig) (string, error) { + var proxys, groups []string + for _, link := range urls { + Scheme := strings.Split(link, "://")[0] + switch { + case Scheme == "ss": + ss, err := DecodeSSURL(link) + if err != nil { + log.Println(err) + continue + } + proxy := map[string]interface{}{ + "name": ss.Name, + "server": ss.Server, + "port": ss.Port, + "cipher": ss.Param.Cipher, + "password": ss.Param.Password, + "udp": sqlconfig.Udp, + } + ssproxy := fmt.Sprintf("%s = ss, %s, %d, encrypt-method=%s, password=%s, udp-relay=%t", + proxy["name"], proxy["server"], proxy["port"], proxy["cipher"], proxy["password"], proxy["udp"]) + groups = append(groups, ss.Name) + proxys = append(proxys, ssproxy) + case Scheme == "vmess": + vmess, err := DecodeVMESSURL(link) + if err != nil { + log.Println(err) + continue + } + tls := false + if vmess.Tls != "none" && vmess.Tls != "" { + tls = true + } + proxy := map[string]interface{}{ + "name": vmess.Ps, + "server": vmess.Add, + "port": vmess.Port, + "uuid": vmess.Id, + "tls": tls, + "network": vmess.Net, + "ws-path": vmess.Path, + "ws-host": vmess.Host, + "udp": sqlconfig.Udp, + "skip-cert-verify": sqlconfig.Cert, + } + + vmessproxy := fmt.Sprintf("%s = vmess, %s, %d, username=%s , tls=%s, vmess-aead=true, udp-relay=%t , skip-cert-verify=%t", + proxy["name"], proxy["server"], proxy["port"], proxy["uuid"], proxy["tls"], proxy["udp"], proxy["skip-cert-verify"]) + if vmess.Net == "ws" { + vmessproxy = fmt.Sprintf("%s, ws=true,ws-path=%s", vmessproxy, proxy["ws-path"]) + if vmess.Host != "" && vmess.Host != "none" { + vmessproxy = fmt.Sprintf("%s, ws-headers=Host:%s", vmessproxy, proxy["ws-host"]) + } + } + if vmess.Sni != "" { + vmessproxy = fmt.Sprintf("%s, sni=%s", vmessproxy, vmess.Sni) + } + groups = append(groups, vmess.Ps) + proxys = append(proxys, vmessproxy) + case Scheme == "trojan": + trojan, err := DecodeTrojanURL(link) + if err != nil { + log.Println(err) + continue + } + proxy := map[string]interface{}{ + "name": trojan.Name, + "server": trojan.Hostname, + "port": trojan.Port, + "password": trojan.Password, + "udp": sqlconfig.Udp, + "skip-cert-verify": sqlconfig.Cert, + } + trojanproxy := fmt.Sprintf("%s = trojan, %s, %d, password=%s, udp-relay=%t, skip-cert-verify=%t", + proxy["name"], proxy["server"], proxy["port"], proxy["password"], proxy["udp"], proxy["skip-cert-verify"]) + if trojan.Query.Sni != "" { + trojanproxy = fmt.Sprintf("%s, sni=%s", trojanproxy, trojan.Query.Sni) + + } + groups = append(groups, trojan.Name) + proxys = append(proxys, trojanproxy) + case Scheme == "hysteria2" || Scheme == "hy2": + hy2, err := DecodeHY2URL(link) + if err != nil { + log.Println(err) + continue + } + proxy := map[string]interface{}{ + "name": hy2.Name, + "server": hy2.Host, + "port": hy2.Port, + "password": hy2.Password, + "udp": sqlconfig.Udp, + "skip-cert-verify": sqlconfig.Cert, + } + hy2proxy := fmt.Sprintf("%s = hy2, %s, %d, password=%s, udp-relay=%t, skip-cert-verify=%t", + proxy["name"], proxy["server"], proxy["port"], proxy["password"], proxy["udp"], proxy["skip-cert-verify"]) + if hy2.Sni != "" { + hy2proxy = fmt.Sprintf("%s, sni=%s", hy2proxy, hy2.Sni) + + } + groups = append(groups, hy2.Name) + proxys = append(proxys, hy2proxy) + case Scheme == "tuic": + tuic, err := DecodeTuicURL(link) + if err != nil { + log.Println(err) + continue + } + proxy := map[string]interface{}{ + "name": tuic.Name, + "server": tuic.Host, + "port": tuic.Port, + "password": tuic.Password, + "udp": sqlconfig.Udp, + "skip-cert-verify": sqlconfig.Cert, + } + tuicproxy := fmt.Sprintf("%s = tuic, %s, %d, token=%s, udp-relay=%t, skip-cert-verify=%t", + proxy["name"], proxy["server"], proxy["port"], proxy["password"], proxy["udp"], proxy["skip-cert-verify"]) + groups = append(groups, tuic.Name) + proxys = append(proxys, tuicproxy) + } + } + return DecodeSurge(proxys, groups, sqlconfig.Surge) +} +func DecodeSurge(proxys, groups []string, file string) (string, error) { + surge, err := os.ReadFile(file) + if err != nil { + log.Println(err) + return "", err + } + proxyReg := regexp.MustCompile(`(?s)\[Proxy\](.*?)\[*]`) + groupReg := regexp.MustCompile(`(?s)\[Proxy Group\](.*?)\[*]`) + + proxyPart := proxyReg.ReplaceAllStringFunc(string(surge), func(s string) string { + + text := strings.Join(proxys, "\n") + return "[Proxy]\n" + text + s[len("[Proxy]"):] + }) + groupPart := groupReg.ReplaceAllStringFunc(proxyPart, func(s string) string { + lines := strings.Split(s, "\n") + grouplist := strings.Join(groups, ",") + for i, line := range lines { + if strings.Contains(line, "=") { + lines[i] = line + "," + grouplist + } + } + return strings.Join(lines, "\n") + s[len("[Proxy Group]"):] + }) + return groupPart, nil +} diff --git a/node/trojan.go b/node/trojan.go index 9c25f82..df926e5 100644 --- a/node/trojan.go +++ b/node/trojan.go @@ -99,7 +99,7 @@ func DecodeTrojanURL(s string) (Trojan, error) { if u.Scheme != "trojan" { return Trojan{}, fmt.Errorf("非trojan协议: %s", s) } - password := Base64Decode2(u.User.Username()) + password := u.User.Username() hostname := u.Hostname() port, _ := strconv.Atoi(u.Port()) peer := u.Query().Get("peer") diff --git a/routers/clients.go b/routers/clients.go index 1a215df..0c58775 100644 --- a/routers/clients.go +++ b/routers/clients.go @@ -13,6 +13,7 @@ func Clients(r *gin.Engine) { { ClientsGroup.GET("/v2ray/:subname", api.GetV2ray) ClientsGroup.GET("/clash/:subname", api.GetClash) + ClientsGroup.GET("/surge/:subname", api.GetSurge) } } diff --git a/static/css/subs.DCunInJu.css b/static/css/subs.DCunInJu.css new file mode 100644 index 0000000..eb650d9 --- /dev/null +++ b/static/css/subs.DCunInJu.css @@ -0,0 +1 @@ +.el-checkbox-group{font-size:0;line-height:0}.el-card[data-v-4bd1fff0]{margin:10px}.el-input[data-v-4bd1fff0]{margin-bottom:10px}.el-tag[data-v-4bd1fff0]{margin:5px} diff --git a/static/css/subs.DwtIKdSy.css b/static/css/subs.DwtIKdSy.css deleted file mode 100644 index 8ae3bd7..0000000 --- a/static/css/subs.DwtIKdSy.css +++ /dev/null @@ -1 +0,0 @@ -.el-checkbox-group{font-size:0;line-height:0}.el-card[data-v-c713c54c]{margin:10px}.el-input[data-v-c713c54c]{margin-bottom:10px}.el-tag[data-v-c713c54c]{margin:5px} diff --git a/static/index.html b/static/index.html index b420670..93e39a1 100644 --- a/static/index.html +++ b/static/index.html @@ -5,7 +5,7 @@
{Array.isArray(e)||(e=[e]);const l={};return e.forEach((e=>{k.value[e.id]=t,l[e.columnKey||e.id]=t})),l},updateCurrentRow:Z,updateSort:P,execFilter:B,execSort:$,execQuery:(e=void 0)=>{e&&e.filter||B(),$()},clearFilter:e=>{const{tableHeaderRef:l}=t.refs;if(!l)return;const a=Object.assign({},l.filterPanels),n=Object.keys(a);if(n.length)if("string"==typeof e&&(e=[e]),Array.isArray(e)){const l=e.map((e=>Oa({columns:u.value},e)));n.forEach((e=>{const t=l.find((t=>t.id===e));t&&(t.filteredValue=[])})),t.store.commit("filterChange",{column:l,values:[],silent:!0,multi:!0})}else n.forEach((e=>{const t=u.value.find((t=>t.id===e));t&&(t.filteredValue=[])})),k.value={},t.store.commit("filterChange",{column:{},values:[],silent:!0})},clearSort:()=>{L.value&&(P(null,null,null),t.store.commit("changeSortCondition",{silent:!0}))},toggleRowExpansion:V,setExpandRowKeysAdapter:e=>{I(e),q(e)},setCurrentRowKey:J,toggleRowExpansionAdapter:(e,t)=>{u.value.some((({type:e})=>"expand"===e))?V(e,t):Y(e,t)},isRowExpanded:D,updateExpandRows:_,updateCurrentRowData:Q,loadOrToggle:G,updateTreeData:U,states:{tableSize:l,rowKey:a,data:n,_data:o,isComplex:r,_columns:s,originColumns:i,columns:u,fixedColumns:d,rightFixedColumns:c,leafColumns:p,fixedLeafColumns:v,rightFixedLeafColumns:h,updateOrderFns:[],leafColumnsLength:f,fixedLeafColumnsLength:m,rightFixedLeafColumnsLength:g,isAllSelected:b,selection:y,reserveSelection:x,selectOnIndeterminate:C,selectable:S,filters:k,filteredData:R,sortingColumn:L,sortProp:M,sortOrder:F,hoverRow:A,...j,...X,...ee}}}function Ua(e,t){return e.map((e=>{var l;return e.id===t.id?t:((null==(l=e.children)?void 0:l.length)&&(e.children=Ua(e.children,t)),e)}))}function Ga(e){e.forEach((e=>{var t,l;e.no=null==(t=e.getColumnIndex)?void 0:t.call(e),(null==(l=e.children)?void 0:l.length)&&Ga(e.children)})),e.sort(((e,t)=>e.no-t.no))}const Xa={rowKey:"rowKey",defaultExpandAll:"defaultExpandAll",selectOnIndeterminate:"selectOnIndeterminate",indent:"indent",lazy:"lazy",data:"data","treeProps.hasChildren":{key:"lazyColumnIdentifier",default:"hasChildren"},"treeProps.children":{key:"childrenColumnName",default:"children"}};function Qa(e,t){if(!e)throw new Error("Table is required.");const l=function(){const e=E(),t=Ya();return{ns:$("table"),...t,mutations:{setData(t,l){const a=K(t._data)!==l;t.data.value=l,t._data.value=l,e.store.execQuery(),e.store.updateCurrentRowData(),e.store.updateExpandRows(),e.store.updateTreeData(e.store.states.defaultExpandAll.value),K(t.reserveSelection)?(e.store.assertRowKey(),e.store.updateSelectionByRowKey()):a?e.store.clearSelection():e.store.cleanSelection(),e.store.updateAllSelected(),e.$ready&&e.store.scheduleLayout()},insertColumn(t,l,a,n){const o=K(t._columns);let r=[];a?(a&&!a.children&&(a.children=[]),a.children.push(l),r=Ua(o,a)):(o.push(l),r=o),Ga(r),t._columns.value=r,t.updateOrderFns.push(n),"selection"===l.type&&(t.selectable.value=l.selectable,t.reserveSelection.value=l.reserveSelection),e.$ready&&(e.store.updateColumns(),e.store.scheduleLayout())},updateColumnOrder(t,l){var a;(null==(a=l.getColumnIndex)?void 0:a.call(l))!==l.no&&(Ga(t._columns.value),e.$ready&&e.store.updateColumns())},removeColumn(t,l,a,n){const o=K(t._columns)||[];if(a)a.children.splice(a.children.findIndex((e=>e.id===l.id)),1),L((()=>{var e;0===(null==(e=a.children)?void 0:e.length)&&delete a.children})),t._columns.value=Ua(o,a);else{const e=o.indexOf(l);e>-1&&(o.splice(e,1),t._columns.value=o)}const r=t.updateOrderFns.indexOf(n);r>-1&&t.updateOrderFns.splice(r,1),e.$ready&&(e.store.updateColumns(),e.store.scheduleLayout())},sort(t,l){const{prop:a,order:n,init:o}=l;if(a){const l=K(t.columns).find((e=>e.property===a));l&&(l.order=n,e.store.updateSort(l,a,n),e.store.commit("changeSortCondition",{init:o}))}},changeSortCondition(t,l){const{sortingColumn:a,sortProp:n,sortOrder:o}=t,r=K(a),s=K(n),i=K(o);null===i&&(t.sortingColumn.value=null,t.sortProp.value=null),e.store.execQuery({filter:!0}),l&&(l.silent||l.init)||e.emit("sort-change",{column:r,prop:s,order:i}),e.store.updateTableScrollY()},filterChange(t,l){const{column:a,values:n,silent:o}=l,r=e.store.updateFilters(a,n);e.store.execQuery(),o||e.emit("filter-change",r),e.store.updateTableScrollY()},toggleAllSelection(){e.store.toggleAllSelection()},rowSelectedChanged(t,l){e.store.toggleRowSelection(l),e.store.updateAllSelected()},setHoverRow(e,t){e.hoverRow.value=t},setCurrentRow(t,l){e.store.updateCurrentRow(l)}},commit:function(t,...l){const a=e.store.mutations;if(!a[t])throw new Error(`Action not found: ${t}`);a[t].apply(e,[e.store.states].concat(l))},updateTableScrollY:function(){L((()=>e.layout.updateScrollY.apply(e.layout)))}}}();return l.toggleAllSelection=bt(l._toggleAllSelection,10),Object.keys(Xa).forEach((e=>{Za(Ja(t,e),e,l)})),function(e,t){Object.keys(Xa).forEach((l=>{N((()=>Ja(t,l)),(t=>{Za(t,l,e)}))}))}(l,t),l}function Za(e,t,l){let a=e,n=Xa[t];"object"==typeof Xa[t]&&(n=n.key,a=a||Xa[t].default),l.states[n].value=a}function Ja(e,t){if(t.includes(".")){const l=t.split(".");let a=e;return l.forEach((e=>{a=a[e]})),a}return e[t]}class en{constructor(e){this.observers=[],this.table=null,this.store=null,this.columns=[],this.fit=!0,this.showHeader=!0,this.height=O(null),this.scrollX=O(!1),this.scrollY=O(!1),this.bodyWidth=O(null),this.fixedWidth=O(null),this.rightFixedWidth=O(null),this.gutterWidth=0;for(const t in e)Re(e,t)&&(U(this[t])?this[t].value=e[t]:this[t]=e[t]);if(!this.table)throw new Error("Table is required for Table Layout");if(!this.store)throw new Error("Store is required for Table Layout")}updateScrollY(){if(null===this.height.value)return!1;const e=this.table.refs.scrollBarRef;if(this.table.vnode.el&&(null==e?void 0:e.wrapRef)){let t=!0;const l=this.scrollY.value;return t=e.wrapRef.scrollHeight>e.wrapRef.clientHeight,this.scrollY.value=t,l!==t}return!1}setHeight(e,t="height"){if(!h)return;const l=this.table.vnode.el;var a;if(e="number"==typeof(a=e)?a:"string"==typeof a?/^\d+(?:px)?$/.test(a)?Number.parseInt(a,10):a:null,this.height.value=Number(e),!l&&(e||0===e))return L((()=>this.setHeight(e,t)));"number"==typeof e?(l.style[t]=`${e}px`,this.updateElsHeight()):"string"==typeof e&&(l.style[t]=e,this.updateElsHeight())}setMaxHeight(e){this.setHeight(e,"max-height")}getFlattenColumns(){const e=[];return this.table.store.states.columns.value.forEach((t=>{t.isColumnGroup?e.push.apply(e,t.columns):e.push(t)})),e}updateElsHeight(){this.updateScrollY(),this.notifyObservers("scrollable")}headerDisplayNone(e){if(!e)return!0;let t=e;for(;"DIV"!==t.tagName;){if("none"===getComputedStyle(t).display)return!0;t=t.parentElement}return!1}updateColumnsWidth(){if(!h)return;const e=this.fit,t=this.table.vnode.el.clientWidth;let l=0;const a=this.getFlattenColumns(),n=a.filter((e=>"number"!=typeof e.width));if(a.forEach((e=>{"number"==typeof e.width&&e.realWidth&&(e.realWidth=null)})),n.length>0&&e){if(a.forEach((e=>{l+=Number(e.width||e.minWidth||80)})),l<=t){this.scrollX.value=!1;const e=t-l;if(1===n.length)n[0].realWidth=Number(n[0].minWidth||80)+e;else{const t=e/n.reduce(((e,t)=>e+Number(t.minWidth||80)),0);let l=0;n.forEach(((e,a)=>{if(0===a)return;const n=Math.floor(Number(e.minWidth||80)*t);l+=n,e.realWidth=Number(e.minWidth||80)+n})),n[0].realWidth=Number(n[0].minWidth||80)+e-l}}else this.scrollX.value=!0,n.forEach((e=>{e.realWidth=Number(e.minWidth)}));this.bodyWidth.value=Math.max(l,t),this.table.state.resizeState.value.width=this.bodyWidth.value}else a.forEach((e=>{e.width||e.minWidth?e.realWidth=Number(e.width||e.minWidth):e.realWidth=80,l+=e.realWidth})),this.scrollX.value=l>t,this.bodyWidth.value=l;const o=this.store.states.fixedColumns.value;if(o.length>0){let e=0;o.forEach((t=>{e+=Number(t.realWidth||t.width)})),this.fixedWidth.value=e}const r=this.store.states.rightFixedColumns.value;if(r.length>0){let e=0;r.forEach((t=>{e+=Number(t.realWidth||t.width)})),this.rightFixedWidth.value=e}this.notifyObservers("columns")}addObserver(e){this.observers.push(e)}removeObserver(e){const t=this.observers.indexOf(e);-1!==t&&this.observers.splice(t,1)}notifyObservers(e){this.observers.forEach((t=>{var l,a;switch(e){case"columns":null==(l=t.state)||l.onColumnsChange(this);break;case"scrollable":null==(a=t.state)||a.onScrollableChange(this);break;default:throw new Error(`Table Layout don't have event ${e}.`)}}))}}const{CheckboxGroup:tn}=Vl,ln=P({name:"ElTableFilterPanel",components:{ElCheckbox:Vl,ElCheckboxGroup:tn,ElScrollbar:lt,ElTooltip:at,ElIcon:ve,ArrowDown:Fe,ArrowUp:Ae},directives:{ClickOutside:yt},props:{placement:{type:String,default:"bottom-start"},store:{type:Object},column:{type:Object},upDataColumn:{type:Function}},setup(e){const t=E(),{t:l}=pe(),a=$("table-filter"),n=null==t?void 0:t.parent;n.filterPanels.value[e.column.id]||(n.filterPanels.value[e.column.id]=t);const o=O(!1),r=O(null),s=w((()=>e.column&&e.column.filters)),i=w((()=>e.column.filterClassName?`${a.b()} ${e.column.filterClassName}`:a.b())),u=w({get:()=>{var t;return((null==(t=e.column)?void 0:t.filteredValue)||[])[0]},set:e=>{d.value&&(null!=e?d.value.splice(0,1,e):d.value.splice(0,1))}}),d=w({get:()=>e.column&&e.column.filteredValue||[],set(t){e.column&&e.upDataColumn("filteredValue",t)}}),c=w((()=>!e.column||e.column.filterMultiple)),p=()=>{o.value=!1},v=t=>{e.store.commit("filterChange",{column:e.column,values:t}),e.store.updateAllSelected()};N(o,(t=>{e.column&&e.upDataColumn("filterOpened",t)}),{immediate:!0});const h=w((()=>{var e,t;return null==(t=null==(e=r.value)?void 0:e.popperRef)?void 0:t.contentRef}));return{tooltipVisible:o,multiple:c,filterClassName:i,filteredValue:d,filterValue:u,filters:s,handleConfirm:()=>{v(d.value),p()},handleReset:()=>{d.value=[],v(d.value),p()},handleSelect:e=>{u.value=e,v(null!=e?d.value:[]),p()},isActive:e=>e.value===u.value,t:l,ns:a,showFilterPanel:e=>{e.stopPropagation(),o.value=!o.value},hideFilterPanel:()=>{o.value=!1},popperPaneRef:h,tooltip:r}}}),an={key:0},nn=["disabled"],on=["label","onClick"];var rn=ae(ln,[["render",function(e,t,l,a,n,o){const r=ze("el-checkbox"),s=ze("el-checkbox-group"),i=ze("el-scrollbar"),u=ze("arrow-up"),d=ze("arrow-down"),c=ze("el-icon"),p=ze("el-tooltip"),v=We("click-outside");return I(),V(p,{ref:"tooltip",visible:e.tooltipVisible,offset:0,placement:e.placement,"show-arrow":!1,"stop-popper-mouse-event":!1,teleported:"",effect:"light",pure:"","popper-class":e.filterClassName,persistent:""},{content:_((()=>[e.multiple?(I(),Y("div",an,[j("div",{class:D(e.ns.e("content"))},[me(i,{"wrap-class":e.ns.e("wrap")},{default:_((()=>[me(s,{modelValue:e.filteredValue,"onUpdate:modelValue":t[0]||(t[0]=t=>e.filteredValue=t),class:D(e.ns.e("checkbox-group"))},{default:_((()=>[(I(!0),Y(Z,null,ge(e.filters,(e=>(I(),V(r,{key:e.value,value:e.value},{default:_((()=>[J(ee(e.text),1)])),_:2},1032,["value"])))),128))])),_:1},8,["modelValue","class"])])),_:1},8,["wrap-class"])],2),j("div",{class:D(e.ns.e("bottom"))},[j("button",{class:D({[e.ns.is("disabled")]:0===e.filteredValue.length}),disabled:0===e.filteredValue.length,type:"button",onClick:t[1]||(t[1]=(...t)=>e.handleConfirm&&e.handleConfirm(...t))},ee(e.t("el.table.confirmFilter")),11,nn),j("button",{type:"button",onClick:t[2]||(t[2]=(...t)=>e.handleReset&&e.handleReset(...t))},ee(e.t("el.table.resetFilter")),1)],2)])):(I(),Y("ul",{key:1,class:D(e.ns.e("list"))},[j("li",{class:D([e.ns.e("list-item"),{[e.ns.is("active")]:void 0===e.filterValue||null===e.filterValue}]),onClick:t[3]||(t[3]=t=>e.handleSelect(null))},ee(e.t("el.table.clearFilter")),3),(I(!0),Y(Z,null,ge(e.filters,(t=>(I(),Y("li",{key:t.value,class:D([e.ns.e("list-item"),e.ns.is("active",e.isActive(t))]),label:t.value,onClick:l=>e.handleSelect(t.value)},ee(t.text),11,on)))),128))],2))])),default:_((()=>[q((I(),Y("span",{class:D([`${e.ns.namespace.value}-table__column-filter-trigger`,`${e.ns.namespace.value}-none-outline`]),onClick:t[4]||(t[4]=(...t)=>e.showFilterPanel&&e.showFilterPanel(...t))},[me(c,null,{default:_((()=>[e.column.filterOpened?(I(),V(u,{key:0})):(I(),V(d,{key:1}))])),_:1})],2)),[[v,e.hideFilterPanel,e.popperPaneRef]])])),_:1},8,["visible","placement","popper-class"])}],["__file","filter-panel.vue"]]);function sn(e){const t=E();He((()=>{l.value.addObserver(t)})),Te((()=>{a(l.value),n(l.value)})),Pe((()=>{a(l.value),n(l.value)})),Be((()=>{l.value.removeObserver(t)}));const l=w((()=>{const t=e.layout;if(!t)throw new Error("Can not find table layout.");return t})),a=t=>{var l;const a=(null==(l=e.vnode.el)?void 0:l.querySelectorAll("colgroup > col"))||[];if(!a.length)return;const n=t.getFlattenColumns(),o={};n.forEach((e=>{o[e.id]=e}));for(let e=0,r=a.length;e {Array.isArray(e)||(e=[e]);const l={};return e.forEach((e=>{k.value[e.id]=t,l[e.columnKey||e.id]=t})),l},updateCurrentRow:Z,updateSort:P,execFilter:B,execSort:$,execQuery:(e=void 0)=>{e&&e.filter||B(),$()},clearFilter:e=>{const{tableHeaderRef:l}=t.refs;if(!l)return;const a=Object.assign({},l.filterPanels),n=Object.keys(a);if(n.length)if("string"==typeof e&&(e=[e]),Array.isArray(e)){const l=e.map((e=>Oa({columns:u.value},e)));n.forEach((e=>{const t=l.find((t=>t.id===e));t&&(t.filteredValue=[])})),t.store.commit("filterChange",{column:l,values:[],silent:!0,multi:!0})}else n.forEach((e=>{const t=u.value.find((t=>t.id===e));t&&(t.filteredValue=[])})),k.value={},t.store.commit("filterChange",{column:{},values:[],silent:!0})},clearSort:()=>{L.value&&(P(null,null,null),t.store.commit("changeSortCondition",{silent:!0}))},toggleRowExpansion:V,setExpandRowKeysAdapter:e=>{I(e),q(e)},setCurrentRowKey:J,toggleRowExpansionAdapter:(e,t)=>{u.value.some((({type:e})=>"expand"===e))?V(e,t):Y(e,t)},isRowExpanded:D,updateExpandRows:_,updateCurrentRowData:Q,loadOrToggle:G,updateTreeData:U,states:{tableSize:l,rowKey:a,data:n,_data:o,isComplex:r,_columns:s,originColumns:i,columns:u,fixedColumns:d,rightFixedColumns:c,leafColumns:p,fixedLeafColumns:v,rightFixedLeafColumns:h,updateOrderFns:[],leafColumnsLength:f,fixedLeafColumnsLength:m,rightFixedLeafColumnsLength:g,isAllSelected:b,selection:y,reserveSelection:x,selectOnIndeterminate:C,selectable:S,filters:k,filteredData:R,sortingColumn:L,sortProp:M,sortOrder:F,hoverRow:A,...j,...X,...ee}}}function Ua(e,t){return e.map((e=>{var l;return e.id===t.id?t:((null==(l=e.children)?void 0:l.length)&&(e.children=Ua(e.children,t)),e)}))}function Ga(e){e.forEach((e=>{var t,l;e.no=null==(t=e.getColumnIndex)?void 0:t.call(e),(null==(l=e.children)?void 0:l.length)&&Ga(e.children)})),e.sort(((e,t)=>e.no-t.no))}const Xa={rowKey:"rowKey",defaultExpandAll:"defaultExpandAll",selectOnIndeterminate:"selectOnIndeterminate",indent:"indent",lazy:"lazy",data:"data","treeProps.hasChildren":{key:"lazyColumnIdentifier",default:"hasChildren"},"treeProps.children":{key:"childrenColumnName",default:"children"}};function Qa(e,t){if(!e)throw new Error("Table is required.");const l=function(){const e=E(),t=Ya();return{ns:$("table"),...t,mutations:{setData(t,l){const a=K(t._data)!==l;t.data.value=l,t._data.value=l,e.store.execQuery(),e.store.updateCurrentRowData(),e.store.updateExpandRows(),e.store.updateTreeData(e.store.states.defaultExpandAll.value),K(t.reserveSelection)?(e.store.assertRowKey(),e.store.updateSelectionByRowKey()):a?e.store.clearSelection():e.store.cleanSelection(),e.store.updateAllSelected(),e.$ready&&e.store.scheduleLayout()},insertColumn(t,l,a,n){const o=K(t._columns);let r=[];a?(a&&!a.children&&(a.children=[]),a.children.push(l),r=Ua(o,a)):(o.push(l),r=o),Ga(r),t._columns.value=r,t.updateOrderFns.push(n),"selection"===l.type&&(t.selectable.value=l.selectable,t.reserveSelection.value=l.reserveSelection),e.$ready&&(e.store.updateColumns(),e.store.scheduleLayout())},updateColumnOrder(t,l){var a;(null==(a=l.getColumnIndex)?void 0:a.call(l))!==l.no&&(Ga(t._columns.value),e.$ready&&e.store.updateColumns())},removeColumn(t,l,a,n){const o=K(t._columns)||[];if(a)a.children.splice(a.children.findIndex((e=>e.id===l.id)),1),L((()=>{var e;0===(null==(e=a.children)?void 0:e.length)&&delete a.children})),t._columns.value=Ua(o,a);else{const e=o.indexOf(l);e>-1&&(o.splice(e,1),t._columns.value=o)}const r=t.updateOrderFns.indexOf(n);r>-1&&t.updateOrderFns.splice(r,1),e.$ready&&(e.store.updateColumns(),e.store.scheduleLayout())},sort(t,l){const{prop:a,order:n,init:o}=l;if(a){const l=K(t.columns).find((e=>e.property===a));l&&(l.order=n,e.store.updateSort(l,a,n),e.store.commit("changeSortCondition",{init:o}))}},changeSortCondition(t,l){const{sortingColumn:a,sortProp:n,sortOrder:o}=t,r=K(a),s=K(n),i=K(o);null===i&&(t.sortingColumn.value=null,t.sortProp.value=null),e.store.execQuery({filter:!0}),l&&(l.silent||l.init)||e.emit("sort-change",{column:r,prop:s,order:i}),e.store.updateTableScrollY()},filterChange(t,l){const{column:a,values:n,silent:o}=l,r=e.store.updateFilters(a,n);e.store.execQuery(),o||e.emit("filter-change",r),e.store.updateTableScrollY()},toggleAllSelection(){e.store.toggleAllSelection()},rowSelectedChanged(t,l){e.store.toggleRowSelection(l),e.store.updateAllSelected()},setHoverRow(e,t){e.hoverRow.value=t},setCurrentRow(t,l){e.store.updateCurrentRow(l)}},commit:function(t,...l){const a=e.store.mutations;if(!a[t])throw new Error(`Action not found: ${t}`);a[t].apply(e,[e.store.states].concat(l))},updateTableScrollY:function(){L((()=>e.layout.updateScrollY.apply(e.layout)))}}}();return l.toggleAllSelection=bt(l._toggleAllSelection,10),Object.keys(Xa).forEach((e=>{Za(Ja(t,e),e,l)})),function(e,t){Object.keys(Xa).forEach((l=>{N((()=>Ja(t,l)),(t=>{Za(t,l,e)}))}))}(l,t),l}function Za(e,t,l){let a=e,n=Xa[t];"object"==typeof Xa[t]&&(n=n.key,a=a||Xa[t].default),l.states[n].value=a}function Ja(e,t){if(t.includes(".")){const l=t.split(".");let a=e;return l.forEach((e=>{a=a[e]})),a}return e[t]}class en{constructor(e){this.observers=[],this.table=null,this.store=null,this.columns=[],this.fit=!0,this.showHeader=!0,this.height=O(null),this.scrollX=O(!1),this.scrollY=O(!1),this.bodyWidth=O(null),this.fixedWidth=O(null),this.rightFixedWidth=O(null),this.gutterWidth=0;for(const t in e)Re(e,t)&&(U(this[t])?this[t].value=e[t]:this[t]=e[t]);if(!this.table)throw new Error("Table is required for Table Layout");if(!this.store)throw new Error("Store is required for Table Layout")}updateScrollY(){if(null===this.height.value)return!1;const e=this.table.refs.scrollBarRef;if(this.table.vnode.el&&(null==e?void 0:e.wrapRef)){let t=!0;const l=this.scrollY.value;return t=e.wrapRef.scrollHeight>e.wrapRef.clientHeight,this.scrollY.value=t,l!==t}return!1}setHeight(e,t="height"){if(!h)return;const l=this.table.vnode.el;var a;if(e="number"==typeof(a=e)?a:"string"==typeof a?/^\d+(?:px)?$/.test(a)?Number.parseInt(a,10):a:null,this.height.value=Number(e),!l&&(e||0===e))return L((()=>this.setHeight(e,t)));"number"==typeof e?(l.style[t]=`${e}px`,this.updateElsHeight()):"string"==typeof e&&(l.style[t]=e,this.updateElsHeight())}setMaxHeight(e){this.setHeight(e,"max-height")}getFlattenColumns(){const e=[];return this.table.store.states.columns.value.forEach((t=>{t.isColumnGroup?e.push.apply(e,t.columns):e.push(t)})),e}updateElsHeight(){this.updateScrollY(),this.notifyObservers("scrollable")}headerDisplayNone(e){if(!e)return!0;let t=e;for(;"DIV"!==t.tagName;){if("none"===getComputedStyle(t).display)return!0;t=t.parentElement}return!1}updateColumnsWidth(){if(!h)return;const e=this.fit,t=this.table.vnode.el.clientWidth;let l=0;const a=this.getFlattenColumns(),n=a.filter((e=>"number"!=typeof e.width));if(a.forEach((e=>{"number"==typeof e.width&&e.realWidth&&(e.realWidth=null)})),n.length>0&&e){if(a.forEach((e=>{l+=Number(e.width||e.minWidth||80)})),l<=t){this.scrollX.value=!1;const e=t-l;if(1===n.length)n[0].realWidth=Number(n[0].minWidth||80)+e;else{const t=e/n.reduce(((e,t)=>e+Number(t.minWidth||80)),0);let l=0;n.forEach(((e,a)=>{if(0===a)return;const n=Math.floor(Number(e.minWidth||80)*t);l+=n,e.realWidth=Number(e.minWidth||80)+n})),n[0].realWidth=Number(n[0].minWidth||80)+e-l}}else this.scrollX.value=!0,n.forEach((e=>{e.realWidth=Number(e.minWidth)}));this.bodyWidth.value=Math.max(l,t),this.table.state.resizeState.value.width=this.bodyWidth.value}else a.forEach((e=>{e.width||e.minWidth?e.realWidth=Number(e.width||e.minWidth):e.realWidth=80,l+=e.realWidth})),this.scrollX.value=l>t,this.bodyWidth.value=l;const o=this.store.states.fixedColumns.value;if(o.length>0){let e=0;o.forEach((t=>{e+=Number(t.realWidth||t.width)})),this.fixedWidth.value=e}const r=this.store.states.rightFixedColumns.value;if(r.length>0){let e=0;r.forEach((t=>{e+=Number(t.realWidth||t.width)})),this.rightFixedWidth.value=e}this.notifyObservers("columns")}addObserver(e){this.observers.push(e)}removeObserver(e){const t=this.observers.indexOf(e);-1!==t&&this.observers.splice(t,1)}notifyObservers(e){this.observers.forEach((t=>{var l,a;switch(e){case"columns":null==(l=t.state)||l.onColumnsChange(this);break;case"scrollable":null==(a=t.state)||a.onScrollableChange(this);break;default:throw new Error(`Table Layout don't have event ${e}.`)}}))}}const{CheckboxGroup:tn}=Vl,ln=P({name:"ElTableFilterPanel",components:{ElCheckbox:Vl,ElCheckboxGroup:tn,ElScrollbar:lt,ElTooltip:at,ElIcon:ve,ArrowDown:Fe,ArrowUp:Ae},directives:{ClickOutside:yt},props:{placement:{type:String,default:"bottom-start"},store:{type:Object},column:{type:Object},upDataColumn:{type:Function}},setup(e){const t=E(),{t:l}=pe(),a=$("table-filter"),n=null==t?void 0:t.parent;n.filterPanels.value[e.column.id]||(n.filterPanels.value[e.column.id]=t);const o=O(!1),r=O(null),s=w((()=>e.column&&e.column.filters)),i=w((()=>e.column.filterClassName?`${a.b()} ${e.column.filterClassName}`:a.b())),u=w({get:()=>{var t;return((null==(t=e.column)?void 0:t.filteredValue)||[])[0]},set:e=>{d.value&&(null!=e?d.value.splice(0,1,e):d.value.splice(0,1))}}),d=w({get:()=>e.column&&e.column.filteredValue||[],set(t){e.column&&e.upDataColumn("filteredValue",t)}}),c=w((()=>!e.column||e.column.filterMultiple)),p=()=>{o.value=!1},v=t=>{e.store.commit("filterChange",{column:e.column,values:t}),e.store.updateAllSelected()};N(o,(t=>{e.column&&e.upDataColumn("filterOpened",t)}),{immediate:!0});const h=w((()=>{var e,t;return null==(t=null==(e=r.value)?void 0:e.popperRef)?void 0:t.contentRef}));return{tooltipVisible:o,multiple:c,filterClassName:i,filteredValue:d,filterValue:u,filters:s,handleConfirm:()=>{v(d.value),p()},handleReset:()=>{d.value=[],v(d.value),p()},handleSelect:e=>{u.value=e,v(null!=e?d.value:[]),p()},isActive:e=>e.value===u.value,t:l,ns:a,showFilterPanel:e=>{e.stopPropagation(),o.value=!o.value},hideFilterPanel:()=>{o.value=!1},popperPaneRef:h,tooltip:r}}}),an={key:0},nn=["disabled"],on=["label","onClick"];var rn=ae(ln,[["render",function(e,t,l,a,n,o){const r=ze("el-checkbox"),s=ze("el-checkbox-group"),i=ze("el-scrollbar"),u=ze("arrow-up"),d=ze("arrow-down"),c=ze("el-icon"),p=ze("el-tooltip"),v=We("click-outside");return I(),V(p,{ref:"tooltip",visible:e.tooltipVisible,offset:0,placement:e.placement,"show-arrow":!1,"stop-popper-mouse-event":!1,teleported:"",effect:"light",pure:"","popper-class":e.filterClassName,persistent:""},{content:_((()=>[e.multiple?(I(),Y("div",an,[j("div",{class:D(e.ns.e("content"))},[me(i,{"wrap-class":e.ns.e("wrap")},{default:_((()=>[me(s,{modelValue:e.filteredValue,"onUpdate:modelValue":t[0]||(t[0]=t=>e.filteredValue=t),class:D(e.ns.e("checkbox-group"))},{default:_((()=>[(I(!0),Y(Z,null,ge(e.filters,(e=>(I(),V(r,{key:e.value,value:e.value},{default:_((()=>[J(ee(e.text),1)])),_:2},1032,["value"])))),128))])),_:1},8,["modelValue","class"])])),_:1},8,["wrap-class"])],2),j("div",{class:D(e.ns.e("bottom"))},[j("button",{class:D({[e.ns.is("disabled")]:0===e.filteredValue.length}),disabled:0===e.filteredValue.length,type:"button",onClick:t[1]||(t[1]=(...t)=>e.handleConfirm&&e.handleConfirm(...t))},ee(e.t("el.table.confirmFilter")),11,nn),j("button",{type:"button",onClick:t[2]||(t[2]=(...t)=>e.handleReset&&e.handleReset(...t))},ee(e.t("el.table.resetFilter")),1)],2)])):(I(),Y("ul",{key:1,class:D(e.ns.e("list"))},[j("li",{class:D([e.ns.e("list-item"),{[e.ns.is("active")]:void 0===e.filterValue||null===e.filterValue}]),onClick:t[3]||(t[3]=t=>e.handleSelect(null))},ee(e.t("el.table.clearFilter")),3),(I(!0),Y(Z,null,ge(e.filters,(t=>(I(),Y("li",{key:t.value,class:D([e.ns.e("list-item"),e.ns.is("active",e.isActive(t))]),label:t.value,onClick:l=>e.handleSelect(t.value)},ee(t.text),11,on)))),128))],2))])),default:_((()=>[q((I(),Y("span",{class:D([`${e.ns.namespace.value}-table__column-filter-trigger`,`${e.ns.namespace.value}-none-outline`]),onClick:t[4]||(t[4]=(...t)=>e.showFilterPanel&&e.showFilterPanel(...t))},[me(c,null,{default:_((()=>[e.column.filterOpened?(I(),V(u,{key:0})):(I(),V(d,{key:1}))])),_:1})],2)),[[v,e.hideFilterPanel,e.popperPaneRef]])])),_:1},8,["visible","placement","popper-class"])}],["__file","filter-panel.vue"]]);function sn(e){const t=E();He((()=>{l.value.addObserver(t)})),Te((()=>{a(l.value),n(l.value)})),Pe((()=>{a(l.value),n(l.value)})),Be((()=>{l.value.removeObserver(t)}));const l=w((()=>{const t=e.layout;if(!t)throw new Error("Can not find table layout.");return t})),a=t=>{var l;const a=(null==(l=e.vnode.el)?void 0:l.querySelectorAll("colgroup > col"))||[];if(!a.length)return;const n=t.getFlattenColumns(),o={};n.forEach((e=>{o[e.id]=e}));for(let e=0,r=a.length;e f)for(;u<=d;)K(e[u],a,l,!0),u++;else{const h=u,m=u,v=new Map;for(u=m;u<=f;u++){const e=t[u]=c?Yr(t[u]):Kr(t[u]);null!=e.key&&v.set(e.key,u)}let g,_=0;const y=f-m+1;let b=!1,x=0;const C=new Array(y);for(u=0;u {const{el:l,type:s,transition:i,children:c,shapeFlag:u}=e;if(6&u)return void G(e.component.subTree,t,n,o);if(128&u)return void e.suspense.move(t,n,o);if(64&u)return void s.move(e,t,n,oe);if(s===Mr){a(l,t,n);for(let e=0;e f)for(;u<=d;)K(e[u],a,l,!0),u++;else{const h=u,m=u,v=new Map;for(u=m;u<=f;u++){const e=t[u]=c?Yr(t[u]):Kr(t[u]);null!=e.key&&v.set(e.key,u)}let g,_=0;const y=f-m+1;let b=!1,x=0;const C=new Array(y);for(u=0;u {const{el:l,type:s,transition:i,children:c,shapeFlag:u}=e;if(6&u)return void G(e.component.subTree,t,n,o);if(128&u)return void e.suspense.move(t,n,o);if(64&u)return void s.move(e,t,n,oe);if(s===Mr){a(l,t,n);for(let e=0;e