Trang 1 trên tổng số 2 12 Cuối cùngCuối cùng
Từ 1 tới 10 trên tổng số 19 kết quả

Đề tài: Tìm hiểu mô hình 3-layer trong CNPM

  1. #1
    Ngày gia nhập
    09 2007
    Bài viết
    724

    Mặc định Tìm hiểu mô hình 3-layer trong CNPM

    Sau bài thiết kế theo HDT của mình mình sẽ tiếp tục loạt bài của mình về vấn đề 3-layer.

    Trong việc phát triển phần mềm thì mô hình 3 layer là một mô hình cơ bản cho chúng ta thiết kế ra một phần mềm có tính mềm dẽo hơn và có tính tiến hóa cao hơn.
    1- Giới thiệu về 3 layer.
    Ngày xưa khi mới học lập trình thì hầu hết chúng ta đều tiếp xúc theo thứ tự:
    - Tất cả gom vào trong hàm main()
    - Chúng ta chia nó ra theo từng hàm, mỗi hàm có một chức năng riêng biệt.
    - Chúng ta làm việc với các khái niệm OOP như class.
    Khi chúng ta làm việc với một số môi trường lập trình thì chúng ta thường code theo kiểu “ông cha ta ở chung một nhà” tức là tất cả chúng ta bỏ chung nó trong một file đó là file chứa các Event giao diện của chương trình như vậy nó sẽ rất là khó khăn mỗi khi chúng ta cần khoanh vùng để debug và rất khó khi quản lý một đống code “bùi nhùi” mà mình code ra.
    Mô hình 3 layer là một mô hình chuẩn khi phát triển một phần mềm mà chúng ta sẽ bắt gặp nó hay là “con em” của nó ở bất kỳ project mà chúng ta làm (theo mình biết thì đi ra ngoài làm người ta sẽ làm theo mô hình n-layer nhưng nó lấy cơ sở từ mô hình 3-layer để nó phát triên lên).

    2- Giới thiệu các thành phần của mô hình 3 layer.
    Mô hình layer gồm có 3 layer:

    - Layer GUI (Graphics User Interface)
    - Layer Business Logic (Đây là layer để xử lý các dữ liệu, thông tin trước khi đưa lên giao diện hoặc đưa xuống dữ liệu.)
    - Layer Data Access – Layer này sẽ nói chuyện Data.

    Mô hình:
    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		3-layer.jpg
Lần xem:	48
Size:		21.8 KB
ID:		4989


    1- GUI Layer.
    - Đây là layer tạo lên giao diện cho người dùng, nó sẽ là nơi tiếp nhận và kết xuất ra kết quả của chương trình cho bạn.
    - Nó có nhiệm vụ xử lý, kiểm tra các dữ liệu nhập vào ( ví như ở TextBox này nó phải là số, số phải từ 1-9….).
    - Nó tiếp nhận các Event của người dùng, kiểm tra dữ liệu được nhập vào, gửi yêu cầu xử lý xuống tầng kế tiếp.
    2- Business Logic Layer:
    - Đây là layer xử lý chính các dữ liệu trước khi được đưa lên hiển thị trên màn hình hoặc xử lý các dữ liệu trước khi lưu dữ liệu xuống cơ sở dữ liệu.
    - Đây là nơi đê kiểm tra các yêu cầu nghiệp vụ, tính toán các yêu cầu nghiệp vụ.
    - Tại đây các tính năng tính toán trong chương trình sẽ được thực thi. (Như tính lương theo một công thức.)
    -à Nói chung tại layer này nó sẽ nhào nặn dữ liệu cho phù hợp trước khi lưu xuống hoặc hiển thị lên chương trình.
    3- Data Access Layer:
    - Layer này sẽ lo nhiệm vụ là đọc cơ sở dữ liệu lên, cập nhật cơ sở dữ liệu, update cơ sở dữ liệu.
    - Nói chung là nó làm nhiệm vụ là nói chuyện phải trái với database.
    4- Cách các layer “nói chuyện” với nhau.
    - Vấn đề đặt ra ở đây là 3 layer này ‘Nói chuyện’ với nhau như thế nào:
    Nhìn vào sơ đồ ta cũng sẽ nhận được câu trả lời:
    - Quá trình hiển thị dữ liệu:
    Data Access layer nói chuyện với Database và lấy dữ liệu lên theo một cách nào đó (có thể là bằng câu lệnh select hay thông qua proceduce) lúc này sau khi lấy được dữ liệu lên thì nó sẽ đẩy lên Business layer tại đây Business cần nhào bột, thêm mắm muối rồi đẩy nó lên trên GUI và tại GUI nó sẽ hiển thị lên cho người dùng.
    - Quá trình đưa dữ liệu xuống.
    Người dùng thao tác với GUI layer sau đó ra lệnh thực hiện (ví như Insert) sau đó hệ thống sẽ kiểm tra các thông tin người dùng nhập vào nếu thỏa đi xuống tiếp layer Business để tiếp tục được nhào nặn, tính toán và kiểm tra sau khi xong thì dữ liệu được đẩy xuống thông tin phía dưới Data Access Layer sau đó tại DataAccess Layer sẽ thực thi nó xuống database.
    5- Cách xử lý “lỗi” trong mô hình 3 layer.
    Một khi gặp lỗi (các trường hợp không đúng dữ liệu) thì đang ở layer nào thì quăng lên trên layer cao hơn nó 1 bậc cho tới GUI thì sẽ quăng ra cho người dùng biết.

    Giờ chưa có ví dụ, tối post tiếp

  2. #2
    Ngày gia nhập
    09 2007
    Bài viết
    724

    Mặc định Ví dụ cho mô hình 3-layer bằng C#

    Ví dụ:
    Viết chương trình tính tổng, hiệu, tích, thương.
    Đọc và ghi một phân số từ file xml.
    đây là hình ảnh chương trình:
    Click vào hình ảnh để lấy hình ảnh lớn

Tên:		vd3Layer-1.jpg
Lần xem:	16
Size:		14.1 KB
ID:		4990

    đây là file XML:

    XML Code:
    1. <zkday>
    2.   <TUSO>2</TUSO>
    3.   <MAUSO>3</MAUSO>
    4. </zkday>


    để cho tiện mình xin post từng lớp lên để các bạn tiện theo dõi.

    đây là lớp Info -- nó cũng được xem là nằm ở tầng GUI.
    Visual C# Code:
    1.  public class CPhanSoInfo
    2.     {
    3.         private int _tu;
    4.         private int _mau;
    5.  
    6.         public CPhanSoInfo()
    7.         {
    8.         }
    9.         public CPhanSoInfo(int tu, int mau)
    10.         {
    11.             _tu = tu;
    12.             _mau = mau;
    13.         }
    14.         public int tu
    15.         {
    16.             get
    17.             {
    18.                 return _tu;
    19.             }
    20.             set
    21.             {
    22.                 _tu = value;
    23.             }
    24.         }
    25.  
    26.         public int mau
    27.         {
    28.             get
    29.             {
    30.                 return _mau;
    31.             }
    32.             set
    33.             {
    34.                 _mau = value;
    35.             }
    36.         }
    37.  
    38.         private int USCLN(int a, int b)
    39.         {
    40.             a = Math.Abs(a); // lay tri tuyet doi cua a
    41.             b = Math.Abs(b); // lay tri tuyet doi cua b
    42.             if (a == 0 || b == 0)
    43.                 return 1;
    44.             while (a != b)
    45.             {
    46.                 if (a > b)
    47.                     a = a - b;
    48.                 else
    49.                     b = b - a;                
    50.             }
    51.             return a;
    52.         }
    53.  
    54.         public void RutGon()
    55.         {
    56.             int a = USCLN(_mau, _tu);
    57.             _mau /= a;
    58.             _tu /= a;          
    59.         }
    60.  
    61.         public override string ToString()
    62.         {
    63.             return _tu.ToString() + "/" + _mau.ToString();
    64.         }
    65.  
    66.        
    67.     }

    Đầu tiên sẽ là file form1.cs --- đây là ở tầng GUI của mình.
    Visual C# Code:
    1.  public partial class Form1 : Form
    2.     {
    3.         string sfileName = @"c:\\zkday.xml";
    4.         public Form1()
    5.         {
    6.             InitializeComponent();
    7.         }
    8.  
    9.         private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
    10.         {
    11.             if (e.KeyChar < '0' || e.KeyChar > '9')
    12.             {
    13.                 MessageBox.Show("Phải là số");
    14.                 e.Handled = true;
    15.             }            
    16.         }
    17.  
    18.         private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
    19.         {
    20.             try
    21.             {
    22.                 if (textBox1.Text != "" && textBox2.Text != "")
    23.                 {
    24.                     CPhanSoInfo infor = new CPhanSoInfo(int.Parse(textBox1.Text.ToString()), int.Parse(textBox2.Text.ToString()));
    25.                     CPhanSoCtrl ctrl = new CPhanSoCtrl();
    26.                     ctrl.Ghi(sfileName, infor);
    27.                 }
    28.                 else
    29.                 {
    30.                     MessageBox.Show("Khong duoc");
    31.                     textBox1.Focus();
    32.                 }
    33.             }
    34.             catch (Exception ex)
    35.             {
    36.                 MessageBox.Show(ex.Message,"Loi");
    37.             }
    38.         }
    39.  
    40.         private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
    41.         {
    42.             try
    43.             {
    44.                 if (textBox3.Text != "" && textBox4.Text != "")
    45.                 {
    46.                     CPhanSoInfo infor = new CPhanSoInfo(int.Parse(textBox3.Text.ToString()), int.Parse(textBox4.Text.ToString()));
    47.                     CPhanSoCtrl ctrl = new CPhanSoCtrl();
    48.                     ctrl.Ghi(sfileName, infor);
    49.                 }
    50.                 else
    51.                 {
    52.                     MessageBox.Show("Khong duoc");
    53.                     textBox3.Focus();
    54.                 }
    55.             }
    56.             catch (Exception ex)
    57.             {
    58.                 MessageBox.Show(ex.Message, "Loi");
    59.             }
    60.         }
    61.  
    62.         private void button1_Click(object sender, EventArgs e)
    63.         {
    64.             //tong
    65.            
    66.             CPhanSoInfo ps1 = new CPhanSoInfo(int.Parse(textBox1.Text.ToString()), int.Parse(textBox2.Text.ToString()));
    67.             CPhanSoInfo ps2 = new CPhanSoInfo(int.Parse(textBox3.Text.ToString()), int.Parse(textBox4.Text.ToString()));
    68.             MessageBox.Show(CPhanSoCtrl.Tong(ps1,ps2).ToString());
    69.         }
    70.  
    71.         private void button2_Click(object sender, EventArgs e)
    72.         {
    73.             //hieu
    74.             CPhanSoInfo ps1 = new CPhanSoInfo(int.Parse(textBox1.Text.ToString()), int.Parse(textBox2.Text.ToString()));
    75.             CPhanSoInfo ps2 = new CPhanSoInfo(int.Parse(textBox3.Text.ToString()), int.Parse(textBox4.Text.ToString()));
    76.             MessageBox.Show(CPhanSoCtrl.Hieu(ps1,ps2).ToString());
    77.         }
    78.  
    79.         private void button3_Click(object sender, EventArgs e)
    80.         {
    81.             //tich
    82.             CPhanSoInfo ps1 = new CPhanSoInfo(int.Parse(textBox1.Text.ToString()), int.Parse(textBox2.Text.ToString()));
    83.             CPhanSoInfo ps2 = new CPhanSoInfo(int.Parse(textBox3.Text.ToString()), int.Parse(textBox4.Text.ToString()));
    84.             MessageBox.Show(CPhanSoCtrl.Tich(ps1, ps2).ToString());
    85.         }
    86.  
    87.         private void button4_Click(object sender, EventArgs e)
    88.         {
    89.             //thuong
    90.             CPhanSoInfo ps1 = new CPhanSoInfo(int.Parse(textBox1.Text.ToString()), int.Parse(textBox2.Text.ToString()));
    91.             CPhanSoInfo ps2 = new CPhanSoInfo(int.Parse(textBox3.Text.ToString()), int.Parse(textBox4.Text.ToString()));
    92.             MessageBox.Show(CPhanSoCtrl.Thuong(ps1, ps2).ToString());
    93.         }
    94.  
    95.         private void button5_Click(object sender, EventArgs e)
    96.         {
    97.             MessageBox.Show("Ket thuc");
    98.             Application.Exit();
    99.         }
    100.  
    101.         private void button6_Click(object sender, EventArgs e)
    102.         {
    103.             //doc
    104.             CPhanSoInfo ps = new CPhanSoInfo();
    105.             CPhanSoCtrl psCtrl = new CPhanSoCtrl();
    106.             ps = psCtrl.Doc(sfileName);
    107.             MessageBox.Show(ps.ToString());
    108.         }
    109.            
    110.     }

    -Đây là file ở layer Business của mình: (mình đặt là CxxxCtrl với xxx là tên đối tượng).
    Visual C# Code:
    1. public class CPhanSoCtrl
    2.     {
    3.  
    4.         public static CPhanSoInfo Hieu(CPhanSoInfo phanso1, CPhanSoInfo phanso2)
    5.         {
    6.             CPhanSoInfo result = new CPhanSoInfo();
    7.             result.tu = phanso1.tu * phanso2.mau - phanso1.mau * phanso2.tu;
    8.             result.mau = phanso1.mau * phanso2.mau;
    9.  
    10.             result.RutGon();
    11.             return result;
    12.         }
    13.  
    14.         public static CPhanSoInfo Tich(CPhanSoInfo phanso1, CPhanSoInfo phanso2)
    15.         {
    16.             CPhanSoInfo result = new CPhanSoInfo();
    17.             result.tu = phanso1.tu * phanso2.tu;
    18.             result.mau = phanso1.mau * phanso2.mau;
    19.  
    20.             result.RutGon();
    21.             return result;
    22.         }
    23.  
    24.         public static CPhanSoInfo Thuong(CPhanSoInfo phanso1, CPhanSoInfo phanso2)
    25.         {
    26.             CPhanSoInfo result = new CPhanSoInfo();
    27.             result.tu = phanso1.tu * phanso2.mau;
    28.             result.mau = phanso1.mau * phanso2.tu;
    29.  
    30.             result.RutGon();
    31.             return result;
    32.         }
    33.  
    34.         public static CPhanSoInfo Tong(CPhanSoInfo phanso1, CPhanSoInfo phanso2)
    35.         {
    36.             CPhanSoInfo result = new CPhanSoInfo();
    37.             result.tu = phanso1.tu * phanso2.mau + phanso1.mau * phanso2.tu;
    38.             result.mau = phanso1.mau * phanso2.mau;
    39.  
    40.             result.RutGon();
    41.             return result;
    42.         }
    43.  
    44.         public CPhanSoInfo Doc(string sFileName)
    45.         {
    46.             CPhanSoInfo psResult = new CPhanSoInfo();
    47.             CPhanSoDAO dao = new CPhanSoDAO();
    48.             return dao.Doc(sFileName);
    49.         }
    50.  
    51.         public void Ghi(string sFileName, CPhanSoInfo info)
    52.         {
    53.             if (info.tu == info.mau)
    54.             {
    55.                 throw new Exception("Người lớn không chơi với tử bằng mẫu");
    56.             }
    57.             if (info.tu == 1)
    58.             {
    59.                 throw new Exception("Chương trình không chơi với tử  bằng 1!!!");                
    60.             }
    61.             if (info.mau == 1)
    62.             {
    63.                 throw new Exception("Chương trình không chơi với mẫu bằng 1!!!");
    64.             }
    65.            
    66.                 CPhanSoDAO dao = new CPhanSoDAO();
    67.                 dao.Ghi(sFileName, info);
    68.            
    69.         }
    70.     }

    cuối cùng là: DataAccess Layer

    Qui tắc đặt tên của mình là: CXxxDAO với Xxx là tên của đối tượng.

    Visual C# Code:
    1.   public class CPhanSoDAO
    2.     {
    3.         public CPhanSoInfo Doc(string sfileName)
    4.         {
    5.             CPhanSoInfo info = new CPhanSoInfo();
    6.             XmlDocument psDoc = new XmlDocument();
    7.             psDoc.Load(sfileName); // mo file XML
    8.             if (psDoc != null)
    9.             {
    10.                 XmlElement e = psDoc.DocumentElement;
    11.                 info.tu = int.Parse(e.SelectSingleNode("TUSO").InnerText);
    12.                 info.mau = int.Parse(e.SelectSingleNode("MAUSO").InnerText);
    13.             }
    14.             return info;
    15.         }
    16.  
    17.         public void Ghi(string sfileName, CPhanSoInfo info)
    18.         {
    19.             try
    20.             {
    21.                 XmlDocument docPhanSo = new XmlDocument();
    22.                 XmlElement rootDocXML = docPhanSo.CreateElement("zkday");
    23.                 docPhanSo.AppendChild(rootDocXML);
    24.                 XmlElement ele_Tuso = rootDocXML.OwnerDocument.CreateElement("TUSO");
    25.                 ele_Tuso.InnerText = info.tu.ToString();
    26.                 rootDocXML.AppendChild(ele_Tuso);
    27.                 XmlElement ele_Mauso = rootDocXML.OwnerDocument.CreateElement("MAUSO");
    28.                 ele_Mauso.InnerText = info.mau.ToString();
    29.                 rootDocXML.AppendChild(ele_Mauso);
    30.  
    31.                 docPhanSo.Save(sfileName);
    32.             }
    33.             catch (Exception e)
    34.             {
    35.                 throw new Exception("Loi trong qua trinh ghi du lieu:"+e.Message.ToString());
    36.             }
    37.         }
    38.     }

    Còn đây là toàn bộ code của chương trình:
    Lưu ý tên file XML mình để cố định tại: C:\zkday.xml
    vì bài này chỉ mang tính demo nên nó còn rất chuối nải. các bạn nếu có thắc mắc thì có thể PM yêu cầu mình mở lại Topic để hỏi hoặc có thể tạo một topic khác để hỏi.

    ^_^ Chúc vui vẻ ^_^
    Attached Files Attached Files

  3. #3
    Ngày gia nhập
    01 2008
    Nơi ở
    Gameloft Studio
    Bài viết
    294

    bài này chỉ mang tính demo nên nó còn rất chuối nải
    Chuối thiệt!

    Có 1 câu hỏi:
    - Tại sao phải dùng kiến trúc 3Tier?

  4. #4
    Ngày gia nhập
    09 2007
    Bài viết
    724

    - Tại sao phải dùng kiến trúc 3Tier?
    Bài này mình chỉ nói về 3-Layer thui còn 3Tier thì mình vẫn đang ngâm cứu, chưa lĩnh hội được nó nên chưa dám nói . Hy vọng sẽ có ai đó làm 1 tut nói về cái này

  5. #5
    Ngày gia nhập
    11 2006
    Bài viết
    633

    Hỏi ngược lại ZCoder87, 3-tier và 3-layer khác nhau hay giống nhau? Nếu khác thì khác như thế nào

  6. #6
    Ngày gia nhập
    09 2007
    Bài viết
    724

    Mặc định Tìm hiểu mô hình 3-layer trong CNPM

    Tính để kéo sang topic khác mà thấy anh HuyNguyen và ZC nói, hồi chiều mới tiếp nhận được 1 ít kéo dài topic này ra luôn vì 2 cái này có liên hệ với nhau.

    Mới tìm hiểu nên chưa sâu có gì nhờ các bác chỉ giáo giúp cho hiểu sâu nó luôn .

    2 cu này thực chất là 2 thằng chẳng liên quan gì tới nhau cả. Nhưng nó có mối liên hệ mật thiết với nhau trong CNPM.

    - 3 layer là một thể hiện của kiến trúc phần mềm ở dạng Logic.
    - 3 tier là một thể hiện của kiến trúc phần mềm ở dạng vật lý.

    vì sao zkday lại nói như vậy. vì 3 layer nó chia 1 lớp đối tượng thành 3 phần và cả 3 phần này đều chạy trên một máy. còn 3 tier thì nó là kiến trúc phần mềm mà khi chia ra thì nó chạy trên nhiều máy (1 phần chạy ở một máy khác nhau).
    3 tier nó chia phần mềm thành 3 phần riêng biệt và run trên 3 máy khác nhau.
    1 - Data tier: tại đây nó sẽ run Data Access Layer của 3 layer. (cái máy này thì nó là máy chuyên chứa data để chúng ta truy xuất)
    2 - Business tier: tại đây nó run Business Layer của 3 layer. (cái máy này thì là nó chuyên gia tính toán và thực thi các nghiệp vụ)
    3 - Presentation tier: tại đây nó run thằng GUI layer (giao diện) của 3 layer. (cái này là máy con chỉ nhận và hiển thị dữ liệu lên cho người dùng)

    - nói chung thì theo zkday hiểu thì:
    - 3 layer là nó chia của lớp đối tượng.
    - 3 Tier là nó chia của một phần mềm để chạy được trên mô hình nhiều máy (mỗi máy có môt chức năng riêng biệt) như zkday nói ở trên.

    Để tìm hiểu sâu và demo được 3 Tier lúc trước anh Dark có nói với zkday là dùng WebServices của VS. (cái này giờ zkday vẫn chưa làm được vì đang ngâm cứu )

    Mới tìm hiểu còn hiểu chưa hết có gì mong các bác chỉ giáo
    Đã được chỉnh sửa lần cuối bởi zkday2686 : 20-11-2008 lúc 12:09 PM. Lý do: Truy Suất --> Truy xuất

  7. #7
    Ngày gia nhập
    11 2007
    Bài viết
    294

    Khuyến mãi cho mấy cái so sánh tier với layer ^^!
    Ref Link Code:

    Mà a nói dùng webservice cho ntier bao giờ nhỉ
    A nhớ chỉ nói duy nhất 1 cái về webservice là ở mô hình SOA khi nói với ZC. Còn dùng trong ntier thì dùng remoting(đang định làm 1 cái tut về cái này ^^) hay webservice đều được cả mà ^^!

    Cheers!
    Đã được chỉnh sửa lần cuối bởi darkan : 19-11-2008 lúc 10:28 PM.
    Is the moon rising...

  8. #8
    Ngày gia nhập
    09 2007
    Bài viết
    724

    hi hi. thank anh dark vì mấy cái link .
    không những zc mà em cũng đang chờ cái topic của anh về SOA.
    Thằng remoting em chỉ mới nghe nói nhưng chưa biết mặt mủi nó thế nào. Không biết nó có giống webservice không nhỉ Ngồi chờ topic của anh vậy


    Mà a nói dùng webservice cho ntier bao giờ nhỉ
    ở đây nè anh dark: http://forums.congdongcviet.com/showthread.php?t=9810 (nhớ có mà kiếm hoài mới ra )

    Cheers! ( cr@ck chữ ký của anh dark cái )

  9. #9
    Ngày gia nhập
    01 2008
    Nơi ở
    Gameloft Studio
    Bài viết
    294

    Tiếc quá Z!
    Trước giờ ZC cứ nghĩ 3 Layer với 3 Tier là 1.

  10. #10
    Ngày gia nhập
    11 2006
    Bài viết
    633

    Mới học ai cũng nghĩ là 1, thậm chí thầy của mình còn gọi sai mà.

Các đề tài tương tự

  1. [3 layer model] minh họa trong bài tính tổng phân số
    Gửi bởi zstar trong diễn đàn Dự án & Source code C#, ASP.NET
    Trả lời: 0
    Bài viết cuối: 14-12-2010, 10:27 PM
  2. 3 layer trong c#
    Gửi bởi daivuongtiep trong diễn đàn Dự án & Source code C#, ASP.NET
    Trả lời: 13
    Bài viết cuối: 21-03-2010, 01:05 AM
  3. Lỗi khi cập nhật dữ liệu vào bảng trong ứng dụng mô hình 3 layer trên C#?
    Gửi bởi honeydt trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 3
    Bài viết cuối: 14-05-2009, 07:23 PM
  4. làm sao để tạo layer như trong Photoshop với lập trình C#?
    Gửi bởi HKuspc trong diễn đàn Thắc mắc lập trình C#
    Trả lời: 2
    Bài viết cuối: 04-11-2008, 08:22 PM
  5. Xin BQTcho phép tôi có quyền chỉnh sửa bài trong box CNPM
    Gửi bởi huynguyen trong diễn đàn Ý kiến, đề xuất và khiếu nại
    Trả lời: 7
    Bài viết cuối: 28-02-2008, 02:05 AM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn