# mm_os框架模板引擎完整语法手册

## 0. 数据来源说明

模板中可以使用的数据主要来自两个对象：

**`viewBag` — 视图数据包**
由控制器（index.js/main.js）通过 `db.tpl.viewBag` 注入。
常用字段：
- `viewBag.lang` — 多语言文本
- `viewBag.query` — URL查询参数
- `viewBag.current_theme` — 当前主题名称
- `viewBag.theme_color` — 当前主题颜色方案
- `viewBag.sys_lang` / `viewBag.sys_language` — 系统语言
- `viewBag.href` — 当前页面完整路径
- `viewBag.seo` — SEO信息
- `viewBag.nav` — 当前应用导航菜单
- `viewBag.path` — 当前请求路径

**`globalBag` — 全局数据包**
由系统在启动时从数据库加载。
常用字段：
- `globalBag.conf` — 系统配置
- `globalBag.nav` — 导航树
- `globalBag.ad` — 广告列表
- `globalBag.seo` — SEO配置列表
- `globalBag.list_lang` — 支持的语言列表
- `globalBag.langs` — 语言包数据

## 一、变量输出

`@` 符号：`${@o.title}` 输出原始HTML（不转义），不加 `@` 时HTML标签被转义。

| 语法 | 说明 |
|:-----|:-----|
| `${viewBag.lang.xxx}` | 输出多语言文本 |
| `${viewBag.query.xxx}` | 输出URL查询参数 |
| `${viewBag.current_theme}` | 当前主题名称 |
| `${viewBag.theme_color}` | 当前主题颜色 |
| `${viewBag.href}` | 当前页面路径 |
| `${ o.url === viewBag.href ? 'active' : '' }` | 三目运算符 |
| `${ viewBag.lang["nav_" + o.name] \|\| o.title }` | 逻辑或运算 |
| `${nav.page_now - 1}` | 表达式运算 |

## 二、模板函数调用

```html
${hookAction('seo', 'title')}
${hookAction('web', 'favicon')}
${hookAction('web', 'logo')}
${@hookAction('style', 'head')}
${@hookAction('script', 'head')}
${hookFilter("params", "首页轮播")}
${@view('./xxx.html', hookFilter("params", "xxx"))}
```

## 三、视图嵌入

```html
${@view('./common/head.html')}
${@view('./common/header.html')}
${@view('./common/footer.html')}
${@view('./components/swiper.html', hookFilter("params", "首页轮播"))}
```

## 四、循环语法

花括号内外各一个空格：

| 正确 | 错误 |
|:-----|:-----|
| `<!--{ if(条件) }-->` | `<!--{if(条件)}-->` |
| `<!--{ else }-->` | `<!--{else}-->` |
| `<!--{ loop data o i }-->` | `<!--{loop data o i}-->` |
| `<!--{ /loop }-->` | `<!--{/loop}-->` |

```html
<!--{ loop globalBag.nav o idx }-->
  <a href="${o.url}">${o.title}</a>
<!--{ /loop }-->
```

## 五、条件语法

```html
<!--{ if(o.app == 'home' && o.position == 'main') }-->
<!--{ if(o.sub && o.sub.length) }-->
  <ul class="dropdown">...</ul>
<!--{ else }-->
  <span>无子菜单</span>
<!--{ /if }-->
```

## 六、挂件插入点

`<!-- #main_top -->` `<!-- #main -->` `<!-- #aside -->` `<!-- #header -->` `<!-- #footer -->` `<!-- #nav -->`

## 七、CSS框架

`mm_warp` `mm_container` `mm_row` `mm_col` `mm_card` `mm_view` `mm_btn`
`btn-primary` `mm_list` `mm_item` `mm_form` `mm_table` `mm_modal`
`hide_phone` `hide_pad` `flex_pad` `fl` `fr` `fn` `mc` `pa` `ma`

CSS变量：`var(--font_primary)` `var(--font_main)` `var(--border_base)` `var(--bg_main)` `var(--radius_small)`

## 八、Vue.js集成

`v-model` `@click` `@blur` `@keypress.enter` `v-if` `v-for` `v-show` `v-html`
`:class` `:src` `{{ o.name }}` `{{ $to_time(o.time) }}`

mm_vue扩展：`this.$post` `this.$get` `this.$toast` `this.$confirm` `$.db.get` `$.db.set`

## 九、路径规范

- 视图嵌入：`./xxx/xxx.html`（相对于当前模板目录）
- 静态资源：`/js/xxx.js`、`/css/xxx.css`、`/img/xxx.png`
- 主题资源：`/template/{主题名}/style/{颜色}/css/theme.css`

## 十、标准请求流程

```
用户请求 → Event路由分发 → Plugin业务处理 → 控制器调用 db.tpl.view() → 模板引擎注入数据 → HTML响应
```
