routes.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. from flask import Blueprint, jsonify, request, current_app, send_from_directory
  2. from app import db
  3. from app.models import User, Carousel, StrategicCooperation, Partner, CaseCategory, CooperationCase, News, DevelopmentHistory, Honor, CompanyInfo, SectionTitle, PageContent
  4. from flask_jwt_extended import create_access_token, jwt_required, get_jwt_identity
  5. from werkzeug.utils import secure_filename
  6. import os
  7. import uuid
  8. bp = Blueprint('api', __name__, url_prefix='/api')
  9. static_bp = Blueprint('static_files', __name__)
  10. # Helper for image upload
  11. ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
  12. def allowed_file(filename):
  13. return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
  14. @bp.route('/upload', methods=['POST'])
  15. @jwt_required()
  16. def upload_file():
  17. if 'file' not in request.files:
  18. return jsonify({'error': 'No file part'}), 400
  19. file = request.files['file']
  20. if file.filename == '':
  21. return jsonify({'error': 'No selected file'}), 400
  22. if file and allowed_file(file.filename):
  23. filename = secure_filename(file.filename)
  24. # Unique filename
  25. unique_filename = f"{uuid.uuid4().hex}_{filename}"
  26. upload_path = current_app.config['UPLOAD_FOLDER']
  27. if not os.path.exists(upload_path):
  28. os.makedirs(upload_path)
  29. file.save(os.path.join(upload_path, unique_filename))
  30. return jsonify({'url': f'/static/uploads/{unique_filename}'}), 201
  31. return jsonify({'error': 'File type not allowed'}), 400
  32. # Serve static files
  33. @static_bp.route('/static/uploads/<filename>')
  34. def uploaded_file(filename):
  35. return send_from_directory(current_app.config['UPLOAD_FOLDER'], filename)
  36. # Auth
  37. @bp.route('/login', methods=['POST'])
  38. def login():
  39. data = request.get_json()
  40. username = data.get('username')
  41. password = data.get('password')
  42. user = User.query.filter_by(username=username).first()
  43. if user and user.check_password(password):
  44. access_token = create_access_token(identity=username)
  45. return jsonify(access_token=access_token, username=username), 200
  46. return jsonify({"msg": "Bad username or password"}), 401
  47. # User Management
  48. @bp.route('/users', methods=['GET'])
  49. @jwt_required()
  50. def get_users():
  51. users = User.query.all()
  52. return jsonify([{'id': u.id, 'username': u.username, 'created_at': u.created_at} for u in users])
  53. @bp.route('/users', methods=['POST'])
  54. @jwt_required()
  55. def create_user():
  56. data = request.get_json()
  57. if User.query.filter_by(username=data['username']).first():
  58. return jsonify({'error': 'User already exists'}), 400
  59. user = User(username=data['username'])
  60. user.set_password(data['password'])
  61. db.session.add(user)
  62. db.session.commit()
  63. return jsonify({'message': 'User created'}), 201
  64. @bp.route('/users/<int:id>', methods=['PUT'])
  65. @jwt_required()
  66. def update_user(id):
  67. user = User.query.get_or_404(id)
  68. data = request.get_json()
  69. if 'password' in data and data['password']:
  70. user.set_password(data['password'])
  71. db.session.commit()
  72. return jsonify({'message': 'User updated'})
  73. @bp.route('/users/<int:id>', methods=['DELETE'])
  74. @jwt_required()
  75. def delete_user(id):
  76. user = User.query.get_or_404(id)
  77. if user.username == 'admin':
  78. return jsonify({'error': 'Cannot delete admin'}), 403
  79. db.session.delete(user)
  80. db.session.commit()
  81. return jsonify({'message': 'User deleted'})
  82. # Strategic Cooperation
  83. @bp.route('/strategic-cooperation', methods=['GET'])
  84. def get_strategic_cooperation():
  85. items = StrategicCooperation.query.all()
  86. return jsonify([{'id': i.id, 'name': i.name, 'description': i.description, 'image_url': i.image_url, 'link': i.link} for i in items])
  87. @bp.route('/strategic-cooperation', methods=['POST'])
  88. @jwt_required()
  89. def create_strategic_cooperation():
  90. data = request.get_json()
  91. item = StrategicCooperation(name=data['name'], description=data.get('description'), image_url=data.get('image_url'), link=data.get('link'))
  92. db.session.add(item)
  93. db.session.commit()
  94. return jsonify({'message': 'Created', 'id': item.id}), 201
  95. @bp.route('/strategic-cooperation/<int:id>', methods=['PUT'])
  96. @jwt_required()
  97. def update_strategic_cooperation(id):
  98. item = StrategicCooperation.query.get_or_404(id)
  99. data = request.get_json()
  100. item.name = data.get('name', item.name)
  101. item.description = data.get('description', item.description)
  102. item.image_url = data.get('image_url', item.image_url)
  103. item.link = data.get('link', item.link)
  104. db.session.commit()
  105. return jsonify({'message': 'Updated'})
  106. @bp.route('/strategic-cooperation/<int:id>', methods=['DELETE'])
  107. @jwt_required()
  108. def delete_strategic_cooperation(id):
  109. item = StrategicCooperation.query.get_or_404(id)
  110. db.session.delete(item)
  111. db.session.commit()
  112. return jsonify({'message': 'Deleted'})
  113. # Partners
  114. @bp.route('/partners', methods=['GET'])
  115. def get_partners():
  116. items = Partner.query.all()
  117. return jsonify([{'id': i.id, 'name': i.name, 'image_url': i.image_url, 'link': i.link} for i in items])
  118. @bp.route('/partners', methods=['POST'])
  119. @jwt_required()
  120. def create_partner():
  121. data = request.get_json()
  122. item = Partner(name=data['name'], image_url=data.get('image_url'), link=data.get('link'))
  123. db.session.add(item)
  124. db.session.commit()
  125. return jsonify({'message': 'Created', 'id': item.id}), 201
  126. @bp.route('/partners/<int:id>', methods=['PUT'])
  127. @jwt_required()
  128. def update_partner(id):
  129. item = Partner.query.get_or_404(id)
  130. data = request.get_json()
  131. item.name = data.get('name', item.name)
  132. item.image_url = data.get('image_url', item.image_url)
  133. item.link = data.get('link', item.link)
  134. db.session.commit()
  135. return jsonify({'message': 'Updated'})
  136. @bp.route('/partners/<int:id>', methods=['DELETE'])
  137. @jwt_required()
  138. def delete_partner(id):
  139. item = Partner.query.get_or_404(id)
  140. db.session.delete(item)
  141. db.session.commit()
  142. return jsonify({'message': 'Deleted'})
  143. # Carousel
  144. @bp.route('/carousels', methods=['GET'])
  145. def get_carousels():
  146. location = request.args.get('location')
  147. query = Carousel.query
  148. if location:
  149. query = query.filter_by(location=location)
  150. items = query.order_by(Carousel.sort_order).all()
  151. return jsonify([{'id': i.id, 'image_url': i.image_url, 'description': i.description, 'title_image_url': i.title_image_url, 'element_image_url': i.element_image_url, 'tag_text': i.tag_text, 'title_content': i.title_content, 'link': i.link, 'location': i.location, 'sort_order': i.sort_order} for i in items])
  152. @bp.route('/carousels', methods=['POST'])
  153. @jwt_required()
  154. def create_carousel():
  155. data = request.get_json()
  156. item = Carousel(
  157. image_url=data['image_url'],
  158. description=data.get('description'),
  159. title_image_url=data.get('title_image_url'),
  160. element_image_url=data.get('element_image_url'),
  161. tag_text=data.get('tag_text'),
  162. title_content=data.get('title_content'),
  163. link=data.get('link'),
  164. location=data['location'],
  165. sort_order=data.get('sort_order', 0)
  166. )
  167. db.session.add(item)
  168. db.session.commit()
  169. return jsonify({'message': 'Created', 'id': item.id}), 201
  170. @bp.route('/carousels/<int:id>', methods=['PUT'])
  171. @jwt_required()
  172. def update_carousel(id):
  173. item = Carousel.query.get_or_404(id)
  174. data = request.get_json()
  175. item.image_url = data.get('image_url', item.image_url)
  176. item.description = data.get('description', item.description)
  177. item.title_image_url = data.get('title_image_url', item.title_image_url)
  178. item.element_image_url = data.get('element_image_url', item.element_image_url)
  179. item.tag_text = data.get('tag_text', item.tag_text)
  180. item.title_content = data.get('title_content', item.title_content)
  181. item.link = data.get('link', item.link)
  182. item.location = data.get('location', item.location)
  183. item.sort_order = data.get('sort_order', item.sort_order)
  184. db.session.commit()
  185. return jsonify({'message': 'Updated'})
  186. @bp.route('/carousels/<int:id>', methods=['DELETE'])
  187. @jwt_required()
  188. def delete_carousel(id):
  189. item = Carousel.query.get_or_404(id)
  190. db.session.delete(item)
  191. db.session.commit()
  192. return jsonify({'message': 'Deleted'})
  193. # Case Categories
  194. @bp.route('/case-categories', methods=['GET'])
  195. def get_case_categories():
  196. section = request.args.get('section')
  197. query = CaseCategory.query
  198. if section:
  199. query = query.filter_by(section=section)
  200. items = query.all()
  201. return jsonify([{'id': i.id, 'name': i.name, 'section': i.section} for i in items])
  202. @bp.route('/case-categories', methods=['POST'])
  203. @jwt_required()
  204. def create_case_category():
  205. data = request.get_json()
  206. item = CaseCategory(name=data['name'], section=data['section'])
  207. db.session.add(item)
  208. db.session.commit()
  209. return jsonify({'message': 'Created', 'id': item.id}), 201
  210. @bp.route('/case-categories/<int:id>', methods=['PUT'])
  211. @jwt_required()
  212. def update_case_category(id):
  213. item = CaseCategory.query.get_or_404(id)
  214. data = request.get_json()
  215. item.name = data.get('name', item.name)
  216. item.section = data.get('section', item.section)
  217. db.session.commit()
  218. return jsonify({'message': 'Updated'})
  219. @bp.route('/case-categories/<int:id>', methods=['DELETE'])
  220. @jwt_required()
  221. def delete_case_category(id):
  222. item = CaseCategory.query.get_or_404(id)
  223. db.session.delete(item)
  224. db.session.commit()
  225. return jsonify({'message': 'Deleted'})
  226. # Cooperation Cases
  227. @bp.route('/cases', methods=['GET'])
  228. def get_cases():
  229. section = request.args.get('section')
  230. category_id = request.args.get('category_id')
  231. query = CooperationCase.query
  232. if section:
  233. query = query.filter_by(section=section)
  234. if category_id:
  235. query = query.filter_by(category_id=category_id)
  236. items = query.all()
  237. return jsonify([{
  238. 'id': i.id,
  239. 'title': i.title,
  240. 'image_url': i.image_url,
  241. 'description': i.description,
  242. 'section': i.section,
  243. 'category_id': i.category_id,
  244. 'category_name': i.category.name if i.category else None
  245. } for i in items])
  246. @bp.route('/cases', methods=['POST'])
  247. @jwt_required()
  248. def create_case():
  249. data = request.get_json()
  250. item = CooperationCase(
  251. title=data['title'],
  252. image_url=data.get('image_url'),
  253. description=data.get('description'),
  254. section=data['section'],
  255. category_id=data.get('category_id')
  256. )
  257. db.session.add(item)
  258. db.session.commit()
  259. return jsonify({'message': 'Created', 'id': item.id}), 201
  260. @bp.route('/cases/<int:id>', methods=['PUT'])
  261. @jwt_required()
  262. def update_case(id):
  263. item = CooperationCase.query.get_or_404(id)
  264. data = request.get_json()
  265. item.title = data.get('title', item.title)
  266. item.image_url = data.get('image_url', item.image_url)
  267. item.description = data.get('description', item.description)
  268. item.section = data.get('section', item.section)
  269. item.category_id = data.get('category_id', item.category_id)
  270. db.session.commit()
  271. return jsonify({'message': 'Updated'})
  272. @bp.route('/cases/<int:id>', methods=['DELETE'])
  273. @jwt_required()
  274. def delete_case(id):
  275. item = CooperationCase.query.get_or_404(id)
  276. db.session.delete(item)
  277. db.session.commit()
  278. return jsonify({'message': 'Deleted'})
  279. # News
  280. @bp.route('/news', methods=['GET'])
  281. def get_news():
  282. items = News.query.order_by(News.publish_time.desc()).all()
  283. return jsonify([{
  284. 'id': i.id,
  285. 'title': i.title,
  286. 'image_url': i.image_url,
  287. 'author': i.author,
  288. 'publish_time': i.publish_time,
  289. 'created_at': i.created_at
  290. } for i in items])
  291. @bp.route('/news/<int:id>', methods=['GET'])
  292. def get_news_detail(id):
  293. item = News.query.get_or_404(id)
  294. return jsonify({
  295. 'id': item.id,
  296. 'title': item.title,
  297. 'content': item.content,
  298. 'image_url': item.image_url,
  299. 'author': item.author,
  300. 'publish_time': item.publish_time,
  301. 'created_at': item.created_at
  302. })
  303. @bp.route('/news', methods=['POST'])
  304. @jwt_required()
  305. def create_news():
  306. data = request.get_json()
  307. item = News(
  308. title=data['title'],
  309. content=data.get('content'),
  310. image_url=data.get('image_url'),
  311. author=data.get('author')
  312. )
  313. db.session.add(item)
  314. db.session.commit()
  315. return jsonify({'message': 'Created', 'id': item.id}), 201
  316. @bp.route('/news/<int:id>', methods=['PUT'])
  317. @jwt_required()
  318. def update_news(id):
  319. item = News.query.get_or_404(id)
  320. data = request.get_json()
  321. item.title = data.get('title', item.title)
  322. item.content = data.get('content', item.content)
  323. item.image_url = data.get('image_url', item.image_url)
  324. item.author = data.get('author', item.author)
  325. db.session.commit()
  326. return jsonify({'message': 'Updated'})
  327. @bp.route('/news/<int:id>', methods=['DELETE'])
  328. @jwt_required()
  329. def delete_news(id):
  330. item = News.query.get_or_404(id)
  331. db.session.delete(item)
  332. db.session.commit()
  333. return jsonify({'message': 'Deleted'})
  334. # Development History
  335. @bp.route('/development-history', methods=['GET'])
  336. def get_development_history():
  337. items = DevelopmentHistory.query.order_by(DevelopmentHistory.year.asc()).all()
  338. return jsonify([{'id': i.id, 'year': i.year, 'title': i.title, 'description': i.description, 'image_url': i.image_url} for i in items])
  339. @bp.route('/development-history', methods=['POST'])
  340. @jwt_required()
  341. def create_development_history():
  342. data = request.get_json()
  343. item = DevelopmentHistory(
  344. year=data['year'],
  345. title=data['title'],
  346. description=data.get('description'),
  347. image_url=data.get('image_url')
  348. )
  349. db.session.add(item)
  350. db.session.commit()
  351. return jsonify({'message': 'Created', 'id': item.id}), 201
  352. @bp.route('/development-history/<int:id>', methods=['PUT'])
  353. @jwt_required()
  354. def update_development_history(id):
  355. item = DevelopmentHistory.query.get_or_404(id)
  356. data = request.get_json()
  357. item.year = data.get('year', item.year)
  358. item.title = data.get('title', item.title)
  359. item.description = data.get('description', item.description)
  360. item.image_url = data.get('image_url', item.image_url)
  361. db.session.commit()
  362. return jsonify({'message': 'Updated'})
  363. @bp.route('/development-history/<int:id>', methods=['DELETE'])
  364. @jwt_required()
  365. def delete_development_history(id):
  366. item = DevelopmentHistory.query.get_or_404(id)
  367. db.session.delete(item)
  368. db.session.commit()
  369. return jsonify({'message': 'Deleted'})
  370. # Honors
  371. @bp.route('/honors', methods=['GET'])
  372. def get_honors():
  373. items = Honor.query.all()
  374. return jsonify([{'id': i.id, 'title': i.title, 'image_url': i.image_url} for i in items])
  375. @bp.route('/honors', methods=['POST'])
  376. @jwt_required()
  377. def create_honor():
  378. data = request.get_json()
  379. item = Honor(
  380. title=data['title'],
  381. image_url=data.get('image_url')
  382. )
  383. db.session.add(item)
  384. db.session.commit()
  385. return jsonify({'message': 'Created', 'id': item.id}), 201
  386. @bp.route('/honors/<int:id>', methods=['PUT'])
  387. @jwt_required()
  388. def update_honor(id):
  389. item = Honor.query.get_or_404(id)
  390. data = request.get_json()
  391. item.title = data.get('title', item.title)
  392. item.image_url = data.get('image_url', item.image_url)
  393. db.session.commit()
  394. return jsonify({'message': 'Updated'})
  395. @bp.route('/honors/<int:id>', methods=['DELETE'])
  396. @jwt_required()
  397. def delete_honor(id):
  398. item = Honor.query.get_or_404(id)
  399. db.session.delete(item)
  400. db.session.commit()
  401. return jsonify({'message': 'Deleted'})
  402. # Section Titles
  403. @bp.route('/section-titles', methods=['GET'])
  404. def get_section_titles():
  405. items = SectionTitle.query.all()
  406. return jsonify([{
  407. 'id': i.id,
  408. 'section_key': i.section_key,
  409. 'section_name': i.section_name,
  410. 'title': i.title,
  411. 'subtitle': i.subtitle,
  412. 'icon_url': i.icon_url
  413. } for i in items])
  414. @bp.route('/section-titles/<int:id>', methods=['PUT'])
  415. @jwt_required()
  416. def update_section_title(id):
  417. item = SectionTitle.query.get_or_404(id)
  418. data = request.get_json()
  419. item.title = data.get('title', item.title)
  420. item.subtitle = data.get('subtitle', item.subtitle)
  421. item.icon_url = data.get('icon_url', item.icon_url)
  422. db.session.commit()
  423. return jsonify({'message': 'Updated'})
  424. # Page Contents
  425. @bp.route('/page-contents', methods=['GET'])
  426. def get_page_contents():
  427. items = PageContent.query.all()
  428. return jsonify([{
  429. 'id': i.id,
  430. 'page_key': i.page_key,
  431. 'page_name': i.page_name,
  432. 'content': i.content,
  433. 'updated_at': i.updated_at
  434. } for i in items])
  435. @bp.route('/page-contents/<page_key>', methods=['GET'])
  436. def get_page_content_by_key(page_key):
  437. item = PageContent.query.filter_by(page_key=page_key).first_or_404()
  438. return jsonify({
  439. 'id': item.id,
  440. 'page_key': item.page_key,
  441. 'page_name': item.page_name,
  442. 'content': item.content,
  443. 'updated_at': item.updated_at
  444. })
  445. @bp.route('/page-contents/<page_key>', methods=['PUT'])
  446. @jwt_required()
  447. def update_page_content(page_key):
  448. item = PageContent.query.filter_by(page_key=page_key).first_or_404()
  449. data = request.get_json()
  450. item.content = data.get('content', item.content)
  451. db.session.commit()
  452. return jsonify({'message': 'Updated'})
  453. # Company Info
  454. @bp.route('/company-info', methods=['GET'])
  455. def get_company_info():
  456. info = CompanyInfo.query.first()
  457. if not info:
  458. return jsonify({})
  459. return jsonify({
  460. 'id': info.id,
  461. 'intro_banner_url': info.intro_banner_url,
  462. 'intro_content': info.intro_content,
  463. 'intro_image_url': info.intro_image_url,
  464. 'vision': info.vision,
  465. 'mission': info.mission,
  466. 'values': info.values,
  467. 'phone': info.phone,
  468. 'email': info.email,
  469. 'qrcode_url': info.qrcode_url
  470. })
  471. @bp.route('/company-info', methods=['POST', 'PUT'])
  472. @jwt_required()
  473. def update_company_info():
  474. info = CompanyInfo.query.first()
  475. data = request.get_json()
  476. if not info:
  477. info = CompanyInfo()
  478. db.session.add(info)
  479. info.intro_banner_url = data.get('intro_banner_url', info.intro_banner_url)
  480. info.intro_content = data.get('intro_content', info.intro_content)
  481. info.intro_image_url = data.get('intro_image_url', info.intro_image_url)
  482. info.vision = data.get('vision', info.vision)
  483. info.mission = data.get('mission', info.mission)
  484. info.values = data.get('values', info.values)
  485. info.phone = data.get('phone', info.phone)
  486. info.email = data.get('email', info.email)
  487. info.qrcode_url = data.get('qrcode_url', info.qrcode_url)
  488. db.session.commit()
  489. return jsonify({'message': 'Updated'})