diff --git a/internal/web/actions/default/servers/certs/selectPopup.go b/internal/web/actions/default/servers/certs/selectPopup.go
index 54a9bb72..9210a58a 100644
--- a/internal/web/actions/default/servers/certs/selectPopup.go
+++ b/internal/web/actions/default/servers/certs/selectPopup.go
@@ -2,9 +2,11 @@ package certs
 
 import (
 	"encoding/json"
+	"errors"
 	"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
 	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
+	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
 	"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/sslconfigs"
 	"github.com/iwind/TeaGo/lists"
 	"github.com/iwind/TeaGo/maps"
@@ -23,15 +25,82 @@ func (this *SelectPopupAction) Init() {
 }
 
 func (this *SelectPopupAction) RunGet(params struct {
+	ServerId         int64  // 搜索的服务
+	UserId           int64  // 搜索的用户名
+	SearchingDomains string // 搜索的域名
+	SearchingType    string // 搜索类型:match|all
+
 	ViewSize        string
 	SelectedCertIds string
 	Keyword         string
 }) {
-	// TODO 列出常用和最新的证书供用户选择
+	// 服务相关
+	if params.ServerId > 0 {
+		serverResp, err := this.RPC().ServerRPC().FindEnabledUserServerBasic(this.AdminContext(), &pb.FindEnabledUserServerBasicRequest{ServerId: params.ServerId})
+		if err != nil {
+			this.ErrorPage(err)
+			return
+		}
+		var server = serverResp.Server
+		if server != nil {
+			if server.UserId > 0 {
+				params.UserId = server.UserId
+			}
+
+			// 读取所有ServerNames
+			serverNamesResp, err := this.RPC().ServerRPC().FindServerNames(this.AdminContext(), &pb.FindServerNamesRequest{ServerId: params.ServerId})
+			if err != nil {
+				this.ErrorPage(err)
+				return
+			}
+			if len(serverNamesResp.ServerNamesJSON) > 0 {
+				var serverNames = []*serverconfigs.ServerNameConfig{}
+				err = json.Unmarshal(serverNamesResp.ServerNamesJSON, &serverNames)
+				if err != nil {
+					this.ErrorPage(err)
+					return
+				}
+				params.SearchingDomains = strings.Join(serverconfigs.PlainServerNames(serverNames), ",")
+			}
+		}
+	}
+
+	// 用户相关
+	this.Data["userId"] = params.UserId
+
+	// 域名搜索相关
+	var url = this.Request.URL.Path
+	var query = this.Request.URL.Query()
+	query.Del("searchingType")
+	this.Data["baseURL"] = url + "?" + query.Encode()
+
+	var searchingDomains = []string{}
+	if len(params.SearchingDomains) > 0 {
+		searchingDomains = strings.Split(params.SearchingDomains, ",")
+	}
+	const maxDomains = 2_000 // 限制搜索的域名数量
+	if len(searchingDomains) > maxDomains {
+		searchingDomains = searchingDomains[:maxDomains]
+	}
+	this.Data["searchingDomains"] = searchingDomains
 
 	this.Data["keyword"] = params.Keyword
 	this.Data["selectedCertIds"] = params.SelectedCertIds
 
+	var searchingType = params.SearchingType
+	if len(searchingType) == 0 {
+		if len(params.SearchingDomains) == 0 {
+			searchingType = "all"
+		} else {
+			searchingType = "match"
+		}
+	}
+	if searchingType != "all" && searchingType != "match" {
+		this.ErrorPage(errors.New("invalid searching type '" + searchingType + "'"))
+		return
+	}
+	this.Data["searchingType"] = searchingType
+
 	// 已经选择的证书
 	var selectedCertIds = []string{}
 	if len(params.SelectedCertIds) > 0 {
@@ -43,24 +112,68 @@ func (this *SelectPopupAction) RunGet(params struct {
 	}
 	this.Data["viewSize"] = params.ViewSize
 
-	countResp, err := this.RPC().SSLCertRPC().CountSSLCerts(this.AdminContext(), &pb.CountSSLCertRequest{
+	// 全部证书数量
+	countAllResp, err := this.RPC().SSLCertRPC().CountSSLCerts(this.AdminContext(), &pb.CountSSLCertRequest{
+		UserId:  params.UserId,
 		Keyword: params.Keyword,
 	})
 	if err != nil {
 		this.ErrorPage(err)
 		return
 	}
+	var totalAll = countAllResp.Count
+	this.Data["totalAll"] = totalAll
 
-	page := this.NewPage(countResp.Count)
+	// 已匹配证书数量
+	var totalMatch int64 = 0
+	if len(searchingDomains) > 0 {
+		countMatchResp, err := this.RPC().SSLCertRPC().CountSSLCerts(this.AdminContext(), &pb.CountSSLCertRequest{
+			UserId:  params.UserId,
+			Keyword: params.Keyword,
+			Domains: searchingDomains,
+		})
+		if err != nil {
+			this.ErrorPage(err)
+			return
+		}
+		totalMatch = countMatchResp.Count
+	}
+	this.Data["totalMatch"] = totalMatch
+
+	var totalCerts int64
+	if searchingType == "all" {
+		totalCerts = totalAll
+	} else if searchingType == "match" {
+		totalCerts = totalMatch
+	}
+
+	var page = this.NewPage(totalCerts)
 	this.Data["page"] = page.AsHTML()
 
-	listResp, err := this.RPC().SSLCertRPC().ListSSLCerts(this.AdminContext(), &pb.ListSSLCertsRequest{
-		Keyword: params.Keyword,
-		Offset:  page.Offset,
-		Size:    page.Size,
-	})
+	var listResp *pb.ListSSLCertsResponse
+	if searchingType == "all" {
+		listResp, err = this.RPC().SSLCertRPC().ListSSLCerts(this.AdminContext(), &pb.ListSSLCertsRequest{
+			UserId:  params.UserId,
+			Keyword: params.Keyword,
+			Offset:  page.Offset,
+			Size:    page.Size,
+		})
+	} else if searchingType == "match" {
+		listResp, err = this.RPC().SSLCertRPC().ListSSLCerts(this.AdminContext(), &pb.ListSSLCertsRequest{
+			UserId:  params.UserId,
+			Keyword: params.Keyword,
+			Domains: searchingDomains,
+			Offset:  page.Offset,
+			Size:    page.Size,
+		})
+	}
 
-	certConfigs := []*sslconfigs.SSLCertConfig{}
+	if listResp == nil {
+		this.ErrorPage(errors.New("'listResp' should not be nil"))
+		return
+	}
+
+	var certConfigs = []*sslconfigs.SSLCertConfig{}
 	err = json.Unmarshal(listResp.SslCertsJSON, &certConfigs)
 	if err != nil {
 		this.ErrorPage(err)
@@ -68,8 +181,8 @@ func (this *SelectPopupAction) RunGet(params struct {
 	}
 	this.Data["certs"] = certConfigs
 
-	certMaps := []maps.Map{}
-	nowTime := time.Now().Unix()
+	var certMaps = []maps.Map{}
+	var nowTime = time.Now().Unix()
 	for _, certConfig := range certConfigs {
 		countServersResp, err := this.RPC().ServerRPC().CountAllEnabledServersWithSSLCertId(this.AdminContext(), &pb.CountAllEnabledServersWithSSLCertIdRequest{SslCertId: certConfig.Id})
 		if err != nil {
diff --git a/web/public/js/components/server/server-name-box.js b/web/public/js/components/server/server-name-box.js
index 6970005e..6b4e79b0 100644
--- a/web/public/js/components/server/server-name-box.js
+++ b/web/public/js/components/server/server-name-box.js
@@ -1,78 +1,100 @@
 Vue.component("server-name-box", {
-    props: ["v-server-names"],
-    data: function () {
-        let serverNames = this.vServerNames;
-        if (serverNames == null) {
-            serverNames = []
-        }
-        return {
-            serverNames: serverNames,
-            isSearching: false,
-            keyword: ""
-        }
-    },
-    methods: {
-        addServerName: function () {
-            window.UPDATING_SERVER_NAME = null
-            let that = this
-            teaweb.popup("/servers/addServerNamePopup", {
-                callback: function (resp) {
-                    var serverName = resp.data.serverName
-                    that.serverNames.push(serverName)
-                }
-            });
-        },
+	props: ["v-server-names"],
+	data: function () {
+		let serverNames = this.vServerNames;
+		if (serverNames == null) {
+			serverNames = []
+		}
+		return {
+			serverNames: serverNames,
+			isSearching: false,
+			keyword: ""
+		}
+	},
+	methods: {
+		addServerName: function () {
+			window.UPDATING_SERVER_NAME = null
+			let that = this
+			teaweb.popup("/servers/addServerNamePopup", {
+				callback: function (resp) {
+					var serverName = resp.data.serverName
+					that.serverNames.push(serverName)
+				}
+			});
+		},
 
-        removeServerName: function (index) {
-            this.serverNames.$remove(index)
-        },
+		removeServerName: function (index) {
+			this.serverNames.$remove(index)
+		},
 
-        updateServerName: function (index, serverName) {
-            window.UPDATING_SERVER_NAME = teaweb.clone(serverName)
-            let that = this
-            teaweb.popup("/servers/addServerNamePopup", {
-                callback: function (resp) {
-                    var serverName = resp.data.serverName
-                    Vue.set(that.serverNames, index, serverName)
-                }
-            });
-        },
-        showSearchBox: function () {
-            this.isSearching = !this.isSearching
-            if (this.isSearching) {
-                let that = this
-                setTimeout(function () {
-                    that.$refs.keywordRef.focus()
-                }, 200)
-            } else {
-                this.keyword = ""
-            }
-        },
-    },
-    watch: {
-        keyword: function (v) {
-            this.serverNames.forEach(function (serverName) {
-                if (v.length == 0) {
-                    serverName.isShowing = true
-                    return
-                }
-                if (serverName.subNames == null || serverName.subNames.length == 0) {
-                    if (!teaweb.match(serverName.name, v)) {
-                        serverName.isShowing = false
-                    }
-                } else {
-                    let found = false
-                    serverName.subNames.forEach(function (subName) {
-                        if (teaweb.match(subName, v)) {
-                            found = true
-                        }
-                    })
-                    serverName.isShowing = found
-                }
-            })
-        }
-    },
-    template: `
+		updateServerName: function (index, serverName) {
+			window.UPDATING_SERVER_NAME = teaweb.clone(serverName)
+			let that = this
+			teaweb.popup("/servers/addServerNamePopup", {
+				callback: function (resp) {
+					var serverName = resp.data.serverName
+					Vue.set(that.serverNames, index, serverName)
+				}
+			});
+		},
+		showSearchBox: function () {
+			this.isSearching = !this.isSearching
+			if (this.isSearching) {
+				let that = this
+				setTimeout(function () {
+					that.$refs.keywordRef.focus()
+				}, 200)
+			} else {
+				this.keyword = ""
+			}
+		},
+		allServerNames: function () {
+			if (this.serverNames == null) {
+				return []
+			}
+			let result = []
+			this.serverNames.forEach(function (serverName) {
+				if (serverName.subNames != null && serverName.subNames.length > 0) {
+					serverName.subNames.forEach(function (subName) {
+						if (subName != null && subName.length > 0) {
+							if (!result.$contains(subName)) {
+								result.push(subName)
+							}
+						}
+					})
+				} else if (serverName.name != null && serverName.name.length > 0) {
+					if (!result.$contains(serverName.name)) {
+						result.push(serverName.name)
+					}
+				}
+			})
+			return result
+		}
+	},
+	watch: {
+		keyword: function (v) {
+			this.serverNames.forEach(function (serverName) {
+				if (v.length == 0) {
+					serverName.isShowing = true
+					return
+				}
+				if (serverName.subNames == null || serverName.subNames.length == 0) {
+					if (!teaweb.match(serverName.name, v)) {
+						serverName.isShowing = false
+					}
+				} else {
+					let found = false
+					serverName.subNames.forEach(function (subName) {
+						if (teaweb.match(subName, v)) {
+							found = true
+						}
+					})
+					serverName.isShowing = found
+				}
+			})
+		}
+	},
+	template: `
 	
 	
 		
diff --git a/web/public/js/components/server/ssl-certs-box.js b/web/public/js/components/server/ssl-certs-box.js
index 24ad267c..ee8a04ae 100644
--- a/web/public/js/components/server/ssl-certs-box.js
+++ b/web/public/js/components/server/ssl-certs-box.js
@@ -5,7 +5,8 @@ Vue.component("ssl-certs-box", {
 		"v-protocol", // 协议:https|tls
 		"v-view-size", // 弹窗尺寸:normal, mini
 		"v-single-mode", // 单证书模式
-		"v-description" // 描述文字
+		"v-description", // 描述文字
+		"v-domains" // 搜索的域名列表或者函数
 	],
 	data: function () {
 		let certs = this.vCerts
@@ -43,8 +44,8 @@ Vue.component("ssl-certs-box", {
 		// 选择证书
 		selectCert: function () {
 			let that = this
-			let width = "50em"
-			let height = "30em"
+			let width = "54em"
+			let height = "32em"
 			let viewSize = this.vViewSize
 			if (viewSize == null) {
 				viewSize = "normal"
@@ -53,11 +54,37 @@ Vue.component("ssl-certs-box", {
 				width = "35em"
 				height = "20em"
 			}
-			teaweb.popup("/servers/certs/selectPopup?viewSize=" + viewSize, {
+
+			let searchingDomains = []
+			if (this.vDomains != null) {
+				if (typeof this.vDomains == "function") {
+					let resultDomains = this.vDomains()
+					if (resultDomains != null && typeof resultDomains == "object" && (resultDomains instanceof Array)) {
+						searchingDomains = resultDomains
+					}
+				} else if (typeof this.vDomains == "object" && (this.vDomains instanceof Array)) {
+					searchingDomains = this.vDomains
+				}
+				if (searchingDomains.length > 10000) {
+					searchingDomains = searchingDomains.slice(0, 10000)
+				}
+			}
+
+			let selectedCertIds = this.certs.map(function (cert) {
+				return cert.id
+			})
+
+			teaweb.popup("/servers/certs/selectPopup?viewSize=" + viewSize + "&searchingDomains=" + window.encodeURIComponent(searchingDomains.join(",")) + "&selectedCertIds=" + selectedCertIds.join(","), {
 				width: width,
 				height: height,
 				callback: function (resp) {
-					that.certs.push(resp.data.cert)
+					if (resp.data.cert != null) {
+						that.certs.push(resp.data.cert)
+					}
+					if (resp.data.certs != null) {
+						that.certs.$pushAll(resp.data.certs)
+					}
+					that.$forceUpdate()
 				}
 			})
 		},
diff --git a/web/public/js/components/server/ssl-config-box.js b/web/public/js/components/server/ssl-config-box.js
index fa514b9c..e8ba3493 100644
--- a/web/public/js/components/server/ssl-config-box.js
+++ b/web/public/js/components/server/ssl-config-box.js
@@ -107,12 +107,23 @@ Vue.component("ssl-config-box", {
 					selectedCertIds.push(cert.id.toString())
 				})
 			}
-			teaweb.popup("/servers/certs/selectPopup?selectedCertIds=" + selectedCertIds, {
+			let serverId = this.vServerId
+			if (serverId == null) {
+				serverId = 0
+			}
+			teaweb.popup("/servers/certs/selectPopup?selectedCertIds=" + selectedCertIds + "&serverId=" + serverId, {
 				width: "50em",
 				height: "30em",
 				callback: function (resp) {
-					that.policy.certRefs.push(resp.data.certRef)
-					that.policy.certs.push(resp.data.cert)
+					if (resp.data.cert != null && resp.data.certRef != null) {
+						that.policy.certRefs.push(resp.data.certRef)
+						that.policy.certs.push(resp.data.cert)
+					}
+					if (resp.data.certs != null && resp.data.certRefs != null) {
+						that.policy.certRefs.$pushAll(resp.data.certRefs)
+						that.policy.certs.$pushAll(resp.data.certs)
+					}
+					that.$forceUpdate()
 				}
 			})
 		},
@@ -312,8 +323,15 @@ Vue.component("ssl-config-box", {
 				width: "50em",
 				height: "30em",
 				callback: function (resp) {
-					that.policy.clientCARefs.push(resp.data.certRef)
-					that.policy.clientCACerts.push(resp.data.cert)
+					if (resp.data.cert != null && resp.data.certRef != null) {
+						that.policy.clientCARefs.push(resp.data.certRef)
+						that.policy.clientCACerts.push(resp.data.cert)
+					}
+					if (resp.data.certs != null && resp.data.certRefs != null) {
+						that.policy.clientCARefs.$pushAll(resp.data.certRefs)
+						that.policy.clientCACerts.$pushAll(resp.data.certs)
+					}
+					that.$forceUpdate()
 				}
 			})
 		},
@@ -525,7 +543,7 @@ Vue.component("ssl-config-box", {
 				
客户端认证CA证书 | 
 				
 					
-						 
+						 
 							{{cert.name}} / {{cert.dnsNames}} / 有效至{{formatTime(cert.timeEndAt)}}    
 						 
 						
diff --git a/web/views/@default/servers/certs/index.js b/web/views/@default/servers/certs/index.js
index 0358e502..fc43ba4c 100644
--- a/web/views/@default/servers/certs/index.js
+++ b/web/views/@default/servers/certs/index.js
@@ -14,7 +14,6 @@ Tea.context(function () {
 	// 批量上传证书
 	this.uploadBatch = function () {
 		teaweb.popup("/servers/certs/uploadBatchPopup", {
-			height: "30em",
 			callback: function () {
 				window.location.reload()
 			}
diff --git a/web/views/@default/servers/certs/selectPopup.html b/web/views/@default/servers/certs/selectPopup.html
index bbc072e2..8e9d5880 100644
--- a/web/views/@default/servers/certs/selectPopup.html
+++ b/web/views/@default/servers/certs/selectPopup.html
@@ -1,26 +1,48 @@
 {$layout "layout_popup"}
 
- 选择证书
+ 选择证书 (当前服务域名:{{searchingDomains[0]}}等{{searchingDomains.length}}个域名)
 
 
 
 
+
+ 
+     
+     
+        所有证书 ({{totalAll}})
+        |
+        域名匹配证书  ({{totalMatch}})
+    
+ 
+
+
+ 
+     
+     
+ 
+
 
-
+
  
 	
         
+             | 
             证书说明 | 
             域名 | 
             过期日期 | 
@@ -30,6 +52,9 @@
          
 	
 	
+        | 
+            
+         | 
         
             {{cert.name}}
             {{cert.name}}
diff --git a/web/views/@default/servers/certs/selectPopup.js b/web/views/@default/servers/certs/selectPopup.js
index cbc5c269..a3075da7 100644
--- a/web/views/@default/servers/certs/selectPopup.js
+++ b/web/views/@default/servers/certs/selectPopup.js
@@ -11,4 +11,67 @@ Tea.context(function () {
 			}
 		})
 	}
+
+	this.encodeURL = function (arg) {
+		return window.encodeURIComponent(arg)
+	}
+
+	/**
+	 * 复选框
+	 */
+	this.countChecked = 0
+
+	this.certs.forEach(function (cert) {
+		cert.isChecked = false
+	})
+
+	this.changeAll = function (b) {
+		let that = this
+		this.certs.forEach(function (cert) {
+			cert.isChecked = b
+		})
+
+		if (b) {
+			let countChecked = 0
+			this.certs.forEach(function (cert, index) {
+				if (cert.isChecked && !that.certInfos[index].isSelected) {
+					countChecked++
+				}
+			})
+			this.countChecked = countChecked
+		} else {
+			this.countChecked = 0
+		}
+	}
+
+	this.changeCertChecked = function () {
+		let countChecked = 0
+		this.certs.forEach(function (cert) {
+			if (cert.isChecked) {
+				countChecked++
+			}
+		})
+		this.countChecked = countChecked
+	}
+
+	this.confirmChecked = function () {
+		let resultCerts = []
+		let resultCertRefs = []
+		this.certs.forEach(function (cert) {
+			if (cert.isChecked) {
+				resultCerts.push(cert)
+				resultCertRefs.push({
+					isOn: true,
+					certId: cert.id
+				})
+			}
+		})
+		NotifyPopup({
+			code: 200,
+			data: {
+				certs: resultCerts,
+				certRefs: resultCertRefs
+			}
+		})
+	}
 })
\ No newline at end of file
diff --git a/web/views/@default/servers/create.html b/web/views/@default/servers/create.html
index a3f77abe..349ca288 100644
--- a/web/views/@default/servers/create.html
+++ b/web/views/@default/servers/create.html
@@ -7,14 +7,14 @@
             新网站服务主要信息:
             
                 
-                    | 所属用户 | 
+                    所属用户 | 
                     
                         
                         
                      | 
                  
                 
-                    | 选择套餐 | 
+                    选择套餐 | 
                     
                          | 
                  
                 
-                    | 部署的集群 * | 
+                    部署的集群 * | 
                     
                          
                             
@@ -47,7 +47,7 @@
                       |  
                         | {{tlsProtocolName.toUpperCase()}}证书 | 
                         
-                            
+                            
                          | 
                      
                 
@@ -77,7 +77,7 @@
                 
 
                 
-                    | 绑定端口 * | 
+                    绑定端口 * | 
                     
                         
                      | 
diff --git a/web/views/@default/servers/create.js b/web/views/@default/servers/create.js
index 6bc432b1..eecb2b67 100644
--- a/web/views/@default/servers/create.js
+++ b/web/views/@default/servers/create.js
@@ -96,4 +96,11 @@ Tea.context(function () {
 				this.plans = resp.data.plans
 			})
 	}
+
+	/**
+	 * 证书相关
+	 */
+	this.findServerNames = function () {
+		return this.$refs.serverNameBox.allServerNames()
+	}
 })
\ No newline at end of file
   |    |