如何在同一视图(结构)中显示多个警报 Xcode SwiftUI Firebase

huangapple go评论102阅读模式
英文:

How to show multiple alerts in the same view (struct) Xcode swiftUI Firebase

问题

我在Xcode中创建了一个更改密码视图,但其中的警报之一无法正常工作。

这是我的SwiftUI代码:

import SwiftUI
import FirebaseAuth
import FirebaseFirestore

extension String {
    static func myNotEqual(lhs: String, rhs: String) -> Bool {
        return lhs.range(of: rhs, options: .regularExpression) != nil
    }
}

struct ResetPasswordView: View {
    @Environment(\.presentationMode) var presentationMode
    @Environment(\.dismiss) var dismiss
    @Environment(\.colorScheme) var colorScheme
    @State var emailID: String = ""
    @State var ResetPassword: Bool = false
    @State var OldPassword: String = ""
    @State var NewPassword: String = ""
    @State var showError: Bool = false
    @State var errorMessage: String = ""
    @State var isLoading: Bool = false
    @State var showAlert = false
    @State var showPasswordMismatchAlert: Bool = false
    @State var showPasswordChangeSuccessAlert: Bool = false
    
    var body: some View {
        VStack(spacing: 10){
            Text("Reset Your Password")
                .font(.largeTitle.bold())
                .hAlign(.leading)
                .padding(.top, -220)
                .padding(.leading, 14)
            
            Text("Even If Your Password Is Wrong, There Will Be Sent a Link to Change Your Password To Your Current Email")
                .font(.title3)
                .hAlign(.leading)
                .padding(.top, -190)
                .padding(.leading, 15)
            VStack{
                
                TextField("Email", text: $emailID)
                    .disableAutocorrection(true)
                    .autocapitalization(.none)
                    .textContentType(.none)
                    .keyboardType(.emailAddress)
                    .border(1, .gray.opacity(0.5))
                    .hAlign(.center)
                    .padding(.leading, 1)
                    .padding(.all, 10)
                    .padding(.top, -20)
                
                SecureTextField(text: $OldPassword)
                    .autocapitalization(.none)
                    .border(1, .gray.opacity(0.5))
                    .hAlign(.center)
                    .padding(.leading, 1)
                    .padding(.all, 10)
                    .padding(.top, -10)
                
                Secure2TextField(text: $NewPassword)
                    .autocapitalization(.none)
                    .border(1, .gray.opacity(0.5))
                    .hAlign(.center)
                    .padding(.leading, 1)
                    .padding(.all, 10)
                    .padding(.top, -10)
                    .textContentType(.password)
                Group{
                    Text("• 7 characters")
                        .padding(.leading, -83)
                        .foregroundColor(self.requirements[0] ? .green : .red)
                    Text("• 1 number")
                        .padding(.leading, -83)
                        .foregroundColor(self.requirements[1] ? .green : .red)
                    Text("• 1 special character(! @ # $ % ^ *)")
                        .padding(.leading, -0)
                        .foregroundColor(self.requirements[2] ? .green : .red)
                    
                }
                .padding(.leading, -100)
                
                Button("Change Password", action: changePassword)
                    .hAlign(.center)
                    .fillView(colorScheme == .light ? .black : .white)
                    .foregroundColor(colorScheme == .light ? .white : .black)
                    .padding(.leading, 1)
                    .padding(.all, 10)
                    .padding(.top, -10)
                    .disableWithOpacity(NewPassword == "" || emailID == "" || OldPassword == "" || requirements[0] == false || requirements[1] == false || requirements[2] == false)
                
                Button("Back to Previous Page"){
                    dismiss()
                }
                .foregroundColor(colorScheme == .light ? .black : .white)
                .font(.callout)
                .fontWeight(.medium)
                .tint(.black)
            }
        }
        
        .alert(isPresented: $showPasswordMismatchAlert){
            Alert(title: Text("Wrong Password or Email"), message: Text("Try Again"), dismissButton: .default(Text("OK")))
        }
        
        .alert(isPresented: $showPasswordChangeSuccessAlert){
            Alert(title: Text("Done"), message: Text("All Changes Were Made"), dismissButton: .default(Text("OK")))
        }
    }
    
    // 其他部分已省略...
    
    //MARK: Displaying Errors VIA Alert
    func setError(_ error: Error)async{
        //MARK: UI Must be Updated on Main Thread
        await MainActor.run(body: {
            errorMessage = error.localizedDescription
            showError.toggle()
            isLoading = false
        })
    }
}

struct ResetPasswordView_Previews: PreviewProvider {
    static var previews: some View {
        ResetPasswordView()
    }
}
英文:

He I have made an change password view in Xcode but the alerts one of them don't work.

here is my swiftUI code

import SwiftUI
import FirebaseAuth
import FirebaseFirestore
extension String {
static func myNotEqual(lhs: String, rhs: String) -> Bool {
return lhs.range(of: rhs, options: .regularExpression) != nil
}
}
struct ResetPasswordView: View {
@Environment(\.presentationMode) var presentationMode
@Environment(\.dismiss) var dismiss
@Environment(\.colorScheme) var colorScheme
@State var emailID: String = ""
@State var ResetPassword: Bool = false
@State var OldPassword: String = ""
@State var NewPassword: String = ""
@State var showError: Bool = false
@State var errorMessage: String = ""
@State var isLoading: Bool = false
@State var showAlert = false
@State var showPasswordMismatchAlert: Bool = false
@State var showPasswordChangeSuccessAlert: Bool = false
var body: some View {
VStack(spacing: 10){
Text("Reset Your Password")
.font(.largeTitle.bold())
.hAlign(.leading)
.padding(.top, -220)
.padding(.leading, 14)
Text("Even If Your Password Is Wrong, There Will Be Sent a Link to Change Your Password To Your Current Email")
.font(.title3)
.hAlign(.leading)
.padding(.top, -190)
.padding(.leading, 15)
VStack{
TextField("Email", text: $emailID)
.disableAutocorrection(true)
.autocapitalization(.none)
.textContentType(.none)
.keyboardType(.emailAddress)
.border(1, .gray.opacity(0.5))
.hAlign(.center)
.padding(.leading, 1)
.padding(.all, 10)
.padding(.top, -20)
SecureTextField(text: $OldPassword)
.autocapitalization(.none)
.border(1, .gray.opacity(0.5))
.hAlign(.center)
.padding(.leading, 1)
.padding(.all, 10)
.padding(.top, -10)
Secure2TextField(text: $NewPassword)
.autocapitalization(.none)
.border(1, .gray.opacity(0.5))
.hAlign(.center)
.padding(.leading, 1)
.padding(.all, 10)
.padding(.top, -10)
.textContentType(.password)
Group{
Text("• 7 characters")
.padding(.leading, -83)
.foregroundColor(self.requirements[0] ? .green : .red)
Text("• 1 number")
.padding(.leading, -83)
.foregroundColor(self.requirements[1] ? .green : .red)
Text("• 1 special character(! @ # $ % ^ *)")
.padding(.leading, -0)
.foregroundColor(self.requirements[2] ? .green : .red)
}
.padding(.leading, -100)
Button("Change Password", action: changePassword)
.hAlign(.center)
.fillView(colorScheme == .light ? .black : .white)
.foregroundColor(colorScheme == .light ? .white : .black)
.padding(.leading, 1)
.padding(.all, 10)
.padding(.top, -10)
.disableWithOpacity(NewPassword == "" || emailID == "" || OldPassword == "" || requirements[0] == false || requirements[1] == false || requirements[2] == false)
Button("Back to Previous Page"){
dismiss()
}
.foregroundColor(colorScheme == .light ? .black : .white)
.font(.callout)
.fontWeight(.medium)
.tint(.black)
}
}
.alert(isPresented: $showPasswordMismatchAlert){
Alert(title: Text("Wrong Password or Email"), message: Text("Try Again"), dismissButton: .default(Text("OK")))
}
.alert(isPresented: $showPasswordChangeSuccessAlert){
Alert(title: Text("Done"), message: Text("All Changes Were Made"), dismissButton: .default(Text("OK")))
}
}
func changePassword() {
Auth.auth().signIn(withEmail: emailID, password: OldPassword) { _, error in
if error != nil {
showPasswordMismatchAlert = true
}else{
Auth.auth().currentUser?.updatePassword(to: NewPassword)
showPasswordChangeSuccessAlert = true
let userUID = Auth.auth().currentUser?.uid
let databaseRef = Firestore.firestore().collection("Users").document(userUID!)
let updatePassword = NewPassword
databaseRef.setData(["passwordLog": updatePassword], merge: true) { (error) in
if let error = error {
print("Error updating document: \(error)")
} else {
print("Email updated successfully")
}
}
}
}
}
struct SecureTextField: View {
@State private var isSecureField: Bool = true
@Binding var text: String
var body: some View {
HStack{
if isSecureField {
SecureField ("Current Password", text: $text)
}else{
TextField("Current Password", text: $text)
}
}.overlay(alignment: .trailing) {
Image(systemName: isSecureField ? "eye.slash": "eye")
.onTapGesture {
isSecureField.toggle()
}
}
}
}
struct Secure2TextField: View {
@State private var isSecureField: Bool = true
@Binding var text: String
var body: some View {
HStack{
if isSecureField {
SecureField ("New Password", text: $text)
}else{
TextField("New Password", text: $text)
}
}.overlay(alignment: .trailing) {
Image(systemName: isSecureField ? "eye.slash": "eye")
.onTapGesture {
isSecureField.toggle()
}
}
}
}
private var requirements: Array<Bool> {
[
NewPassword.count >= 7,             // Minimum Length
NewPassword != "[0-9]",             // One Number
NewPassword != ".*[^A-Za-z0-9].*"   // One Special Character
]
}
func VerifyPassword(){
showAlert = true
isLoading = true
Task{
do{
try await Auth.auth().sendPasswordReset(withEmail: emailID)
print("email sent")
try await Auth.auth().signIn(withEmail: emailID, password: OldPassword)
print("Pasword Worked")
changePassword()
}catch{
await setError(error)
}
}
}
//MARK: Displaying Errors VIA Alert
func setError(_ error: Error)async{
//MARK: UI Must be Updated on Main Thread
await MainActor.run(body: {
errorMessage = error.localizedDescription
showError.toggle()
isLoading = false
})
}
}
struct ResetPasswordView_Previews: PreviewProvider {
static var previews: some View {
ResetPasswordView()
}
}

I have tryd removing the $showPasswordChangeSuccessAlert alert and if I did that the $showPasswordMismatchAlert alert works and the other way around. so the problem I think is that I can't have two alerts at the same time in one view (struct) please help me

答案1

得分: 0

I solved the code, the problem was that I couldn't show two separate alerts in the same struct (view) so I made one alert that if is if showPasswordMismatchAlert = true he shows the mismatch alert and if is showPasswordChangeSuccessAlert = true he shows the success alert and I did the showPasswordChangeSuccessAlert = true thing in the error Handlemend of my function so if there was an error with "Auth.auth().signIn(withEmail: emailID, password: CurrentPassword)" he shows show showPasswordMismatchAlert = true and showAlert = true and if he doesn't have an error he shows showPasswordMismatchAlert = false showPasswordChangeSuccessAlert = true showAlert = true (why the false well if the user has had an error and now tries again and the showPasswordMismatchAlert wood still be true he wood show showPasswordMismatchAlert) the error Handlemend shit of my function is

func changePassword() {
    Auth.auth().signIn(withEmail: emailID, password: CurrentPassword) { _, error in
        if error != nil {
            Auth.auth().sendPasswordReset(withEmail: emailID)
            showPasswordMismatchAlert = true
            showAlert = true
        } else {
            Auth.auth().sendPasswordReset(withEmail: emailID)
            Auth.auth().currentUser?.updatePassword(to: NewPassword)
            showPasswordMismatchAlert = false
            showPasswordChangeSuccessAlert = true
            showAlert = true

            let userUID = Auth.auth().currentUser?.uid
            let databaseRef = Firestore.firestore().collection("Users").document(userUID!)
            let updatePassword = ["passwordLog": NewPassword]

            databaseRef.updateData(updatePassword)

            let updateEmailLog = ["userEmail": emailID]
            databaseRef.updateData(updateEmailLog)
        }
    }
}
import SwiftUI
import FirebaseAuth
import FirebaseFirestore

extension String {
    static func myNotEqual(lhs: String, rhs: String) -> Bool {
        return lhs.range(of: rhs, options: .regularExpression) != nil
    }
}

struct ResetPasswordView: View {
    @Environment(\.presentationMode) var presentationMode
    @Environment(\.dismiss) var dismiss
    @Environment(\.colorScheme) var colorScheme
    @State var emailID: String = ""
    @State var ResetPassword: Bool = false
    @State var CurrentPassword: String = ""
    @State var NewPassword: String = ""
    @State var showError: Bool = false
    @State var errorMessage: String = ""
    @State var isLoading: Bool = false
    @State var showAlert = false
    @State var showPasswordMismatchAlert: Bool = false
    @State var showPasswordChangeSuccessAlert: Bool = false

    var body: some View {
        VStack(spacing: 10){
            Text("Reset Your Password")
                .font(.largeTitle.bold())
                .hAlign(.leading)
                .padding(.top, -260)
                .padding(.leading, 14)

            Text("If You Don't Know Your Password Don't Worry,\nThere Will Be Sent a Reset Link to Your Email, Regardless of if You Put in The Right Password")
                .hAlign(.leading)
                .padding(.top, -230)
                .padding(.leading, 14)

            VStack{

                TextField("Email", text: $emailID)
                    .disableAutocorrection(true)
                    .autocapitalization(.none)
                    .textContentType(.none)
                    .keyboardType(.emailAddress)
                    .border(1, .gray.opacity(0.5))
                    .hAlign(.center)
                    .padding(.leading, 1)
                    .padding(.all, 10)
                    .padding(.top, -100)

                SecureTextField(text: $CurrentPassword)
                    .autocapitalization(.none)
                    .border(1, .gray.opacity(0.5))
                    .hAlign(.center)
                    .padding(.leading, 1)
                    .padding(.all, 10)
                    .padding(.top, -60)

                Secure2TextField(text: $NewPassword)
                    .autocapitalization(.none)
                    .border(1, .gray.opacity(0.5))
                    .hAlign(.center)
                    .padding(.leading, 1)
                    .padding(.all, 10)
                    .padding(.top, -20)
                    .textContentType(.password)
                Group{
                    Text("• 7 characters")
                        .padding(.leading, -83)
                        .foregroundColor(self.requirements[0] ? .green : .red)
                    Text("• 1 number")
                        .padding(.leading, -83)
                        .foregroundColor(self.requirements[1] ? .green : .red)
                    Text("• 1 special character(! @ # $ % ^ )")
                        .padding(.leading, -0)
                        .foregroundColor(self.requirements[2] ? .green : .red)



                }
                .padding(.leading, -100)

                Button("Change Password", action: changePassword)
                    .hAlign(.center)
                    .fillView(colorScheme == .light ? .black : .white)
                    .foregroundColor(colorScheme == .light ? .white : .black)
                    .padding(.leading, 1)
                    .padding(.all, 10)
                    .padding(.top, -10)
                    .disableWithOpacity(NewPassword == "" || emailID == "" || CurrentPassword == "" || requirements[0] == false || requirements[1] == false || requirements[2] == false)

                Button("Back to Previous Page"){
                    dismiss()
                }
                .foregroundColor(colorScheme == .light ? .black : .white)
                .font(.callout)
                .fontWeight(.medium)
                .tint(.black)
            }
        }

        .alert(isPresented: $showAlert) {
            if showPasswordMismatchAlert {
                return Alert(title: Text("Wrong Password or Email"), message: Text("Try Again"), dismissButton: .default(Text("OK")))
            } else if showPasswordChangeSuccessAlert {
                return Alert(title: Text("Your Password is Changed"), message: Text("There is an email sent to your current email if you want to change it back within the next hour"), dismissButton: .default(Text("OK")))
            } else {
                return Alert(title: Text("Not Right"), message: Text("something is wrong contact the developer at ziya@ziyaxservers.nl"), dismissButton: .default(Text("OK")))
            }
        }
    }

    func changePassword() {
        Auth.auth().signIn(withEmail: emailID, password: CurrentPassword) { _, error in
            if error != nil {
                Auth.auth().sendPasswordReset(withEmail: emailID)
                showPasswordMismatchAlert = true
                showAlert = true
            } else {
                Auth.auth().sendPasswordReset(withEmail: emailID)
                Auth.auth().currentUser?.updatePassword(to: NewPassword)
                showPasswordMismatchAlert = false
                showPasswordChangeSuccessAlert = true
                showAlert = true

                let userUID = Auth.auth().currentUser?.uid
                let databaseRef = Firestore.firestore().collection("Users").document(userUID!)
                let updatePassword = ["passwordLog": NewPassword]

                databaseRef.updateData(updatePassword)

                let updateEmailLog =

<details>
<summary>英文:</summary>

I solved the code, 
the problem was that I couldn&#39;t show two separate alerts in the same struct (view) so I made one alert that if is if showPasswordMismatchAlert = true he shows the mismatch alert and if is showPasswordChangeSuccessAlert = true he shows the success alert and I did the showPasswordChangeSuccessAlert = true thing in the error Handlemend of my function so if there was an error with &quot;Auth.auth().signIn(withEmail: emailID, password: CurrentPassword)&quot; he shows show showPasswordMismatchAlert = true and showAlert = true and if he doesn&#39;t have an error he shows showPasswordMismatchAlert = false showPasswordChangeSuccessAlert = true showAlert = true (why the false well if the user has had an error and now tries again and the showPasswordMismatchAlert wood still be true he wood show showPasswordMismatchAlert) the error Handlemend shit of my function is 

func changePassword() {
Auth.auth().signIn(withEmail: emailID, password: CurrentPassword) { _, error in
if error != nil {
Auth.auth().sendPasswordReset(withEmail: emailID)
showPasswordMismatchAlert = true
showAlert = true
} else {
Auth.auth().sendPasswordReset(withEmail: emailID)
Auth.auth().currentUser?.updatePassword(to: NewPassword)
showPasswordMismatchAlert = false
showPasswordChangeSuccessAlert = true
showAlert = true
let userUID = Auth.auth().currentUser?.uid
let databaseRef = Firestore.firestore().collection(&quot;Users&quot;).document(userUID!)
let updatePassword = [&quot;passwordLog&quot;: NewPassword]
databaseRef.updateData(updatePassword)
let updateEmailLog = [&quot;userEmail&quot;: emailID]
databaseRef.updateData(updateEmailLog)
}
}
}

import SwiftUI
import FirebaseAuth
import FirebaseFirestore

extension String {
static func myNotEqual(lhs: String, rhs: String) -> Bool {
return lhs.range(of: rhs, options: .regularExpression) != nil
}
}

struct ResetPasswordView: View {
@Environment(.presentationMode) var presentationMode
@Environment(.dismiss) var dismiss
@Environment(.colorScheme) var colorScheme
@State var emailID: String = ""
@State var ResetPassword: Bool = false
@State var CurrentPassword: String = ""
@State var NewPassword: String = ""
@State var showError: Bool = false
@State var errorMessage: String = ""
@State var isLoading: Bool = false
@State var showAlert = false
@State var showPasswordMismatchAlert: Bool = false
@State var showPasswordChangeSuccessAlert: Bool = false

var body: some View {
VStack(spacing: 10){
Text(&quot;Reset Your Password&quot;)
.font(.largeTitle.bold())
.hAlign(.leading)
.padding(.top, -260)
.padding(.leading, 14)
Text(&quot;If You Don&#39;t Know Your Password Don&#39;t Worry,\nThere Will Be Sent a Reset Link to Your Email, Regardless of if You Put in The Right Password&quot;)
.hAlign(.leading)
.padding(.top, -230)
.padding(.leading, 14)
VStack{
TextField(&quot;Email&quot;, text: $emailID)
.disableAutocorrection(true)
.autocapitalization(.none)
.textContentType(.none)
.keyboardType(.emailAddress)
.border(1, .gray.opacity(0.5))
.hAlign(.center)
.padding(.leading, 1)
.padding(.all, 10)
.padding(.top, -100)
SecureTextField(text: $CurrentPassword)
.autocapitalization(.none)
.border(1, .gray.opacity(0.5))
.hAlign(.center)
.padding(.leading, 1)
.padding(.all, 10)
.padding(.top, -60)
Secure2TextField(text: $NewPassword)
.autocapitalization(.none)
.border(1, .gray.opacity(0.5))
.hAlign(.center)
.padding(.leading, 1)
.padding(.all, 10)
.padding(.top, -20)
.textContentType(.password)
Group{
Text(&quot;• 7 characters&quot;)
.padding(.leading, -83)
.foregroundColor(self.requirements[0] ? .green : .red)
Text(&quot;• 1 number&quot;)
.padding(.leading, -83)
.foregroundColor(self.requirements[1] ? .green : .red)
Text(&quot;• 1 special character(! @ # $ % ^ *)&quot;)
.padding(.leading, -0)
.foregroundColor(self.requirements[2] ? .green : .red)
}
.padding(.leading, -100)
Button(&quot;Change Password&quot;, action: changePassword)
.hAlign(.center)
.fillView(colorScheme == .light ? .black : .white)
.foregroundColor(colorScheme == .light ? .white : .black)
.padding(.leading, 1)
.padding(.all, 10)
.padding(.top, -10)
.disableWithOpacity(NewPassword == &quot;&quot; || emailID == &quot;&quot; || CurrentPassword == &quot;&quot; || requirements[0] == false || requirements[1] == false || requirements[2] == false)
Button(&quot;Back to Previous Page&quot;){
dismiss()
}
.foregroundColor(colorScheme == .light ? .black : .white)
.font(.callout)
.fontWeight(.medium)
.tint(.black)
}
}
.alert(isPresented: $showAlert) {
if showPasswordMismatchAlert {
return Alert(title: Text(&quot;Wrong Password or Email&quot;), message: Text(&quot;Try Again&quot;), dismissButton: .default(Text(&quot;OK&quot;)))
} else if showPasswordChangeSuccessAlert {
return Alert(title: Text(&quot;Your Password is Changed&quot;), message: Text(&quot;There is an email sent to your current email if you want to change it back within the next hour&quot;), dismissButton: .default(Text(&quot;OK&quot;)))
} else {
return Alert(title: Text(&quot;Not Right&quot;), message: Text(&quot;something is wrong contact the develeper at ziya@ziyaxservers.nl&quot;), dismissButton: .default(Text(&quot;OK&quot;)))
}
}
}
func changePassword() {
Auth.auth().signIn(withEmail: emailID, password: CurrentPassword) { _, error in
if error != nil {
Auth.auth().sendPasswordReset(withEmail: emailID)
showPasswordMismatchAlert = true
showAlert = true
} else {
Auth.auth().sendPasswordReset(withEmail: emailID)
Auth.auth().currentUser?.updatePassword(to: NewPassword)
showPasswordMismatchAlert = false
showPasswordChangeSuccessAlert = true
showAlert = true
let userUID = Auth.auth().currentUser?.uid
let databaseRef = Firestore.firestore().collection(&quot;Users&quot;).document(userUID!)
let updatePassword = [&quot;passwordLog&quot;: NewPassword]
databaseRef.updateData(updatePassword)
let updateEmailLog = [&quot;userEmail&quot;: emailID]
databaseRef.updateData(updateEmailLog)
}
}
}
struct SecureTextField: View {
@State private var isSecureField: Bool = true
@Binding var text: String
var body: some View {
HStack{
if isSecureField {
SecureField (&quot;Current Password&quot;, text: $text)
}else{
TextField(&quot;Current Password&quot;, text: $text)
}
}.overlay(alignment: .trailing) {
Image(systemName: isSecureField ? &quot;eye.slash&quot;: &quot;eye&quot;)
.onTapGesture {
isSecureField.toggle()
}
}
}
}
struct Secure2TextField: View {
@State private var isSecureField: Bool = true
@Binding var text: String
var body: some View {
HStack{
if isSecureField {
SecureField (&quot;New Password&quot;, text: $text)
}else{
TextField(&quot;New Password&quot;, text: $text)
}
}.overlay(alignment: .trailing) {
Image(systemName: isSecureField ? &quot;eye.slash&quot;: &quot;eye&quot;)
.onTapGesture {
isSecureField.toggle()
}
}
}
}
private var requirements: Array&lt;Bool&gt; {
[
NewPassword.count &gt;= 7,             // Minimum Length
NewPassword != &quot;[0-9]&quot;,             // One Number
NewPassword != &quot;.*[^A-Za-z0-9].*&quot;   // One Special Character
]
}

}

struct ResetPasswordView_Previews: PreviewProvider {
static var previews: some View {
ResetPasswordView()
}
}


</details>

huangapple
  • 本文由 发表于 2023年5月6日 16:29:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76187909.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定