skip to content
仙人掌主题

使用Cursor + supabase + ChatGPT o3开发导航站后台(下)

/ 28 min read

本期我们来开发一个简单的导航站的管理后台功能,你将会完成一个具有登录注册、管理员设置、数据增/删/改/查的管理后台。同时你将会学习到以下技巧和技术栈:

1. 如何基于ChatGPT的o3,来开发一个详细的需求文档

2. 如何让Cursor自动生成默认的Cursor Rules,并且自己创建自定义Rules来限制开发要求

3. 如何创建/docs/*.md,来存放文档让Cursor更好的开发

4. 如何基于supabase来开发后台,并且实现数据库的增/删/改/查功能

注意:本篇教程是《使用v0 + supabase + Cursor创建一个导航站(上)》的下半部分,建议先着完上部分的教程内容再来着这一期的视频。

1. 生成项目文档

1.1 给到AI对应的提示词

• 让ChatGPT的o3,加上画布模式来生成我们的需求文档

现在有一个AI导航站,是基于supabase的,现在这个导航站有3个表:
1. AI工具表,定义如下:
```sql
create table
public.ai_tools (
id uuid not null default uuid_generate_v4 (),
name character varying(200) not null,
slug character varying(200) not null,
description text not null,
full_description text null,
website_url character varying(255) null,
image_url character varying(255) null,
category_id uuid not null,
created_at timestamp without time zone not null default now(),
updated_at timestamp without time zone not null default now(),
user_id uuid null,
is_approved boolean not null default true,
logo_url text null,
type text null,
constraint ai_tools_pkey primary key (id),
constraint ai_tools_slug_key unique (slug),
constraint ai_tools_category_id_fkey foreign key (category_id) references categories (id),
constraint ai_tools_user_id_fkey foreign key (user_id) references users (id)
) tablespace pg_default;
create index if not exists idx_ai_tools_category_id on public.ai_tools using btree (category_id) tablespace pg_default;
create index if not exists idx_ai_tools_user_id on public.ai_tools using btree (user_id) tablespace pg_default;
```
2. AI工具分类表,定义如下:
```sql
create table
public.categories (
id uuid not null default uuid_generate_v4 (),
name character varying(100) not null,
icon character varying(255) not null,
created_at timestamp without time zone not null default now(),
constraint categories_pkey primary key (id)
) tablespace pg_default;
```
3. 公户提交的AI工具记录表,定义如下:
```sql
create table
public.tool_submissions (
id uuid not null default uuid_generate_v4 (),
name character varying(200) not null,
description text not null,
full_description text null,
website_url character varying(255) not null,
image_url character varying(255) null,
category_id uuid not null,
user_id uuid not null,
status character varying(20) not null default 'pending'::character varying,
admin_comments text null,
created_at timestamp without time zone not null default now(),
updated_at timestamp without time zone not null default now(),
processed_at timestamp without time zone null,
ai_tool_id uuid null,
slug text not null,
constraint tool_submissions_pkey primary key (id),
constraint tool_submissions_category_id_fkey foreign key (category_id) references categories (id),
constraint tool_submissions_user_id_fkey foreign key (user_id) references users (id),
constraint tool_submissions_ai_tool_id_fkey foreign key (ai_tool_id) references ai_tools (id)
) tablespace pg_default;
create index if not exists idx_tool_submissions_user_id on public.tool_submissions using btree (user_id) tablespace pg_default;
create index if not exists idx_tool_submissions_status on public.tool_submissions using btree (status) tablespace pg_default;
create index if not exists idx_tool_submissions_category_id on public.tool_submissions using btree (category_id) tablespace pg_default;
create index if not exists idx_tool_submissions_created_at on public.tool_submissions using btree (created_at) tablespace pg_default;
```
我先给的导航站创建一个后台,有3个侧边栏:
1. 概览:
- 顶部右上角具有添加按钮,支持用户添加AI工具。点击后从右侧弹出Drawer,Drawer内有表单支持用户添加AI工具到ai_tools这张表中。
- 顶部显示4个卡片,包括:AI工具数量(获取ai_tools的数据量),AI分类数量(获取categories的数量),以及当日用户提交(获取今天在ai_tool_submissions中的数据)、未审核的用户提交(获取ai_tool_submissions 中未审核的数据)
- 底部显示所有的AI工具,并且支持查看和编辑功能(获取ai_tools的数据量)
2. 审核:查看当前未审核的用户提交(获取 ai_tool_submissions 中未审核的数据),管理员能够进行审核,将ai_tool_submissions中的status修改成为success。并且审核通过后,将数据添加到ai_tools这张表中
3. 用户管理:管理员能够设置用户是否是管理员,只有是管理员的用户才能登陆进入该后台。否则不允许进入该后台,请你信创建一个admin_users的表来实现这个逻辑。
请你根据我的上述需求,给到我一个完整的需求文档

1.2 AI生成的需求文档

下面是ChatGPT 03帮我生成的需求文档,我们可以基于ChatGPT的画布模式优化这个需求文档。删除我们觉得没有必要,或者AI过度设计的内容部分。然后这个需求文档中帮我们新增了 admin_users这一张用户保存管理员用户的表,但是并没有给我们RLS的策略,所以这边我们来让AI帮我们新增一下,输入以下提示词:

•提示词:

请你帮我给admin_users这张表添加RLS开启和相关的策略约束

什么是RLS策略?

我们在supabase的课程中有详细的讲到RLS策略,这里我们在来回顾一下。RLS 的作用是:

1. 精细控制访问权限:决定哪些用户可以着到、添加、修改或删除哪些数据行

2. 自动过滤数据:用户查询时,只会看到他们有权限看到的数据

3. 安全在数据库层实现:不依赖前端代码,防止安全漏洞

接下来是我完整的需求文档部分,你可以直接复制粘贴使用:

# AI 导航站后台需求文档
---
## 1. 项目概述
本后台系统用于管理 **AI 导航站** 的核心数据(AI 工具、分类、用户提交记录)并支撑运营人员进行内容审核及用户权限管理。
## 2. 目标与范围
* **目标**:
1. 提供直观可视化的运营数据概览。
2. 支持运营人员在后台快速添加 / 编辑 AI 工具。
3. 支持审核用户提交的 AI 工具申请并一键入库。
4. 支持为用户分配或撤销管理员权限,保障后台安全访问。
* **范围**:仅涵盖后台管理端(前端 Next.js + Supabase *Server Role* API),不包括导航站前台页面。
## 3. 角色与权限
| 角色 | 说明 | 权限 |
| -------- | ----------------------- | -------------------------- |
| **管理员** | 通过 `admin_users` 表认定的用户 | 可访问后台全部功能模块;可设定其他用户是否为管理员。 |
| **普通用户** | 默认注册用户 | 仅能通过前台发起工具提交;无法访问后台管理端。 |
## 4. 数据库表概览(已有)
* **ai\_tools** – 已上架工具主表。
* **categories** – 工具分类表。
* **tool\_submissions** – 用户提交记录表。
### 4.1 新增:`admin_users`
```sql
create table public.admin_users (
user_id uuid primary key references auth.users(id) on delete cascade,
created_at timestamp without time zone default now()
);
-- 启用 Row‑Level Security
alter table public.admin_users enable row level security;
-- 1) 仅允许已存在的管理员查看记录(判断当前 uid 是否已在表内)
create policy "Admins can read admin_users"
on public.admin_users
for select
using (exists (select 1 from public.admin_users au where au.user_id = auth.uid()));
-- 2) 仅允许已存在的管理员添加新管理员
create policy "Admins can add admins"
on public.admin_users
for insert
with check (exists (select 1 from public.admin_users au where au.user_id = auth.uid()));
-- 3) 仅允许已存在的管理员移除管理员
create policy "Admins can remove admins"
on public.admin_users
for delete
using (exists (select 1 from public.admin_users au where au.user_id = auth.uid()));
```
> **约定**:判定管理员身份时,仅检查当前登录用户 `uid` 是否存在于 `admin_users` 表。
###
## 5. 功能模块
### 5.1 登录与权限校验
* 所有 `/api/admin/**` 路由及后台页面使用中间件校验 `auth.uid()` 是否存在于 `admin_users`。
* 无权限访问时重定向至前台首页或展示 403 页面。
### 5.2 概览(Sidebar #1)
| 功能 | 说明 |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
| **顶部操作栏** | 右上角「添加 AI 工具」按钮 -> 右侧 Drawer 表单;表单字段:名称、Slug、描述、分类、网站链接、Logo/图片等。 |
| **统计卡片 ×4** | 1) AI 工具总数(`ai_tools`) 2) 分类总数(`categories`) 3) 当日提交数(`tool_submissions` 当天) 4) 未审核提交数(`tool_submissions.status = 'pending'`) |
| **工具列表 DataTable** | 列字段:名称、分类、类型、创建时间、状态;支持搜索、分页、查看、编辑。 |
| **查看/编辑 Drawer** | 与新增表单复用;提交后更新 `ai_tools` 表并刷新列表。 |
### 5.3 审核(Sidebar #2)
| 功能 | 说明 |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **待审核列表** | 默认筛选 `tool_submissions.status = 'pending'`;字段:名称、用户、分类、提交时间。 |
| **审核操作** | - **通过**:事务内执行 1) 插入 `ai_tools`(字段映射) 2) 将 `tool_submissions.status` 更新为 `'success'`, `ai_tool_id` 关联。 \|\n- **拒绝**:更新 `status = 'rejected'` 并填写 `admin_comments`。 |
| **批量操作** | 复选框 + 批量通过 / 拒绝。 |
### 5.4 用户管理(Sidebar #3)
| 功能 | 说明 |
| -------- | ------------------------------------- |
| **用户列表** | 来源 `auth.users`;列:Email、注册时间、是否管理员。 |
| **权限切换** | 开关按钮:写入 / 删除 `admin_users`。操作成功后即刻生效。 |
## 6. UI / 交互规范
* **框架**:Next.js 14, Tailwind CSS, shadcn/ui;暗色 & 亮色自适应。
* **布局**:固定侧边栏(宽 240px)+ 顶部导航栏(含用户头像下拉)。
* **Drawer**:宽度 480px,从右滑入;ESC 或点击遮罩关闭,保留未提交的表单状态。
* **DataTable**:基于 shadcn `DataTable` 组件,支持列排序、搜索、分页(50 / 页)。
* **表单校验**:前端使用 `zod` + React Hook Form;后端再次校验必填字段非空。
## 7. API 设计(仅展示核心)
| 方法 | 路径 | 功能 | 备注 | | |
| ---- | ------------------------------------- | ------------ | -------------------------- | ------- | ---------- |
| GET | `/api/admin/overview/stats` | 获取四张统计卡的数据 | | | |
| GET | `/api/admin/ai-tools` | 分页获取 AI 工具列表 | `?page=&pageSize=&search=` | | |
| POST | `/api/admin/ai-tools` | 新增 AI 工具 | body: 工具信息 | | |
| PUT | `/api/admin/ai-tools/{id}` | 更新 AI 工具 | | | |
| GET | `/api/admin/submissions` | 获取提交列表 | \`?status=pending | success | rejected\` |
| POST | `/api/admin/submissions/{id}/approve` | 审核通过 & 入库 | | | |
| POST | `/api/admin/submissions/{id}/reject` | 审核拒绝 | body: `admin_comments` | | |
| GET | `/api/admin/users` | 获取用户列表 | | | |
| POST | `/api/admin/users/{id}/toggle-admin` | 切换管理员状态 | | | |
> **注意**:所有 `/api/admin/**` 路由需在 Middleware 中验证 `admin_users`,请求上下文使用 Supabase **Service Role** Key 执行以绕过 RLS。
>
> ##

2. 初始化项目

2.1 安装模板

2.1.1 使用next.js + supabase的官方模板

访问next.js的官网,在Templates中搜索supabase提供的官方模板。我们使用这套模板开发我们的这个管理后台项目。

安装这套模板也非常简单,我们在我们的课程中也多次使用到了:

• 如果你使用的npm,直接在命令中输入:

npx create-next-app --example with-supabase dirs-admin

• 如果你和我一样,用的pnpm,输入这个命令:

pnpm create next-app --example with-supabase dirs-admin

dirs-admin 是项目文件夹的名称,你可以修改成为自己想命名的名称。

如果你下载遇到了网络问题,也可以直接使用我们提供的这个代码初始文件包:

dirs-admin.zip 1.1MB

安装成功后,用Cursor打开项目即可,然后在命令行中安装相关的依赖:

• 安装依赖:

pnpm install

2.1.2 放入需求文档

接下来我们把AI给到的需求文档放到我们的项目当中:

1. 项目的根目录下创建一个 docs/ 目录

2. 创建一个 /docs/prd.md 文件

3. 复制粘贴刚才1.2中AI给到我们的需求文档

2.2 填写环境变量

• 将项目根目录下的.env.example 修改成为 .env.local,并且添加 SUPABASE_SERVICE_KEY 这个环境变量。

• 在MemfireDB的【设置】-【API】-【API设置】中,找到对应的应用URL和公钥,填入到 .env.local中

对应关系如下:

NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_KEY=your-service-keym

NEXT_PUBLIC_SUPABASE_URL : 应用URL

NEXT_PUBLIC_SUPABASE_ANON_KEY : anon 公钥

SUPABASE_SERVICE_KEY : service_role 私钥

2.3 增加管理角色supabase

• 提示词:

@supabase 创建一个admin.ts,使用@supabase/supabase-js,调用环境变量中SUPABASE_SERVICE_KEY初始化supabase,这是服务端私钥,以确保是service_role

注意:你 @supabase 文件夹的操作,需要自己手动@,直接复制提示词没有效果!

等待AI生成完成,这一步非常关键,AI应该会正确的创建 utils/supabase/admin.ts 文件,文件内容如下:

import { createClient } from '@supabase/supabase-js';
// Create a Supabase client with the service role key
// This allows full access to the database without RLS restrictions
// Should ONLY be used in server-side code
export const createAdminClient = () => {
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
const supabaseServiceKey = process.env.SUPABASE_SERVICE_KEY;
if (!supabaseUrl || !supabaseServiceKey) {
throw new Error('Missing Supabase environment variables for admin client');
}
return createClient(supabaseUrl, supabaseServiceKey, {
auth: {
autoRefreshToken: false,
persistSession: false
}
});
};

为什么要使用服务端私钥?

服务端私钥有最高权限,可以不受数据库中表的RLS策略的限制,这样能让我们的管理员更加方便的操作数据库,对其中的几张表进行增/删/改/查。我们只需要确保在操作前,校验这个用户是管理员用户就行了。

2.4 创建对应的rules

接下来我们来创建一下Cursor Rules,首先我们会通过Cursor 0.49版本引入的 【Generate Cursor Rules】的功能,来自动创建这个项目对应的Cursor Rules。之后我们再来编写一些自定义的Cursor Rules。

2.4.1 Cursor自动生成Cursor Rules

•在Agent模式下,输入反斜杠,点击 Generate Cursor Rules。让AI自动的创建 Cursor Rules

•等待AI生成完成,你会看到在 .cursor/rules 中Cursor会自动的帮我们创建对应的 Cursor Rules.

2.4.2 创建自定义Cursor Rules

• project-rule.mdc:

# 项目开发规则
1. 所有的数据库请求逻辑,都需要新建api实现,不能直接通过supabase-sdk操作
2. api的所有请求,都使用utils/supabase/admin.ts进行操作,避免RLS策略
3. 所有的api请求逻辑,都需要通过中间件校验用户是否是管理员。通过用户是否在 `admin_users`这张表中。如果该用户不是管理员,则接口报错。
4. 所有的文案都使用中文的,这是一个中文网站

• 记得把这个设置为Always

2.5 启动项目

到这一步,初始化项目就完成了,在命令行执行 npm run dev,然后开始进如实际的业务开发中吧!

记得用Git提交一下对应的修改哦!有一个好的Git版本管理的习惯~

3. 用户登陆+管理功能

3.1修改页面

• 输入下面的提示词:

根据 @prd.md 需求文档,将 @page.tsx 把首页修改成为后台的简单首页,用户点击可以进行登陆和注册,注册默认为普通用户,登陆用户后需要进行校验,如果不为管理员,不允许登陆。登陆注册采用现在项目中已有的页面,不要自己创建。首页只作为跳转使用

测试登陆注册功能,如果遇到问题进行优化,你可能会遇到以下问题,跟着进行修改(注意:你遇到的问题可能会和我遇到的不一致,我们根据具体问题具体修改)

• 首页布局问题

提示词:

@layout.tsx 移除掉默认的布局,只保留子页面

• 登录注册页相关的布局问题

• 提示词:

1. 优化 @(auth-pages) 的相关页面布局,要求居中显示
2. 同时优化文案,为中文

3.2 添加sql

在memfireddb中添加管理员的表

• SQL语句:

create table public.admin_users (
user_id uuid primary key references auth.users(id) on delete cascade,
created_at timestamp without time zone default now()
);
-- 启用 Row‑Level Security
alter table public.admin_users enable row level security;
-- 1) 仅允许已存在的管理员查看记录(判断当前 uid 是否已在表内)
create policy "Admins can read admin_users"
on public.admin_users
for select
using (exists (select 1 from public.admin_users au where au.user_id = auth.uid()));
-- 2) 仅允许已存在的管理员添加新管理员
create policy "Admins can add admins"
on public.admin_users
for insert
with check (exists (select 1 from public.admin_users au where au.user_id = auth.uid()));
-- 3) 仅允许已存在的管理员移除管理员
create policy "Admins can remove admins"
on public.admin_users
for delete
using (exists (select 1 from public.admin_users au where au.user_id = auth.uid()));

3.3 添加管理员账号

•点击【认证】,选择你想添加进入管理员的用户id,复制用户UID

• 点击【表编辑器】,打开 admin_users这张表,添加插入一条数据。

。user_id 为你刚才复制的用户id

。is_super 选择 TRUE

3.4 测试

测试登陆,目前管理员登录功能是好使的了。但是现在有个bug 就是,如果不是管理员,依然可以登录,但是是跳转了到/protected 页面,这里我们来让AI进行修改:

•提示词:

现在有个bug,我希望如果我不是管理员,登录都不应该登录成功的,也不应该自动跳转到/protected页面,而是报错。

如果遇到报错,把明确的报错信息给到Cursor,让Al进行修改修改。

3.5 完成用户管理

接下来我们来完成用户管理页面 /admin/users

• 提示词

输入以下提示词:

创建/admin/users页面,并完成设置管理员和移除管理员的功能

如果遇到报错,把明确的报错信息给到Cursor,让AI进行修改修改。我们这里遇到一个登陆的报错,直接在控制台找到报错信息,复制粘贴给Cursor让其修改。

如果正常的话,你就完成了用户管理这个页面的开发。

4. 完成概览+工具管理

4.1 放入数据库文档

• 在 docs/sql.md 下创建一个数据库文档,用于之后的业务逻辑中编写后端逻辑。

# 数据库表结构
1. AI工具表:用于存放项目中的所有AI工具
```sql
create table
public.ai_tools (
id uuid not null default uuid_generate_v4 (),
name character varying(200) not null,
slug character varying(200) not null,
description text not null,
full_description text null,
website_url character varying(255) null,
image_url character varying(255) null,
category_id uuid not null,
created_at timestamp without time zone not null default now(),
updated_at timestamp without time zone not null default now(),
user_id uuid null,
is_approved boolean not null default true,
logo_url text null,
type text null,
constraint ai_tools_pkey primary key (id),
constraint ai_tools_slug_key unique (slug),
constraint ai_tools_category_id_fkey foreign key (category_id) references categories (id),
constraint ai_tools_user_id_fkey foreign key (user_id) references users (id)
) tablespace pg_default;
create index if not exists idx_ai_tools_category_id on public.ai_tools using btree (category_id) tablespace pg_default;
create index if not exists idx_ai_tools_user_id on public.ai_tools using btree (user_id) tablespace pg_default;
```
2. AI工具分类表:用于存放项目中的所有AI工具分类
```sql
create table
public.categories (
id uuid not null default uuid_generate_v4 (),
name character varying(100) not null,
icon character varying(255) not null,
created_at timestamp without time zone not null default now(),
constraint categories_pkey primary key (id)
) tablespace pg_default;
```
3. 用户提交的AI工具记录表:用于存放用户提交的AI工具记录
```sql
create table
public.tool_submissions (
id uuid not null default uuid_generate_v4 (),
name character varying(200) not null,
description text not null,
full_description text null,
website_url character varying(255) not null,
image_url character varying(255) null,
category_id uuid not null,
user_id uuid not null,
status character varying(20) not null default 'pending'::character varying,
admin_comments text null,
created_at timestamp without time zone not null default now(),
updated_at timestamp without time zone not null default now(),
processed_at timestamp without time zone null,
ai_tool_id uuid null,
slug text not null,
constraint tool_submissions_pkey primary key (id),
constraint tool_submissions_category_id_fkey foreign key (category_id) references categories (id),
constraint tool_submissions_user_id_fkey foreign key (user_id) references users (id),
constraint tool_submissions_ai_tool_id_fkey foreign key (ai_tool_id) references ai_tools (id)
) tablespace pg_default;
create index if not exists idx_tool_submissions_user_id on public.tool_submissions using btree (user_id) tablespace pg_default;
create index if not exists idx_tool_submissions_status on public.tool_submissions using btree (status) tablespace pg_default;
create index if not exists idx_tool_submissions_category_id on public.tool_submissions using btree (category_id) tablespace pg_default;
create index if not exists idx_tool_submissions_created_at on public.tool_submissions using btree (created_at) tablespace pg_default;
```
4. 管理员表:用于存放后台管理员信息
```sql
create table
public.admin_users (
user_id uuid not null,
created_at timestamp without time zone null default now(),
constraint admin_users_pkey primary key (user_id),
constraint admin_users_user_id_fkey foreign key (user_id) references users (id) on delete cascade
) tablespace pg_default;
```

4.2 卡片数据

首先我们来开发后台【概览】页面的卡片数据,输入以下提示词:

• 提示词:

@page.tsx 完成AI工具导航站的数据卡片数据获取和渲染逻辑,参考@sql.md

等Cursor开发成功后,可以测试管理后台的卡片数据,完成

4.3 完成新建工具

表单参考截图如下:

现在我们来完成新增工具的提交功能,输入下面的提示词(记得复制表单参考截图哦~)

提示词:

1. 完成 @page.tsx 添加AI工具的逻辑,跳转到/admin/tools/new页面并完成表单提交的前后端逻辑。参考图片中的字段,改页面提交的录入工具的数据会放到 @sql.md 的ai_tools这一张表
2. 图片需要采用上传组件,上传到supabase的storage中后保存对应的url。图标上传到tool-logos这个bucket中,展示图片上传到tool-previews这个bucket中
3. full_description保存的是markdown语法,并且要支持markdown的预览样式
4. 务必添加成功后,添加到ai_tools这一张表中

如果有任何的报错,记得同样给到明确的错误给到Cursor,让AI进行修改就好。

4.4 完成编辑/查看/删除功能现在我们来完成AI工具的编辑、查看和删除功能。

• 提示词:

@page.tsx 请你帮我完成这个页面的列表中编辑、查看和删除功能

等待AI修改完成,如果编辑页面404,这个时候我们需要新增加页面,给Cursor对应的提示词:

编辑页面现在是404,请你创建这个页面,并且参考我新建时的表单,能够实现编辑功能

5. 完成【审核】

现在我们来完成最后的【审核中心】页面,输入对应的提示词:

• 提示词:

完成审核中心页面/admin/submissions,参考 @sql.md 的逻辑:
1. 用户在这个页面能够查看到所有未审核通过的数据,并且点击弹框查看详情
2. 管理员能够查看并且通过,如果点击通过之后,将ai_tool_submissions表中该工具的数据插入到ai_tools中。并修改对应的状态
3. 管理员也能点击驳回,驳回用户的AI工具提交,并修改对应的状态

这一步基本没有太多问题,但是我们之前遗漏了用户提交这张表 ai tool submissions 中AI工具logo的字段创建,导致logo无法正常显示,这个问题不影响核心流程。这个bug修改的点比较多,你可以参考我们的视频内容进行修改~

AI开发完成后,进行实际的测试,如果成功的话,我们就可以去审核用户上传的AI具并且发布。

目前这个产品功能基本就开发完成了,但是【AI分类】还有一个数据库的增/删/改/查我们没有实现,大家可以自己基于Cursor实现。

6. 源码

6.1 初始化项目源码

dirs-admin.zip 1.1MB

6.2 最终项目源码

ai-dirs-admin-main.zip 707.2KB