fix: make CMS content live and migrate to MySQL
This commit is contained in:
+39
-27
@@ -21,6 +21,7 @@ const db = getDB();
|
||||
app.use(cors({ origin: process.env.CORS_ORIGIN || true }));
|
||||
app.use(express.json({ limit: '5mb' }));
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
app.use((req, res, next) => { res.set('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); next(); });
|
||||
app.use(authMiddleware);
|
||||
|
||||
// 静态:上传文件
|
||||
@@ -139,6 +140,8 @@ app.post('/api/contact/leads', (req, res) => {
|
||||
// 通用工具
|
||||
const nowISO = () => new Date().toISOString();
|
||||
const genId = (p) => `${p}-${Date.now()}-${Math.random().toString(36).slice(2,6)}`;
|
||||
const queryOne = (sql, params=[]) => new Promise((resolve, reject) => db.get(sql, params, (err, row) => err ? reject(err) : resolve(row || null)));
|
||||
const queryAll = (sql, params=[]) => new Promise((resolve, reject) => db.all(sql, params, (err, rows) => err ? reject(err) : resolve(rows || [])));
|
||||
|
||||
// 全局配置
|
||||
app.get('/api/cms/config', (req, res) => {
|
||||
@@ -153,6 +156,16 @@ app.put('/api/cms/config', (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
// 可配置站点文案。页面只读取公开聚合中的 texts,后台通过此处集中维护。
|
||||
app.get('/api/cms/texts', (req, res) => db.all(`SELECT * FROM site_texts ORDER BY id`, (e, rows) => res.json({ code: 0, data: rows || [] })));
|
||||
app.put('/api/cms/texts', (req, res) => {
|
||||
const items = Array.isArray(req.body) ? req.body : [];
|
||||
const stmt = db.prepare(`INSERT INTO site_texts (id, label, value, updated_at) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE label=VALUES(label), value=VALUES(value), updated_at=VALUES(updated_at)`);
|
||||
Promise.all(items.filter(it => it?.id).map(it => stmt.run(it.id, it.label || it.id, it.value || '', nowISO())))
|
||||
.then(() => stmt.finalize(() => res.json({ code: 0, msg: '保存成功' })))
|
||||
.catch(err => res.status(500).json({ code: 500, msg: err.message }));
|
||||
});
|
||||
|
||||
// 首页板块
|
||||
app.get('/api/cms/home-sections', (req, res) => {
|
||||
db.all(`SELECT * FROM home_sections ORDER BY sort_order DESC`, (err, rows) => res.json({code:0, data: rows}));
|
||||
@@ -192,21 +205,20 @@ app.get('/api/cms/four-values', (req,res)=> db.all(`SELECT * FROM four_values OR
|
||||
app.post('/api/cms/four-values', (req,res)=>{
|
||||
const b=req.body; if(!b.key||!b.name) return res.status(400).json({code:400,msg:'key和名称必填'});
|
||||
const id=genId('fv');
|
||||
db.run(`INSERT INTO four_values (id, key, name, definition, description, image_url, sort_order, status, updated_at) VALUES (?,?,?,?,?,?,?,?,?)`,
|
||||
db.run(`INSERT INTO four_values (id, \`key\`, name, definition, description, image_url, sort_order, status, updated_at) VALUES (?,?,?,?,?,?,?,?,?)`,
|
||||
[id,b.key,b.name,b.definition,b.description,b.image_url,b.sort_order||0,b.status||'published',nowISO()], e=> res.json({code:0,data:{id}}));
|
||||
});
|
||||
app.put('/api/cms/four-values/:id', (req,res)=>{
|
||||
const b=req.body;
|
||||
db.run(`UPDATE four_values SET key=?, name=?, definition=?, description=?, image_url=?, sort_order=?, status=?, updated_at=? WHERE id=?`,
|
||||
db.run(`UPDATE four_values SET \`key\`=?, name=?, definition=?, description=?, image_url=?, sort_order=?, status=?, updated_at=? WHERE id=?`,
|
||||
[b.key,b.name,b.definition,b.description,b.image_url,b.sort_order,b.status,nowISO(),req.params.id], e=> res.json({code:0,msg:'更新成功'}));
|
||||
});
|
||||
app.delete('/api/cms/four-values/:id', (req,res)=> db.run(`DELETE FROM four_values WHERE id=?`,[req.params.id], e=> res.json({code:0,msg:'删除成功'})));
|
||||
app.get('/api/cms/amb-states', (req,res)=> db.all(`SELECT * FROM amb_states ORDER BY sort_order DESC`, (e,r)=> res.json({code:0,data:r})));
|
||||
app.put('/api/cms/amb-states/:id', (req,res)=>{
|
||||
const b=req.body;
|
||||
// fixed_note 不可删但可编辑?按约束固定说明不可删
|
||||
db.run(`UPDATE amb_states SET name=?, definition=?, description=?, image_url=?, sort_order=?, status=?, updated_at=? WHERE id=?`,
|
||||
[b.name,b.definition,b.description,b.image_url,b.sort_order,b.status,nowISO(),req.params.id], e=> res.json({code:0,msg:'更新成功'}));
|
||||
db.run(`UPDATE amb_states SET name=?, definition=?, description=?, image_url=?, sort_order=?, fixed_note=?, status=?, updated_at=? WHERE id=?`,
|
||||
[b.name,b.definition,b.description,b.image_url,b.sort_order,b.fixed_note,b.status,nowISO(),req.params.id], e=> res.json({code:0,msg:'更新成功'}));
|
||||
});
|
||||
|
||||
// 方法与能力
|
||||
@@ -238,7 +250,7 @@ app.post('/api/cms/services', (req,res)=>{
|
||||
const id=genId('svc');
|
||||
const slug = b.slug || `svc-${Date.now()}`;
|
||||
db.run(`INSERT INTO services (id, slug, name, stage, intro, service_content, delivery, suitable, price, price_unit, advantage, detail_html, status, sort_weight, type, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`,
|
||||
[id,slug,b.name,b.stage,b.intro,b.service_content,b.delivery,b.suitable,b.price?Number(b.price):null,b.price_unit,b.advantage,b.detail_html,b.status||'draft',b.sort_weight||0,b.type||'custom',nowISO(),nowISO()], e=> res.json({code:0,data:{id,slug}}));
|
||||
[id,slug,b.name,b.stage,b.intro,b.service_content,b.delivery,b.suitable,b.price?Number(b.price):null,b.price_unit,b.advantage,b.detail_html,b.status||'published',b.sort_weight||0,b.type||'custom',nowISO(),nowISO()], e=> res.json({code:0,data:{id,slug}}));
|
||||
});
|
||||
app.put('/api/cms/services/:id', (req,res)=>{
|
||||
const b=req.body;
|
||||
@@ -256,7 +268,7 @@ app.post('/api/cms/cases', (req,res)=>{
|
||||
const id=genId('case');
|
||||
const slug = b.slug || `case-${Date.now()}`;
|
||||
db.run(`INSERT INTO cases (id, slug, industry, scale, amb_tags, value_tags, title, cover_url, original_state, goal, gap, root_cause, ameba_intervention, evolution_path, actions, phased_result, continuous_iteration, publish_time, status, sort_weight, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`,
|
||||
[id,slug,b.industry,b.scale,JSON.stringify(b.amb_tags||[]),JSON.stringify(b.value_tags||[]),b.title,b.cover_url,b.original_state,b.goal,b.gap,b.root_cause,b.ameba_intervention,b.evolution_path,b.actions,b.phased_result,b.continuous_iteration,b.publish_time||nowISO(),b.status||'draft',b.sort_weight||0,nowISO(),nowISO()], e=> res.json({code:0,data:{id,slug}}));
|
||||
[id,slug,b.industry,b.scale,JSON.stringify(b.amb_tags||[]),JSON.stringify(b.value_tags||[]),b.title,b.cover_url,b.original_state,b.goal,b.gap,b.root_cause,b.ameba_intervention,b.evolution_path,b.actions,b.phased_result,b.continuous_iteration,b.publish_time||nowISO(),b.status||'published',b.sort_weight||0,nowISO(),nowISO()], e=> res.json({code:0,data:{id,slug}}));
|
||||
});
|
||||
app.put('/api/cms/cases/:id', (req,res)=>{
|
||||
const b=req.body;
|
||||
@@ -273,7 +285,7 @@ app.post('/api/cms/articles', (req,res)=>{
|
||||
const id=genId('art');
|
||||
const slug = b.slug || `art-${Date.now()}`;
|
||||
db.run(`INSERT INTO articles (id, slug, title, subtitle, category, cover_url, content_html, publish_time, recommend_weight, status, created_at, updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)`,
|
||||
[id,slug,b.title,b.subtitle,b.category,b.cover_url,b.content_html,b.publish_time||nowISO(),b.recommend_weight||0,b.status||'draft',nowISO(),nowISO()], e=> res.json({code:0,data:{id,slug}}));
|
||||
[id,slug,b.title,b.subtitle,b.category,b.cover_url,b.content_html,b.publish_time||nowISO(),b.recommend_weight||0,b.status||'published',nowISO(),nowISO()], e=> res.json({code:0,data:{id,slug}}));
|
||||
});
|
||||
app.put('/api/cms/articles/:id', (req,res)=>{
|
||||
const b=req.body;
|
||||
@@ -292,25 +304,25 @@ app.put('/api/cms/self-check', (req,res)=>{
|
||||
|
||||
// 前端公开聚合接口(供前端一次性拉取,不需要鉴权,使用GET放行)
|
||||
app.get('/api/cms/public', (req,res)=>{
|
||||
const data={};
|
||||
db.serialize(()=>{
|
||||
db.get(`SELECT * FROM global_config WHERE id=1`, (e,r)=> data.config=r);
|
||||
db.all(`SELECT * FROM home_sections WHERE visible=1 ORDER BY sort_order DESC`, (e,r)=> data.home_sections=r);
|
||||
db.get(`SELECT * FROM ameba_page WHERE id=1`, (e,r)=> data.ameba=r);
|
||||
db.all(`SELECT * FROM experts WHERE status='published' ORDER BY sort_weight DESC`, (e,r)=> data.experts=r);
|
||||
db.get(`SELECT * FROM evolution_thought WHERE id=1`, (e,r)=> data.evolution_thought=r);
|
||||
db.all(`SELECT * FROM four_values WHERE status='published' ORDER BY sort_order DESC`, (e,r)=> data.four_values=r);
|
||||
db.all(`SELECT * FROM amb_states WHERE status='published' ORDER BY sort_order DESC`, (e,r)=> data.amb_states=r);
|
||||
db.get(`SELECT * FROM evolution_process WHERE id=1`, (e,r)=> data.evolution_process=r);
|
||||
db.all(`SELECT * FROM ten_systems WHERE status='published' ORDER BY sort_order DESC`, (e,r)=> data.ten_systems=r);
|
||||
db.all(`SELECT * FROM services WHERE status='published' ORDER BY sort_weight DESC`, (e,r)=> data.services=r);
|
||||
db.all(`SELECT * FROM cases WHERE status='published' ORDER BY sort_weight DESC`, (e,r)=> data.cases=r);
|
||||
db.all(`SELECT * FROM articles WHERE status='published' ORDER BY recommend_weight DESC`, (e,r)=> data.articles=r);
|
||||
db.get(`SELECT * FROM self_check WHERE id=1`, (e,r)=> {
|
||||
data.self_check=r;
|
||||
res.json({code:0,data});
|
||||
});
|
||||
});
|
||||
Promise.all([
|
||||
queryOne(`SELECT * FROM global_config WHERE id=1`),
|
||||
queryAll(`SELECT * FROM home_sections WHERE visible=1 ORDER BY sort_order DESC`),
|
||||
queryOne(`SELECT * FROM ameba_page WHERE id=1`),
|
||||
queryAll(`SELECT * FROM experts WHERE status='published' ORDER BY sort_weight DESC`),
|
||||
queryOne(`SELECT * FROM evolution_thought WHERE id=1`),
|
||||
queryAll(`SELECT * FROM four_values WHERE status='published' ORDER BY sort_order DESC`),
|
||||
queryAll(`SELECT * FROM amb_states WHERE status='published' ORDER BY sort_order DESC`),
|
||||
queryOne(`SELECT * FROM evolution_process WHERE id=1`),
|
||||
queryAll(`SELECT * FROM ten_systems WHERE status='published' ORDER BY sort_order DESC`),
|
||||
queryAll(`SELECT * FROM services WHERE status='published' ORDER BY sort_weight DESC`),
|
||||
queryAll(`SELECT * FROM cases WHERE status='published' ORDER BY sort_weight DESC`),
|
||||
queryAll(`SELECT * FROM articles WHERE status='published' ORDER BY recommend_weight DESC`),
|
||||
queryOne(`SELECT * FROM self_check WHERE id=1`),
|
||||
queryAll(`SELECT id, label, value FROM site_texts ORDER BY id`),
|
||||
]).then(([config, home_sections, ameba, experts, evolution_thought, four_values, amb_states, evolution_process, ten_systems, services, cases, articles, self_check, texts]) => {
|
||||
const textMap = Object.fromEntries(texts.map(item => [item.id, item.value]));
|
||||
res.json({ code: 0, data: { config, home_sections, ameba, experts, evolution_thought, four_values, amb_states, evolution_process, ten_systems, services, cases, articles, self_check, texts: textMap } });
|
||||
}).catch(err => res.status(500).json({ code: 500, msg: err.message }));
|
||||
});
|
||||
|
||||
// ================= 诊断系统 =================
|
||||
|
||||
Reference in New Issue
Block a user