@fui-org/mlis-cli 0.0.0-stage → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -2
- package/dist/mlis.js +86 -0
- package/package.json +32 -4
- package/render/MlisRender.cs +298 -0
- package/render/SampleDataConnection.cs +320 -0
- package/skills/mlis/SKILL.md +147 -0
- package/skills/mlis/references/cdn-files.md +38 -0
- package/skills/mlis/references/controls.md +161 -0
- package/skills/mlis/references/design-patterns.md +94 -0
- package/skills/mlis/references/news.md +65 -0
- package/skills/mlis/references/rendered-html.md +91 -0
- package/skills/mlis/references/viewpage-structure.md +105 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mlis
|
|
3
|
+
description: Dùng cho mọi việc thiết kế giao diện website MLIS (lhu.edu.vn và các site MLIS khác) qua CLI `mlis` — xem, tải về, sửa và đẩy lên các trang .ascx/.css/.js cùng hình, font trong thư mục ViewPage, dùng các control <MLIS:NewsList>, <MLIS:CatMenu>, <MLIS:LoadPage>…, đọc/sửa bài viết (tin tức) cấp nội dung động cho trang, và upload tài liệu qua CKFinder. Kích hoạt khi người dùng nói đến ViewPage, trang ascx, giao diện MLIS, PageStyle, HeaderOfSite, hoặc gọi lệnh mlis.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# MLIS ViewPage với `mlis`
|
|
7
|
+
|
|
8
|
+
`mlis` là CLI làm việc với API `api/viewpage/*` của website MLIS (ASP.NET). Mọi trang giao diện nằm trong thư mục `ViewPage/` trên server:
|
|
9
|
+
- **.ascx, .css, .js** — sửa như văn bản, có diff.
|
|
10
|
+
- **Hình, font, media, pdf** (png, jpg, gif, webp, svg, ico, avif, woff/woff2/ttf/otf/eot, mp4/webm/mp3, pdf; ≤ 10 MB) — `pull`/`push`/`rm` như file code nhưng chỉ so khác/giống. Cần server có API `UploadFile`/`DownloadFile`; server cũ sẽ báo cần deploy.
|
|
11
|
+
- Tài liệu dùng trong bài viết (doc, xls, zip…) hoặc ảnh không thuộc giao diện → CKFinder (`mlis cdn`), lưu ở `/Data/...`.
|
|
12
|
+
|
|
13
|
+
## Chuẩn bị (một lần)
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
mlis config # xem url, workdir, token (chỉ hiện "(set)")
|
|
17
|
+
mlis token set # dán giá trị cookie jwtAuth (prompt ẩn, hoặc pipe qua stdin)
|
|
18
|
+
mlis config set url https://lhu.edu.vn
|
|
19
|
+
mlis config set cdn-cat <CatID> # thư mục (CatID) chứa hình/tài liệu cho CKFinder
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Token là cookie `jwtAuth` của tài khoản có SystemRight ≥ 3. **Không bao giờ** in, dán vào chat, ghi vào file hay truyền token làm tham số dòng lệnh; không `cat` file config. Lỗi "server rejected the token" → nhờ người dùng chạy lại `mlis token set`.
|
|
23
|
+
|
|
24
|
+
## Người dùng đưa URL của một trang: tìm template đang vẽ trang đó
|
|
25
|
+
|
|
26
|
+
Sửa "trang `https://…`" nghĩa là sửa **template trong ViewPage** mà site dùng cho URL đó (hoặc bài viết, nếu chỉ đổi chữ). Không đoán, hỏi CLI:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
mlis page https://tuyensinh.lhu.edu.vn/ # tên miền → thư mục trang chủ → PageStyle
|
|
30
|
+
mlis page https://lhu.edu.vn/446/3387/ten-bai.html # /CatID/NewsID → PageRead của thư mục 446 (+ NewsID để sửa nội dung)
|
|
31
|
+
mlis page https://lhu.edu.vn/more-list/21/0/0/x.html --pull # tải template + các file nó LoadPage + HeaderOfSite về workspace
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Kết quả: `template` (thư mục ViewPage có default.ascx), `includes` (Header/Footer… nạp bằng LoadPage — chữ nằm ở header/footer thì sửa file đó), `head` (HeaderOfSite), `shared` (**bao nhiêu thư mục cùng dùng template này** — sửa template là đổi tất cả; nếu chỉ một thư mục cần khác, báo người dùng và đề xuất template riêng), `content` (NewsID → `mlis news pull`). Một máy chủ MLIS phục vụ nhiều tên miền (lhu.edu.vn, tuyensinh.lhu.edu.vn, sinhvientuonglai.lhu.edu.vn…) với **chung một ViewPage**: dùng chung một workspace, không tạo `--workdir` mới cho tên miền khác (CLI tự nhận ra cùng máy chủ; chỉ máy chủ MLIS khác mới cần workspace riêng).
|
|
35
|
+
|
|
36
|
+
## Quy trình chuẩn
|
|
37
|
+
|
|
38
|
+
1. **Xem**: `mlis tree [folder] [--files]`, `mlis ls <folder>`, `mlis cat <file>`.
|
|
39
|
+
2. **Tải về**: `mlis pull <folder|file>` → bản sao ở `<workdir>/<đường dẫn ViewPage>` (mặc định `C:\APP\mlis-workspaces\…`). Mỗi workspace dành cho một máy chủ MLIS (mọi tên miền của nó). Luôn pull trước khi sửa; file local lâu ngày có thể đã cũ — chạy `mlis status <folder> --remote` để kiểm.
|
|
40
|
+
3. **Sửa** file trong workspace (Edit/Write trực tiếp file local).
|
|
41
|
+
4. **Kiểm**: `mlis status <folder>` (new/changed/missing) và `mlis diff <file|folder>` (so với bản đang chạy trên server). Đọc kỹ diff trước khi đẩy.
|
|
42
|
+
5. **Đẩy**: `mlis push <file|folder>...` (`--dry-run` để xem trước). Trước khi ghi, bản server được lưu vào `_history/`.
|
|
43
|
+
6. **Xác minh**: mở trang thật trên trình duyệt. Khách chưa đăng nhập có thể thấy HTML cũ tới **60 giây** (HtmlPageCache); CSS được nạp kèm `?version` của site nên trình duyệt có thể giữ CSS cũ — tải lại cứng (Ctrl+F5) hoặc kiểm bằng `mlis cat`.
|
|
44
|
+
|
|
45
|
+
Đường dẫn: dùng đường dẫn ViewPage như `LHUENB4/@HomePage/default.ascx` (có thể kèm tiền tố `ViewPage/`), hoặc đường dẫn local nằm trong workspace (`.\default.ascx` khi đang đứng trong thư mục đó).
|
|
46
|
+
|
|
47
|
+
## Thiết kế một trang: dữ liệu → mã → xem nháp → đẩy
|
|
48
|
+
|
|
49
|
+
1. **Biết trang phục vụ thư mục nào và lấy dữ liệu từ đâu** — không đoán CatID/Location:
|
|
50
|
+
```bash
|
|
51
|
+
mlis category find "tuyển sinh" # tìm CatID theo tên (bỏ dấu cũng được)
|
|
52
|
+
mlis category pages LHUENB4/DefaultPageCatalog # thư mục nào đang dùng trang này (page/read)
|
|
53
|
+
mlis category tree 21 --depth 2 # cây con: id, kiểu, page/read, loc:Location1,2,3
|
|
54
|
+
mlis category ls 21 # thư mục con của 21 và Location của chúng
|
|
55
|
+
mlis category show 21 # mọi cấu hình + đường dẫn + tên miền chủ
|
|
56
|
+
```
|
|
57
|
+
`<MLIS:NewsList CatID="21" Location="22">` lấy tin của **các thư mục con của 21 có Location1/2/3 = 22** (mỗi thư mục con một khối ListFormat). `Location="0"` lấy tin của chính CatID. `CatID="-100"` = thư mục đang mở, `0` = trang chủ tên miền. Danh sách thư mục lưu ở workspace; `mlis category sync` để làm mới (dùng chung API của trang quản trị thư mục `/api/admin/GetAllFolder`, `GetFolderList`).
|
|
58
|
+
2. **Viết mã**: xem mẫu thật cùng loại (`mlis skill ref design-patterns`), thuộc tính control (`controls`), HTML control sinh ra để viết CSS (`rendered-html`). Xong thì **`mlis check <thư mục>`**: bắt đường dẫn `ViewPage/...` không tồn tại (Src, CssFolder, href/src, url()), thẻ MLIS thiếu `runat="server"`, dấu `{`/`}` lạc trong format (làm trang lỗi), directive `CodeFile`, ảnh thiếu/giữ chỗ `alt`, số `<h1>`, thẻ SEO trùng với nền tảng. Sửa hết `error` trước khi render/push (exit code 1 khi còn error).
|
|
59
|
+
3. **Tự render trên máy và xem ảnh chụp trước khi đẩy** — không ghi gì lên server:
|
|
60
|
+
```bash
|
|
61
|
+
mlis render shot LHUENB4/MyPage # trang thư mục; in đường dẫn ảnh desktop (1366px) + mobile (390px)
|
|
62
|
+
mlis render shot LHUENB4/@HomePage --full # trang chủ, chụp cả trang
|
|
63
|
+
mlis render shot LHUENB4/@ReadPage # trang đọc tin (bài mẫu)
|
|
64
|
+
mlis render shot LHUENB4/MyPage --as read # thư mục không có "home"/"read" trong tên: chọn kiểu bằng --as
|
|
65
|
+
mlis render shot LHUENB4/_default/Box.ascx # xem riêng một control (trang bọc + HeaderOfSite)
|
|
66
|
+
mlis render start LHUENB4/MyPage # chỉ chạy, in http://localhost:5080/… để mở bằng trình duyệt
|
|
67
|
+
mlis render stop
|
|
68
|
+
```
|
|
69
|
+
`mlis render` chạy chính mã nền tảng (Default.aspx, App_Code, control MLIS) từ `site-src` (mặc định `C:\APP\MLIS_2025`) trên `http://localhost:<render-port>`, thư mục ViewPage trỏ thẳng vào workspace (sửa file là thấy khi chạy lại), cơ sở dữ liệu thay bằng **dữ liệu mẫu**: thư mục mẫu cho mọi `CatID`/`Location` mà trang và các file nó `LoadPage` dùng (3 thư mục con mỗi Location, mỗi cái 2 con), tin mẫu có tiêu đề/tóm tắt/nội dung tiếng Việt, hình giữ chỗ ghi kích thước (`tin-<cat>-<k> · 800×500`). Vì ViewPage chỉ là khuôn, dữ liệu thật không cần có sẵn. File tĩnh nền tảng mà bản local thiếu được lấy từ site thật (chỉ GET, lưu đệm). Lần đầu mất ~1 phút để biên dịch site, các lần sau vài giây. Lỗi biên dịch/parse của .ascx được in ra kèm file và dòng.
|
|
70
|
+
**Mở các ảnh PNG (Read) và tự review**: bố cục, tràn ngang, chữ tiếng Việt, khoảng cách, mobile; đối chiếu yêu cầu, sửa rồi chạy lại cho tới khi đạt. Cần Windows + .NET Framework 4 và `playwright` (Chromium).
|
|
71
|
+
4. **Đẩy trang thật**: `mlis check` → `mlis diff` → `mlis push` → mở trang thật kiểm lại. Trang mới cần người dùng gán PageStyle/PageRead trong /admin (CLI không làm được).
|
|
72
|
+
|
|
73
|
+
## Nội dung động: đặt chữ trong bài viết, không cứng trong .ascx
|
|
74
|
+
|
|
75
|
+
Chữ/hình hay đổi (giới thiệu, thông báo, số liệu, thẻ, slider, FAQ) nên lấy từ **bài viết** qua `<MLIS:NewsDetail NewsID="…" NewsFormat="{4}">` (một khối) hoặc `<MLIS:NewsList CatID="…">` (mỗi bài một khối), để người quản trị sửa trong /admin mà không đụng mã. Khi người dùng muốn **đổi nội dung** đang hiển thị: tìm CatID/NewsID trong .ascx, rồi `mlis news ls <CatID>` → `mlis news pull <NewsID>` → sửa `_news/<NewsID>.html` → `mlis news diff` → `mlis news push`. Đổi chữ thì sửa bài, không sửa .ascx. Chi tiết, định dạng file và quy tắc: `mlis skill ref news`.
|
|
76
|
+
|
|
77
|
+
## Quy tắc thiết kế (SEO, AI search, truy cập)
|
|
78
|
+
|
|
79
|
+
- **Một `<h1>` mỗi trang.** Trang đọc tin: h1 là tiêu đề bài (`{1}` của NewsDetail sinh `<h1 class=NTitle>`) — không thêm h1 khác. Trang chủ/trang thư mục: tự đặt một h1 (tên trang/thư mục, có thể ẩn bằng CSS chuẩn `visually-hidden` nếu thiết kế không muốn hiện); tiêu đề khối dùng h2/h3 (`CatFormat="<h2>…</h2>"`).
|
|
80
|
+
- **Ảnh có ý nghĩa phải có `alt`** mô tả nội dung; ảnh trang trí đặt `alt=""` hoặc dùng CSS background. Không đưa chữ quan trọng vào ảnh.
|
|
81
|
+
- Nội dung chính nằm trong HTML khi tải trang, không sinh bằng JavaScript (crawler AI không chạy JS). Không ẩn nội dung chính trong tab/accordion chỉ mở bằng JS mà không có HTML sẵn.
|
|
82
|
+
- Liên kết có chữ mô tả rõ ("Thông báo tuyển sinh 2027", không "Xem tại đây"); dùng `<a href>` thật, không `onclick`.
|
|
83
|
+
- Không thêm `<title>`, `meta description`, `og:*`, canonical, JSON-LD Breadcrumb/NewsArticle vào ascx/HeaderOfSite — nền tảng đã tự thêm (`viewpage-structure` → "Những gì nền tảng tự làm").
|
|
84
|
+
- Kiểm tra mobile: Bootstrap grid (`col-12 col-md-…`), ảnh `max-width:100%`, không chiều rộng cố định.
|
|
85
|
+
|
|
86
|
+
## An toàn
|
|
87
|
+
|
|
88
|
+
- `push` dừng với **exit 3** nếu file trên server đã bị sửa sau lần pull cuối (hoặc tồn tại mà chưa từng pull). Không tự ý thêm `--force`: chạy `mlis diff <file>`, báo người dùng, rồi chọn: giữ bản mình (`push --force`, bản server vào `_history`) hoặc lấy bản server (`pull <file> --force`, bản local vào `_history`) rồi sửa lại.
|
|
89
|
+
- `pull` không ghi đè file local đang sửa dở (báo `kept-local`); `--force` mới ghi đè và lưu bản local vào `_history`.
|
|
90
|
+
- Xoá (`mlis rm`, `mlis rmdir`, `mlis cdn rm/rmdir`) là vĩnh viễn trên server: chỉ chạy khi người dùng đồng ý rõ ràng cho đúng file đó, kèm `--confirm-delete`. Yêu cầu "sửa trang" không bao hàm quyền xoá file.
|
|
91
|
+
- Site đang chạy thật: thay đổi có hiệu lực ngay cho người xem. Sửa trang chủ/HeaderOfSite/_default (dùng chung toàn site) cần cẩn thận gấp đôi; luôn `mlis render shot` và xem ảnh trước khi `push` trang thật.
|
|
92
|
+
- Một lỗi cú pháp trong .ascx làm trang lỗi ngay (redirect `/error`). Giữ thẻ `runat="server"` đóng đúng, thuộc tính dùng nháy kép bên ngoài và nháy đơn bên trong chuỗi format (`ListFormat="<div class='row'>{1}</div>"`), hoặc dùng thẻ con `<NewsFormat>…</NewsFormat>` khi format dài/phức tạp.
|
|
93
|
+
- `mlis history <file>` liệt kê bản sao lưu; `mlis restore <file> [--at stamp]` đưa bản cũ về local rồi `push` để khôi phục.
|
|
94
|
+
|
|
95
|
+
## Tạo trang mới
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
mlis new LHUENB4/MyPage/Default.ascx # trang (LoadPage css + Header/Footer của _default) — chỉ tạo trong workspace
|
|
99
|
+
mlis new LHUENB4/MyPage/StyleMain.css # css cùng thư mục được LoadPage CssFolder nạp tự động
|
|
100
|
+
mlis new LHUENB4/_default/Box.ascx # control con, chèn bằng <MLIS:LoadPage Src="ViewPage/LHUENB4/_default/Box.ascx" runat="server" />
|
|
101
|
+
# viết mã → mlis check LHUENB4/MyPage → mlis render shot LHUENB4/MyPage → xem ảnh, sửa → lặp lại
|
|
102
|
+
mlis push LHUENB4/MyPage # khi đã đạt: tạo thư mục + file trên server (bản sạch, không CodeFile)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`mlis new` chỉ ghi vào workspace (nội dung mẫu sạch, không có `<%@ Control CodeFile=… %>` — trang ViewPage không có code-behind); server chưa có gì cho tới `mlis push`. `--push` tạo luôn trên server — không dùng khi chưa render/review, nhất là với trang route `_<Tên>` (có URL ngay khi file tồn tại). Trang thư mục mới chỉ hiển thị khi một thư mục (category) trong /admin có PageStyle = `LHUENB4/MyPage` — việc này người dùng làm.
|
|
106
|
+
|
|
107
|
+
**Đặt tên thư mục** (chi tiết: `mlis skill ref viewpage-structure`):
|
|
108
|
+
- Không có `_` ở đầu → là "trang", chọn được làm PageStyle/PageRead của thư mục (chỉ cấp `<site>/<trang>` hoặc `<site>/<trang>/<con>`, tối đa 50 ký tự).
|
|
109
|
+
- `_` ở đầu → thư mục hỗ trợ, bị ẩn khỏi ô chọn trang: `_default` (header/footer/css dùng chung), `_assets` (HeaderOfSite.ascx, favicon.ico, default_image.png — tên cố định), `_images`/`_fonts` (tài nguyên của trang), `_bk` (sao lưu).
|
|
110
|
+
- `_<Tên>/default.ascx` còn là trang theo URL `/<Tên>/…` (`_Search`, `_Index`, `_RSS`, `_Event`, `_more-List`…): tạo `LHUENB4/_LienHe/default.ascx` là có `https://<site>/LienHe` mà không cần tạo thư mục trong /admin.
|
|
111
|
+
- `@` ở đầu (`@HomePage`, `@ReadPage`) chỉ là quy ước cho trang chính, không có xử lý riêng.
|
|
112
|
+
|
|
113
|
+
## Hình ảnh, font và tài liệu
|
|
114
|
+
|
|
115
|
+
Hình/font của giao diện để ngay trong ViewPage, cạnh trang dùng nó:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# chép file vào workspace rồi đẩy lên như file code
|
|
119
|
+
copy .\hero.webp C:\APP\mlis-workspaces\LHUENB4\MyPage\_images\hero.webp
|
|
120
|
+
mlis status LHUENB4/MyPage
|
|
121
|
+
mlis push LHUENB4/MyPage
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Trong css của trang dùng đường dẫn tương đối `url(_images/hero.webp)`; trong .ascx dùng `/ViewPage/LHUENB4/MyPage/_images/hero.webp`.
|
|
125
|
+
|
|
126
|
+
Tài liệu đính kèm (doc, xls, zip…) hoặc file muốn quản lý qua CKFinder:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
mlis cdn info # Images/Files: URL gốc, giới hạn, đuôi cho phép
|
|
130
|
+
mlis cdn mkdir banner # thư mục trong Images
|
|
131
|
+
mlis cdn upload .\logo.png --to banner # in {"url":"/Data/Folders/<CatID>/images/banner/logo.png"}
|
|
132
|
+
mlis cdn upload .\quyche.pdf --type Files # tài liệu → Files
|
|
133
|
+
mlis cdn list banner # liệt kê + URL
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Dán **URL tương đối** in ra vào .ascx/.css (`<img src="/Data/Folders/…">`, `background:url(/Data/Folders/…)`). CKFinder có thể đổi tên khi trùng hoặc thu nhỏ ảnh quá khổ — luôn dùng URL mà lệnh trả về. Chi tiết: `mlis skill ref cdn-files`.
|
|
137
|
+
|
|
138
|
+
## Tham khảo
|
|
139
|
+
|
|
140
|
+
- `mlis skill ref controls` — thuộc tính và placeholder `{n}` của từng control MLIS (NewsList, CatMenu, CatShow, EventList, NewsDetail, …), giá trị CatID/Location/PageLink/Visibility.
|
|
141
|
+
- `mlis skill ref rendered-html` — HTML mà từng control sinh ra (class, cấu trúc) để viết CSS đúng.
|
|
142
|
+
- `mlis skill ref design-patterns` — mẫu trang thật đang chạy (trang chủ, trang thư mục, trang đọc tin, header/footer) và các quy ước CSS/JS của site.
|
|
143
|
+
- `mlis skill ref viewpage-structure` — cách site chọn trang (PageStyle/PageRead, route `_<Tên>`), nhiều tên miền, những gì nền tảng tự thêm, quy ước tiền tố `_`/`@`, file tĩnh.
|
|
144
|
+
- `mlis skill ref news` — nội dung động bằng bài viết: NewsDetail/NewsList làm khuôn, `mlis news ls|show|pull|diff|push|new`, định dạng file `_news/<NewsID>.html`, quy tắc lưu bài của server, sự kiện, xung đột.
|
|
145
|
+
- `mlis skill ref cdn-files` — CKFinder: CatID, mode folder/news, Images/Files.
|
|
146
|
+
|
|
147
|
+
Lệnh luôn in dữ liệu ra stdout (bảng khi ở terminal, TSV khi pipe, `--json` cho máy), ghi chú/lỗi ra stderr. Exit code: 0 ok, 1 lỗi, 2 sai cú pháp, 3 bị chặn an toàn.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Hình ảnh và tài liệu qua CKFinder (`mlis cdn`)
|
|
2
|
+
|
|
3
|
+
Hình/font thuộc giao diện nên để ngay trong ViewPage (`mlis push`, xem viewpage-structure). CKFinder dành cho file nằm ngoài ViewPage: tài liệu đính kèm (doc, xls, zip…), ảnh dùng chung với bài viết, hoặc khi server chưa có API `UploadFile`. CLI dùng CKFinder 2.6.3 có sẵn của MLIS (`/JScript/CKFinder/core/connector/aspx/connector.aspx`) với cùng token `jwtAuth`.
|
|
4
|
+
|
|
5
|
+
## Nơi lưu file
|
|
6
|
+
|
|
7
|
+
CKFinder của MLIS gắn với một **thư mục (CatID)** trong trang quản trị:
|
|
8
|
+
- `--mode folder` (mặc định): `/Data/Folders/<CatID>/images/…` và `/Data/Folders/<CatID>/files/…`
|
|
9
|
+
- `--mode news`: `/Data/News/<CatID>/…`
|
|
10
|
+
|
|
11
|
+
Đặt CatID mặc định một lần: `mlis config set cdn-cat <CatID>` (hoặc `--cat` cho từng lệnh). Nên dùng một thư mục riêng cho tài nguyên giao diện, hỏi người dùng CatID nào nếu chưa đặt. CLI tự "mồi" session bằng `/Admin/CKFinder.aspx?CatID=…&mode=…` trước khi gọi connector.
|
|
12
|
+
|
|
13
|
+
## Loại tài nguyên
|
|
14
|
+
|
|
15
|
+
| type | Đuôi | Giới hạn |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| `Images` | gif, jpeg, jpg, png | theo Web.config (CKImagesMaxSize*); ảnh quá khổ bị CKFinder thu nhỏ |
|
|
18
|
+
| `Files` | 7z, csv, doc, docx, gif, jpg, mp3, mp4, pdf, png, ppt, pptx, rar, txt, xls, xlsx, zip, … | 4 MB |
|
|
19
|
+
|
|
20
|
+
`mlis cdn info` cho giá trị thật từ server. `upload` tự chọn `Images` cho ảnh, `Files` cho phần còn lại; mặc định các lệnh khác là `Images`, đổi bằng `--type Files`.
|
|
21
|
+
|
|
22
|
+
## Lệnh
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
mlis cdn info
|
|
26
|
+
mlis cdn list [folder] [--type Files] [--recursive]
|
|
27
|
+
mlis cdn mkdir banner
|
|
28
|
+
mlis cdn upload .\banner.jpg --to banner [--name banner-2026.jpg]
|
|
29
|
+
mlis cdn url banner/banner-2026.jpg
|
|
30
|
+
mlis cdn rename banner/banner-2026.jpg banner-tet.jpg
|
|
31
|
+
mlis cdn download banner/banner-tet.jpg -o .\banner-tet.jpg
|
|
32
|
+
mlis cdn rm banner/banner-tet.jpg --confirm-delete
|
|
33
|
+
mlis cdn rmdir banner --confirm-delete [--recursive]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`upload` in `{"type","path","url"}`; dán `url` (tương đối, ví dụ `/Data/Folders/12/images/banner/banner-tet.jpg`) vào .ascx/.css. CKFinder có thể đổi tên file khi trùng (lệnh báo `# CKFinder renamed…`) — luôn dùng URL trả về.
|
|
37
|
+
|
|
38
|
+
Xoá là vĩnh viễn và có thể làm vỡ ảnh trên trang/bài viết đang dùng: chỉ xoá khi người dùng cho phép đúng file/thư mục đó.
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Control MLIS trong trang .ascx
|
|
2
|
+
|
|
3
|
+
Nguồn: `MLIS_UserControl.doc` (tài liệu gốc của MLIS), đối chiếu với thuộc tính thật trong `App_Code/PagesControl/*.vb`. Control dùng tiền tố `MLIS` (đã đăng ký trong Web.config; nhiều trang vẫn ghi thêm `<%@ Register TagPrefix="MLIS" Namespace="MLIS" %>` ở đầu, cũng được). Mọi control cần `runat="server"`. Giá trị trong ngoặc là mặc định.
|
|
4
|
+
|
|
5
|
+
## URL của site
|
|
6
|
+
|
|
7
|
+
- Trang chủ: `https://lhu.edu.vn/`
|
|
8
|
+
- Trang một thư mục: `https://lhu.edu.vn/40/Gioi-thieu.html` — 40 là ID thư mục (CatID).
|
|
9
|
+
- Trang đọc tin: `https://lhu.edu.vn/446/3387/Bai-hat-truyen-thong.html` — 446 là thư mục (và trang ascx hiển thị tin), 3387 là ID tin (NewsID).
|
|
10
|
+
- Trang theo route: `/more-list/…`, `/more-news/…`, `/more-related/…`, `/search/…` → nạp `ViewPage/<site>/_<tên>/default.ascx` (xem viewpage-structure).
|
|
11
|
+
|
|
12
|
+
## Thuộc tính chung
|
|
13
|
+
|
|
14
|
+
**CatID** — thư mục để lấy dữ liệu.
|
|
15
|
+
- `> 0`: đúng CategoryID đó.
|
|
16
|
+
- `0`: cấp lớn nhất (trang chủ, HomeID); `-1`: dưới trang chủ 1 cấp; `-X`: dưới trang chủ X cấp.
|
|
17
|
+
- `-100`: thư mục đang chọn (cấp nhỏ nhất); `-101`: thư mục đang chọn lên 1 cấp; `-10X`: lên X cấp.
|
|
18
|
+
|
|
19
|
+
**Location** (0) — số thứ tự vị trí: chọn các thư mục con của CatID được gán "vị trí" này trong trang quản trị; tin trong các thư mục con đó được lấy ra. `0` = lấy tin nằm ngay trong CatID (với CatMenu: lấy hết menu; với CatShow: chính thư mục đang chọn).
|
|
20
|
+
|
|
21
|
+
**Visibility** (0) — `0` luôn hiển thị; `1` ẩn khi đang đọc tin (có NewsID); `2` ẩn khi không đọc tin.
|
|
22
|
+
|
|
23
|
+
**Related** — dùng "Quan hệ thư mục": `0` cột "Tổng hợp tin" (bit 0), `1` "Cùng nội dung" (bit 1), `2` "Nội dung gần" (bit 2). NewsList/EventList mặc định `5` = không tổng hợp.
|
|
24
|
+
|
|
25
|
+
**PageLink** (0) — thư mục nằm trong link của tin:
|
|
26
|
+
- `0` ID thư mục chứa tin (`/201/50868/…`)
|
|
27
|
+
- `1` ID thư mục của chính danh sách (thư mục CatID/thư mục con theo Location đang được liệt kê — dùng khi tổng hợp tin từ thư mục khác) (`/21/50868/…`)
|
|
28
|
+
- `2` ID trang đang chọn (`/34/50868/…`)
|
|
29
|
+
- `3` ID trang chủ đang hiển thị (`/1/50868/…`)
|
|
30
|
+
|
|
31
|
+
**Skip** (0) — bỏ qua N tin đầu, lấy từ tin N+1.
|
|
32
|
+
|
|
33
|
+
**CatFormat** (`<a>{1}</a>`) — hiển thị thông tin thư mục; thẻ `<a>` tự thành link, bỏ `<a></a>` nếu không muốn link.
|
|
34
|
+
`{0}` Icon (class CIco) · `{1}` Tên thư mục · `{2}` Hình (class CPic) · `{3}` Mô tả · `{4}` Tên khác (Alias) · `{5}` Tài liệu HTML của thư mục · `{6}` Sub menu (thư mục con)
|
|
35
|
+
|
|
36
|
+
**NewsFormat** — định dạng một tin:
|
|
37
|
+
`{0}` Hình (NImg) · `{1}` Tiêu đề (NTitle) · `{2}` Ngày giờ (NTime) · `{3}` Tóm tắt (NIntro) · `{4}` Nội dung (NContent) · `{5}` Từ khoá (NKey) · `{6}` Nguồn/tác giả (NSource) · `{7}` Thời gian cập nhật (NUpdate) · `{8}` chèn class `Selected` cho bài đang xem · `{9}` Lượt xem (NCounter)
|
|
38
|
+
|
|
39
|
+
**DateTimeFormat** — chuỗi định dạng .NET (`dd/MM/yyyy HH:mm:ss`, `H:mm`, …).
|
|
40
|
+
**ViewMore** ("") — chữ của link "xem thêm" cuối danh sách (mở thư mục).
|
|
41
|
+
**HyperFormat** ("") — ưu tiên cao nhất, thay cho ListFormat/EventFormat: khuôn bao ngoài dùng được placeholder của CatFormat (`{1}` tên, `<a>` tự thành link…) và các khối `{{NewsItem}}`, `{{OtherItem}}`, `{{EventItem}}`, `{{ViewMore}}`. Ngoặc nhọn **đôi** là bắt buộc: chuỗi đi qua `String.Format` trước (một cặp ngoặc bị nuốt) rồi mới thay `{NewsItem}`… Một dấu `{` đơn lẻ không phải placeholder trong bất kỳ format nào cũng phải viết `{{` (CSS inline trong format: dùng class thay vì `style="…{…}"`).
|
|
42
|
+
**CssClass** — class CSS của khối.
|
|
43
|
+
|
|
44
|
+
Format có thể viết làm thuộc tính (nháy kép bên ngoài, nháy đơn bên trong) hoặc làm thẻ con khi dài:
|
|
45
|
+
|
|
46
|
+
```aspx
|
|
47
|
+
<MLIS:NewsList Location="7" PageLink="0" CatFormat="" NewsNumber="2" NewsOther="0" runat="server">
|
|
48
|
+
<NewsFormat>
|
|
49
|
+
<li class='row news'><div class='row'><div class='col-md-5'>{0}</div><div class="col-md-7">{1}{3}</div></div></li>
|
|
50
|
+
</NewsFormat>
|
|
51
|
+
<HyperFormat>
|
|
52
|
+
<ul class="">{{NewsItem}}</ul>
|
|
53
|
+
</HyperFormat>
|
|
54
|
+
</MLIS:NewsList>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Nạp trang / css
|
|
58
|
+
|
|
59
|
+
### LoadPage
|
|
60
|
+
Chèn một trang .ascx vào vị trí đặt control và/hoặc nạp mọi file `*.css` trong một thư mục vào `<head>`.
|
|
61
|
+
- `Src` ("") — đường dẫn .ascx, ví dụ `ViewPage/LHUENB4/_default/Header.ascx`.
|
|
62
|
+
- `CssFolder` ("") — thư mục chứa các .css cần nạp, ví dụ `ViewPage/LHUENB4/@HomePage` (nạp tất cả *.css trong đó, kèm `?version`).
|
|
63
|
+
|
|
64
|
+
```aspx
|
|
65
|
+
<MLIS:LoadPage CssFolder="ViewPage/LHUENB4/@HomePage" runat="server" />
|
|
66
|
+
<MLIS:LoadPage CssFolder="ViewPage/LHUENB4/_default" Src="ViewPage/LHUENB4/_default/Header.ascx" runat="server" />
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Menu và thư mục
|
|
70
|
+
|
|
71
|
+
### CatMenu — các thư mục dạng menu
|
|
72
|
+
`CatID` (-100: lấy thư mục con của nó) · `Location` (0 = hết menu) · `CatFormat` (`<a>{1}</a>`, không áp dụng cho sub menu) · `Visibility` · `CssClass` ("CatMenu"; mục đang chọn có class `Selected`) · `ItemClass` ("" class từng nhóm) · `ShowSubName` (false: hiện tên menu cấp 2) · `ShowSubIcon` (false) · `NewsNumber` (0: lấy thêm N tin làm menu; tin xếp từ thứ tự 20 trở đi).
|
|
73
|
+
|
|
74
|
+
```aspx
|
|
75
|
+
<MLIS:CatMenu ID="CatMenu1" CatID="0" Location="1" CssClass="navbar-nav navbar-left" ShowSubName="false" runat="server" />
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### CatRelated — thư mục có "Quan hệ thư mục" dạng menu
|
|
79
|
+
`CatID` (-100) · `Related` (1) · `CatFormat` · `Visibility` · `CssClass` ("CatMenu") · `ItemClass` · `ShowSubName` · `ShowSubIcon`.
|
|
80
|
+
|
|
81
|
+
### CatShow — thuộc tính của một thư mục
|
|
82
|
+
`CatID` (-100) · `Location` (0 = thư mục đang chọn) · `Visibility` · `CatFormat` (`<a>{1}</a>`) · `CssClass` ("CatShow").
|
|
83
|
+
|
|
84
|
+
```aspx
|
|
85
|
+
<MLIS:CatShow ID="CatShow1" CssClass="CatShow" CatFormat="<h2>{1}</h2>" runat="server" />
|
|
86
|
+
<MLIS:CatShow ID="CatShow2" CatFormat="<div>{2}</div><div class='CatHTML'>{5}</div>" runat="server" />
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### CatStream — chuỗi đường dẫn (breadcrumb)
|
|
90
|
+
`Level` (0: từ cấp N trở đi, 0 = gốc HomeID) · `PathText` (`<span>»</span>` ký hiệu phân cách) · `UseAlias` (false) · `CssClass` ("CatStream").
|
|
91
|
+
|
|
92
|
+
### IndexAZ — chỉ mục A–Z các thư mục
|
|
93
|
+
`VisualPath`.
|
|
94
|
+
|
|
95
|
+
## Danh sách tin
|
|
96
|
+
|
|
97
|
+
### NewsList — tin dạng liệt kê có tóm tắt
|
|
98
|
+
`CatID` (-100) · `Location` (0) · `Related` (5) · `PageLink` (0) · `Visibility` · `Skip` · `NewsNumber` (1 tin chính) · `NewsOther` (0 tin khác, chỉ tiêu đề) · `GetFirstNews` (false: lấy tin đầu để hiện chi tiết) · `DateTimeFormat` ("dd/MM/yyyy HH:mm:ss") · `ViewMore` · `HyperFormat` (`{{NewsItem}}`, `{{OtherItem}}`, `{{ViewMore}}`).
|
|
99
|
+
- `ListFormat` (`<div>{0}<ul>{1}</ul><ul>{2}</ul>{3}</div>`): `{0}` CatFormat · `{1}` danh sách NewsFormat · `{2}` danh sách OtherFormat · `{3}` link ViewMore
|
|
100
|
+
- `CatFormat` (`<h3 class=CName><a>{1}</a></h3>`)
|
|
101
|
+
- `NewsFormat` (`<li class="{8}">{0}{1}{2}{3}</li>`) — placeholder như NewsFormat chung
|
|
102
|
+
- `OtherFormat` (`<li>{1}{2}</li>`): `{0}` hình · `{1}` tiêu đề · `{2}` ngày giờ
|
|
103
|
+
|
|
104
|
+
```aspx
|
|
105
|
+
<MLIS:NewsList Location="22" PageLink="1" NewsNumber="1" NewsOther="6" Skip="0"
|
|
106
|
+
ListFormat="<div class='container NewsList'>{0}<div class='row'><div class='col-md-5'><ul class='row h-100'>{1}</ul></div><div class='col-md-7'><ul class='row h-100'>{2}</ul></div></div>{3}</div>"
|
|
107
|
+
CatFormat="<h2 class='row mb-4 mt-5 text-center'><a>{1}</a></h2>"
|
|
108
|
+
NewsFormat="<li class='mb-4'><div class='card shadow-sm h-100'>{0}<div class='card-body'><b>{1}</b><i>{3}</i></div></div></li>"
|
|
109
|
+
OtherFormat="<li class='col-md-4 mb-4'><div class='card shadow-sm h-100'>{0}<div class='card-body'>{1}</div></div></li>"
|
|
110
|
+
runat="server" />
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### NewsRelated — tin trong các thư mục có quan hệ với thư mục đang chọn
|
|
114
|
+
(không hiện tin của chính thư mục đó) — thuộc tính như NewsList, thêm `Merge` (false: để riêng từng thư mục; true: trộn hết) và `Related` mặc định 0. `ListFormat` mặc định `{0}<ul>{1}</ul><ul>{2}</ul>{3}`.
|
|
115
|
+
|
|
116
|
+
### NewsOther — tin liên quan tới bài đang đọc (chỉ hiện khi có NewsID)
|
|
117
|
+
- `ListFormat` (`<ul>{0}</ul><ul>{1}</ul><ul>{2}</ul>{3}`): `{0}` tin cũ hơn tin đang đọc · `{1}` tin cùng dòng sự kiện · `{2}` tin cùng từ khoá · `{3}` ViewMore
|
|
118
|
+
- `NewsFormat` (`<li>{0}{1}{2}</li>`): `{0}` hình · `{1}` tiêu đề · `{2}` ngày giờ
|
|
119
|
+
- `NewsOther` (5) · `NewsStream` (5) · `NewsKeyword` (5) · `Skip` · `PageLink` (0 và 1 như nhau: thư mục chứa tin) · `DateTimeFormat` · `ViewMore`.
|
|
120
|
+
|
|
121
|
+
### EventList — danh sách sự kiện
|
|
122
|
+
`CatID` (-100) · `Location` (0) · `Related` (5) · `Skip` · `Visibility` · `EventNumber` (5) · `DateTimeFormat` ("yyyy/MM/dd HH:mm ") · `DayFormat` ("MM/dd") · `ViewMore` · `CatFormat` (`<h3 class=CName><a>{1}</a></h3>`).
|
|
123
|
+
- `EventFormat` (`{0}{1}{2}`): `{0}` CatFormat · `{1}` danh sách EventItemFormat · `{2}` link các sự kiện tiếp theo
|
|
124
|
+
- `EventItemFormat` (`{1}{2}`): `{0}` hình (NImg) · `{1}` tiêu đề (NTitle) · `{2}` thời gian (DateTimeFormat)
|
|
125
|
+
- `HyperFormat`: `{{EventItem}}`, `{{ViewMore}}`
|
|
126
|
+
|
|
127
|
+
```aspx
|
|
128
|
+
<MLIS:EventList Location="11" Skip="2" DayFormat="''<i>d</i><u>T MM</u>" DateTimeFormat="H:mm" EventNumber="1" runat="server">
|
|
129
|
+
<EventItemFormat>{0}{1}{2}</EventItemFormat>
|
|
130
|
+
<HyperFormat>
|
|
131
|
+
<div class='d-md-none d-lg-block col-lg-4 mb-4'>{{EventItem}}</div>
|
|
132
|
+
</HyperFormat>
|
|
133
|
+
</MLIS:EventList>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Chi tiết
|
|
137
|
+
|
|
138
|
+
### NewsDetail — một tin dạng chi tiết (trang đọc tin `@ReadPage`)
|
|
139
|
+
`NewsID` (0: tin của URL; >0 chỉ định một tin) · `CatName` (`<h2>{0}</h2>`, `{0}` tên thư mục) · `NewsFormat` (`{1}{4}{5}{6}`, placeholder như NewsFormat chung) · `Author` ("{0}", ví dụ "Tác giả {0}", class NSource) · `HitCounter` ("{0}", ví dụ "Lượt xem {0}", class NCount) · `DateTimeFormat` ("dd/MM/yyyy HH:mm:ss").
|
|
140
|
+
|
|
141
|
+
## Khác
|
|
142
|
+
|
|
143
|
+
### Attr — dữ liệu hệ thống
|
|
144
|
+
`AttrFormat`: `{0}` số lần truy cập · `{1}` số người online · `{2}` tên miền · `{3}` HomeID · `{4}` số người đang xem HomeID.
|
|
145
|
+
|
|
146
|
+
```aspx
|
|
147
|
+
<i class="fa fa-bar-chart-o"></i> <MLIS:Attr ID="Attr4" AttrFormat="{1}" runat="server" />
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Search — ô tìm kiếm
|
|
151
|
+
`Text` ("" tiêu đề ô) · `CssClass` ("Search") · `icon` (HTML của nút, ví dụ `<i class='fa fa-search'></i>`).
|
|
152
|
+
|
|
153
|
+
### RSS — các kênh RSS 2.0
|
|
154
|
+
`UseAlias` (true: dùng tên khác; false: tên thư mục).
|
|
155
|
+
|
|
156
|
+
## Cấu hình thư mục liên quan (trong /admin, không sửa bằng CLI)
|
|
157
|
+
|
|
158
|
+
- **Liên kết**: để trống = link tới chính thư mục; `http://…` = link ngoài; `{codien.lhu.edu.vn}` = dùng tên miền đó cho thư mục.
|
|
159
|
+
- **Trang chủ (Home)**: 0 = chính nó là trang chủ; 1 = thư mục cha; 2 = ông nội; …
|
|
160
|
+
- **Kiểu thư mục (CatType)**: 0 ẩn · 1 trang chủ · 2 thư mục · 3 thông báo · 4 sự kiện · 5 giới thiệu · 6 thư viện ảnh · 7 liên kết · 8 tài liệu HTML.
|
|
161
|
+
- **PageStyle**: thư mục trang trong ViewPage dùng để hiển thị thư mục đó (xem viewpage-structure).
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Mẫu thiết kế thật trên lhu.edu.vn (site `LHUVNB4`)
|
|
2
|
+
|
|
3
|
+
Rút ra từ các trang đang chạy (đọc bằng `mlis pull`, 10/2026). Site `LHUVNB4` phục vụ lhu.edu.vn và nhiều tên miền con; `LHUENB4` là bản tiếng Anh. Trước khi làm trang mới, `mlis pull` trang cùng loại gần nhất và theo đúng khung của nó.
|
|
4
|
+
|
|
5
|
+
## Khung chung của mọi trang
|
|
6
|
+
|
|
7
|
+
```aspx
|
|
8
|
+
<%@ Register TagPrefix="MLIS" Namespace="MLIS" %>
|
|
9
|
+
<link href="/ViewPage/LHUVNB4/<TrangNay>/StyleMain.css" rel="stylesheet" type="text/css" /> <%-- hoặc LoadPage CssFolder --%>
|
|
10
|
+
<MLIS:LoadPage ID="LoadPage1" CssFolder="ViewPage/LHUVNB4/_default" Src="ViewPage/LHUVNB4/_default/Header.ascx" runat="server" />
|
|
11
|
+
<div id="TimeLineImage"></div> <%-- chừa chỗ dưới header cố định; trang nào cũng có --%>
|
|
12
|
+
|
|
13
|
+
<div class="container"> … nội dung … </div>
|
|
14
|
+
|
|
15
|
+
<br />
|
|
16
|
+
<MLIS:LoadPage ID="LoadPage2" Src="ViewPage/LHUVNB4/_default/Footer.ascx" runat="server" />
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- `_default/Header.ascx` + `_default/StyleDefault21.css`, `StyleHeaderFooter21.css` (nạp qua `CssFolder="ViewPage/LHUVNB4/_default"`). Header có: menu "Thông tin cho" (`<MLIS:CatMenu CatID="94">`), menu chính (`<MLIS:CatMenu CatID="0" Location="1">`), ô tìm kiếm (`<MLIS:Search icon="<i class='fa fa-search'></i>">` → trang `_Search` dùng Google Custom Search), logo có `alt`, chat widget `https://cdn.lhu.edu.vn/scripts/chat-widget.min.js` (ai.lhu.edu.vn).
|
|
20
|
+
- `_default` còn nhiều biến thể (`Header25.ascx`, `Header-ASU.ascx`, `Footer_2026.ascx`, `Footer_CareerFair.ascx`…): trang đặc biệt chọn header/footer riêng bằng `Src`.
|
|
21
|
+
- HeaderOfSite (`_assets/HeaderOfSite.ascx`) đã nạp: Source Sans Pro, Font Awesome **4.2 và 6.4** (`fa fa-…` và `fa-solid fa-…`), Bootstrap + MDB (`/assets/mdb/`), owlCarousel, Google Tag Manager; và tự khởi chạy owlCarousel cho mọi phần tử `.Carousel` có từ 2 con trở lên.
|
|
22
|
+
|
|
23
|
+
## Trang chủ (`@HomePage/default.ascx`)
|
|
24
|
+
|
|
25
|
+
- Banner: `<MLIS:CatShow ID="CatShow1" CatFormat="{5}" CssClass="Carousel" runat="server" />` — **nội dung banner là HTMLDoc của thư mục trang chủ**, nhân viên sửa trong /admin, không cần designer; class `Carousel` để owlCarousel chạy.
|
|
26
|
+
- Các khối tin: `NewsList` với **Location** (13, 10, 12, 7, 19…) — mỗi số là vị trí gán cho thư mục con của trang chủ. Kiểm tra số nào dùng cho thư mục nào: `mlis category ls <CatID trang chủ>`.
|
|
27
|
+
```aspx
|
|
28
|
+
<MLIS:NewsList Related="0" Location="13" PageLink="0" CatFormat="" NewsNumber="1" NewsOther="0" runat="server">
|
|
29
|
+
<NewsFormat><li><div class="NewsTitle">{0}{1}</div></li></NewsFormat>
|
|
30
|
+
<HyperFormat><ul class="News">{{NewsItem}}</ul></HyperFormat>
|
|
31
|
+
</MLIS:NewsList>
|
|
32
|
+
<%-- cùng nguồn, bỏ qua tin đã hiện: Skip="1" --%>
|
|
33
|
+
```
|
|
34
|
+
- Sự kiện: `<MLIS:EventList Location="11" Skip="0" DayFormat="''<i>d</i><u>T MM</u>" …>` lặp 3 lần với Skip 0/1/2 để chia cột.
|
|
35
|
+
- Khối liên kết cuối trang: `<MLIS:CatMenu CatID="0" Location="20" CatFormat="{6}" CssClass="CatMenu row" ItemClass="col-md col-sm-6" ShowSubName="true">` — mỗi thư mục Location 20 là một cột, `{6}` in menu con.
|
|
36
|
+
- Tiêu đề khối dùng `<div class="TitleGroup">` + `<div class="SubTitle">` (CSS `@HomePage/StyleMain.css`), nút `<button class="Nut">`. **Trang chủ hiện không có `<h1>`** — trang mới nên có một h1 (có thể ẩn bằng CSS) và dùng h2 cho TitleGroup.
|
|
37
|
+
- Hình của trang chủ nằm trong `@HomePage/_images/` (và bản cũ `@HomePage/Image/`); `_default.ascx` trong thư mục là bản lưu cũ (tên có `_` nên không ai chọn nhầm).
|
|
38
|
+
|
|
39
|
+
## Trang thư mục
|
|
40
|
+
|
|
41
|
+
**Dải tiêu đề + breadcrumb** (DefaultPage2Column, DefaultPageCatalog):
|
|
42
|
+
```aspx
|
|
43
|
+
<div class="HeaderSubContent"><div class="container"><div class="HeaderSub">
|
|
44
|
+
<MLIS:CatShow ID="CatShow1" CatFormat="<h2>{1}</h2>" runat="server" />
|
|
45
|
+
<MLIS:CatStream ID="CatStream01" Level="0" PathText="<span> » </span>" runat="server" />
|
|
46
|
+
</div></div></div>
|
|
47
|
+
```
|
|
48
|
+
Hiện dùng `<h2>` cho tên thư mục và trang không có h1 — trang mới nên dùng `CatFormat="<h1>{1}</h1>"` (giữ class/CSS như cũ).
|
|
49
|
+
|
|
50
|
+
- **DefaultPage2Column** — mỗi thư mục con (Location 2) một thẻ card liệt kê 5 tin:
|
|
51
|
+
`<MLIS:NewsList Location="2" Visibility="1" NewsNumber="0" NewsOther="5" ViewMore="Xem thêm" ListFormat="<div class='col-sm-6 d-flex'><div class='card padding mb-5'><div class='text-uppercase CatName'>{0}</div><ul class='more-news'>{2}</ul><div class='view-more'><i class='fa fa-chevron-circle-right'></i>{3}</div></div></div>" OtherFormat="<li>{1}</li>"/>`
|
|
52
|
+
- **DefaultPageCatalog** — cột trái danh sách tiêu đề (tối đa 30) của thư mục, cột phải chi tiết tin đầu tiên: `NewsList … GetFirstNews="true" NewsFormat="<li class='{8}'>{1}</li>"` + `<MLIS:NewsDetail NewsFormat="<div class='NewsDetail'>{1}{4}</div>" CatName="" />`. `{8}` tô tin đang xem. Menu trái thu gọn trên mobile bằng `navbar-collapse`.
|
|
53
|
+
- **DefaultPageCat** — mô tả thư mục `{3}`, danh sách thư mục con, cột phải hình `{2}` + HTMLDoc `{5}`. ⚠ Bản đang chạy còn trỏ site cũ `ViewPage/LHUVN/...` (không tồn tại → mất CSS, header, footer). `mlis check LHUVNB4/DefaultPageCat` báo lỗi này.
|
|
54
|
+
|
|
55
|
+
## Trang đọc tin (`@ReadPage/Default.ascx`)
|
|
56
|
+
|
|
57
|
+
```aspx
|
|
58
|
+
<div class="container"><div class="row">
|
|
59
|
+
<div class="col-md-9">
|
|
60
|
+
<MLIS:NewsDetail ID="NewsDetail1" NewsFormat="<div class='NewsDetail'>{1}{4}{6}{5}</div>"
|
|
61
|
+
DateTimeFormat="'Lạc Hồng', dd/MM/yyyy - HH:mm:ss" HitCounter="Lượt xem {0}" runat="server" />
|
|
62
|
+
<MLIS:NewsOther ID="NewsOther1" PageLink="0" NewsOther="3" NewsKeyword="0" NewsStream="0" ViewMore="Tin khác"
|
|
63
|
+
ListFormat="<ul class='row NewsList'>{0}</ul>…<div class='view-more'>…{3}</div>" NewsFormat="<li class='col-md-4'>{0}{1}</li>" runat="server"/>
|
|
64
|
+
</div>
|
|
65
|
+
<div class="col-md-3"> <%-- cột phải: tin của thư mục cố định --%>
|
|
66
|
+
<MLIS:NewsList PageLink="1" CatID="118" NewsNumber="5" … NewsFormat="<li class='col-md-12'>{0}{1}</li>" runat="server"/>
|
|
67
|
+
<MLIS:NewsList PageLink="1" CatID="21" NewsNumber="5" … runat="server"/>
|
|
68
|
+
</div>
|
|
69
|
+
</div></div>
|
|
70
|
+
```
|
|
71
|
+
`{1}` của NewsDetail là `<h1 class=NTitle>` — h1 duy nhất của trang. Biến thể: `@ReadPageEvent`, `@ReadPageHomePage`, `@ReadPageNNTH` (gán qua PageRead).
|
|
72
|
+
|
|
73
|
+
## Trang nội dung tĩnh / landing
|
|
74
|
+
|
|
75
|
+
- **@LandingPage**: toàn bộ nội dung là HTMLDoc của thư mục: `<div class="container NewsDetail"><div class="NContent"><MLIS:CatShow CatFormat="{5}" runat="server" /></div></div>` — nhân viên soạn trong /admin, designer chỉ làm khung + CSS. Nên thêm h1 (`CatShow CatFormat="<h1>{1}</h1>"`) phía trên.
|
|
76
|
+
- **GioiThieu**: trang viết tay dài (card, ảnh trong `GioiThieu/_Images/`, ảnh 360 ở `/Data/img360/...`) kèm `NewsList Location="25"` cho danh sách bài. ⚠ Nhiều ảnh `alt="Card image cap"`/`"smaple image"` hoặc thiếu alt — trang mới phải mô tả ảnh thật.
|
|
77
|
+
- **Trang theo route** `_TuyenSinhDaiHoc` (URL `/TuyenSinhDaiHoc`): landing tuyển sinh tự chứa (CSS riêng, JS bundle), dùng `CatShow CatID="0" CatFormat="{4}"` (tên khác của trang chủ tên miền) và `CatFormat="{5}"`. ⚠ Bản đang chạy nạp CSS từ `ViewPage/LHUVNB4/TuyenSinhDaiHoc/` (thiếu dấu `_`) — `mlis check` báo.
|
|
78
|
+
|
|
79
|
+
## Trang hệ thống
|
|
80
|
+
|
|
81
|
+
- `_more-List`: `NewsList PageLink="1" NewsNumber="100"` — danh sách "xem thêm" phân trang theo `Skip` trên URL.
|
|
82
|
+
- `_Search`: Google CSE (`cse.google.com`, `queryParameterName="q"`) + `<form runat="server">` (vì vậy trang không được cache).
|
|
83
|
+
|
|
84
|
+
## Lớp CSS hay dùng (StyleDefault21.css / StyleMain.css)
|
|
85
|
+
|
|
86
|
+
`#TimeLineImage`, `.mobile-fluid`, `.Carousel`, `.TitleGroup`, `.SubTitle`, `.Nut`, `.News`, `.News2`, `.boxNews`, `.NewsList`, `.NewsTitleList`, `.more-news`, `.view-more`, `.HeaderSubContent`, `.HeaderSub`, `.CatName`, `.NewsDetail`, `.NContent`, `.btn-action`, `.no-hover`, cùng các class do control sinh (`NImg`, `NTitle`, `NTime`… — xem `rendered-html`). Bootstrap: `container`, `row`, `col-md-*`, `col-lg-*`, `d-flex`, `py-5`, `card`.
|
|
87
|
+
|
|
88
|
+
## Lỗi thường gặp đã thấy trên site (tránh lặp lại)
|
|
89
|
+
|
|
90
|
+
1. Trỏ site cũ `ViewPage/LHUVN/...` sau khi đổi tên site → mất CSS/header không báo lỗi. Luôn `mlis check` trước khi push.
|
|
91
|
+
2. Chép thư mục trang nhưng quên đổi đường dẫn `ViewPage/<thư mục>` bên trong (ví dụ `TuyenSinhDaiHoc` ↔ `_TuyenSinhDaiHoc`).
|
|
92
|
+
3. Alt giữ chỗ từ mẫu Bootstrap; ảnh không alt.
|
|
93
|
+
4. Không có h1 / dùng h2 cho tên trang.
|
|
94
|
+
5. File thừa trong thư mục trang (`Default - Copy.ascx`, `_BK…`): vô hại nhưng gây nhầm; bản lưu nên để trong `_bk` hoặc dùng `mlis history`.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Nội dung động: bài viết (news) thay cho chữ cứng trong .ascx
|
|
2
|
+
|
|
3
|
+
Trang .ascx là **khuôn**. Chữ, hình, danh sách hay đổi (giới thiệu, thông báo, số liệu, khối "Vì sao chọn…", slider, liên hệ…) nên nằm trong **bài viết** để người quản trị sửa ngay trong /admin → Bài viết (hoặc AI sửa bằng `mlis news`), không phải sửa mã và đẩy lại ViewPage.
|
|
4
|
+
|
|
5
|
+
## Ba cách đưa nội dung vào trang
|
|
6
|
+
|
|
7
|
+
| Cần | Viết trong .ascx | Sửa nội dung ở đâu |
|
|
8
|
+
|---|---|---|
|
|
9
|
+
| Một khối nội dung cố định (đoạn giới thiệu, bảng học phí, hướng dẫn) | `<MLIS:NewsDetail NewsID="3387" NewsFormat="{4}" CatName="" runat="server" />` — `{4}` là nội dung HTML của bài; `{1}` tiêu đề, `{0}` hình, `{3}` tóm tắt | bài 3387: `mlis news pull 3387` |
|
|
10
|
+
| Một nhóm khối giống nhau (thẻ, slider, lý do, đối tác, câu hỏi thường gặp) | `<MLIS:NewsList CatID="512" NewsNumber="6" NewsFormat="<div class='card'>{0}<h3>{1}</h3>{3}</div>" runat="server" />` — mỗi bài là một khối, thứ tự theo thứ tự sắp trong /admin | thêm/sửa/ẩn bài trong thư mục 512: `mlis news ls 512` |
|
|
11
|
+
| Mô tả/HTML gắn với chính thư mục | `<MLIS:CatShow CatFormat="{3}">` (mô tả), `{5}` (Tài liệu HTML của thư mục) | /admin → Thư mục → Tài liệu HTML (chưa có lệnh mlis) |
|
|
12
|
+
|
|
13
|
+
Placeholder đầy đủ: `mlis skill ref controls` (NewsFormat chung: `{0}` hình · `{1}` tiêu đề · `{2}` ngày · `{3}` tóm tắt · `{4}` nội dung · `{5}` từ khoá · `{6}` nguồn). Thư mục dùng làm kho nội dung cho trang thường để **không** cho hiện trong menu/RSS (cấu hình trong /admin).
|
|
14
|
+
|
|
15
|
+
Khi thiết kế trang mới có nội dung động: đề xuất với người dùng thư mục/bài sẽ chứa nội dung (CatID/NewsID phải có sẵn hoặc tạo trong /admin — CLI không tạo thư mục), viết khuôn bằng NewsList/NewsDetail, rồi đưa nội dung vào bài bằng `mlis news`. `mlis render` dùng dữ liệu mẫu nên khuôn xem được cả khi bài chưa có.
|
|
16
|
+
|
|
17
|
+
## Tìm bài đang cấp nội dung cho một trang
|
|
18
|
+
|
|
19
|
+
1. Đọc .ascx (`mlis pull <thư mục>`), tìm `CatID="…"`/`NewsID="…"` trong `<MLIS:NewsList|NewsDetail|NewsRelated|EventList>`. `CatID="-100"` = thư mục đang mở, `0` = trang chủ tên miền; `Location="n"` = các thư mục con có Location n (`mlis category ls <CatID>`).
|
|
20
|
+
2. `mlis news ls <CatID> [--search chữ]` → NewsID, tiêu đề, từ khoá, người tạo/sửa (giống danh sách trong /admin: tài khoản chỉ có quyền đóng góp thì chỉ thấy bài của mình).
|
|
21
|
+
3. Có URL thì `mlis page <url>`: trang đọc tin `/<CatID>/<NewsID>/<tên>.html` cho biết NewsID và template.
|
|
22
|
+
|
|
23
|
+
## Lệnh
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
mlis news ls 512 [--search "học phí"] [--from 2026/01/01] [--to 2026/12/31] [--skip 20] [--limit 50] [--trash]
|
|
27
|
+
mlis news show 3387 # in bài (không ghi file); --json: mọi cột
|
|
28
|
+
mlis news pull 3387 3388 # → <workspace>/_news/3387.html
|
|
29
|
+
mlis news diff 3387 # local ↔ server
|
|
30
|
+
mlis news push 3387 [--dry-run] # lưu; exit 3 nếu bài đã bị sửa trên server sau lần pull
|
|
31
|
+
mlis news new 512 --title "Học bổng 2027" # tạo _news/new-512-<giờ>.html (newsId 0); push mới tạo bài
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
File bài: header là chú thích HTML, dưới là nội dung HTML của bài:
|
|
35
|
+
```html
|
|
36
|
+
<!--mlis-news
|
|
37
|
+
newsId: 3387
|
|
38
|
+
catId: 512
|
|
39
|
+
title: Học phí năm học 2026-2027
|
|
40
|
+
intro: Tóm tắt một dòng
|
|
41
|
+
images: /Data/News/512/images/hoc-phi.jpg
|
|
42
|
+
keyword: học phí, tuyển sinh
|
|
43
|
+
source: Phòng Tài chính
|
|
44
|
+
# news trong thư mục Thông tin tuyển sinh ← dòng # chỉ để đọc
|
|
45
|
+
-->
|
|
46
|
+
<p>Nội dung…</p>
|
|
47
|
+
```
|
|
48
|
+
- Giá trị nhiều dòng hoặc có khoảng trắng đầu/cuối, bắt đầu bằng `"` → viết dạng chuỗi JSON (`intro: "dòng 1\ndòng 2"`).
|
|
49
|
+
- **Sự kiện** (thư mục kiểu sự kiện): có `orderTime: yyyy-MM-dd HH:mm` (thời gian diễn ra), không có `intro`/`keyword`.
|
|
50
|
+
- **Thư viện ảnh**: chỉ đọc; sửa trong /admin.
|
|
51
|
+
- `catId` chỉ có ý nghĩa khi tạo bài mới; bài đã có giữ thư mục của nó (chuyển thư mục: kéo bài trong /admin → Bài viết).
|
|
52
|
+
|
|
53
|
+
## Quy tắc của server (giống trang sửa bài trong /admin — App_Code\NewsEditor.vb)
|
|
54
|
+
|
|
55
|
+
- Tiêu đề bắt buộc, ≤ 150 ký tự, không HTML (`<` `>` bị đổi thành `<` `>`), khoảng trắng thừa bị gộp.
|
|
56
|
+
- Nội dung ≥ 30 ký tự, ≤ 50.000 (sự kiện 500.000); không nhúng ảnh base64 (`data:image`) — upload ảnh trước bằng `mlis cdn upload --mode news --cat <CatID>` rồi dùng URL `/Data/News/<CatID>/…`.
|
|
57
|
+
- Từ khoá được chuẩn hoá thành `a, b, c`. Sau push, file được ghi lại đúng như server lưu (thông báo "server normalised").
|
|
58
|
+
- Quyền: chỉ bài trong thư mục tài khoản có quyền; không có quyền → lỗi 404/403 từ server.
|
|
59
|
+
|
|
60
|
+
## An toàn
|
|
61
|
+
|
|
62
|
+
- Bài viết hiển thị **ngay** trên site thật (sau tối đa 60 giây cache). Chỉ sửa bài người dùng yêu cầu; đọc `mlis news diff` trước khi push và báo người dùng nội dung thay đổi.
|
|
63
|
+
- Exit 3 = bài đã bị sửa trên web sau lần pull: chạy `mlis news diff`, hỏi người dùng giữ bản nào — `mlis news pull <id> --force` (lấy bản server, bản local vào `_history/_news/`) hoặc `mlis news push <id> --force` (ghi đè, bản server vào `_history/_news/`).
|
|
64
|
+
- Không có lệnh xoá/ẩn bài: việc đó làm trong /admin.
|
|
65
|
+
- Nội dung bài là HTML do người biên tập soạn bằng CKEditor: giữ cấu trúc đơn giản (p, h2/h3, ul/ol, table, img có alt, a), không đưa `<script>`, `<style>` hay class bố cục vào bài — bố cục thuộc về .ascx/.css.
|