from flask import Blueprint, jsonify, request, current_app, send_from_directory from app import db from app.models import User, Carousel, StrategicCooperation, Partner, CaseCategory, CooperationCase, News, DevelopmentHistory, Honor, CompanyInfo from flask_jwt_extended import create_access_token, jwt_required, get_jwt_identity from werkzeug.utils import secure_filename import os import uuid bp = Blueprint('api', __name__, url_prefix='/api') static_bp = Blueprint('static_files', __name__) # Helper for image upload ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'} def allowed_file(filename): return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS @bp.route('/upload', methods=['POST']) @jwt_required() def upload_file(): if 'file' not in request.files: return jsonify({'error': 'No file part'}), 400 file = request.files['file'] if file.filename == '': return jsonify({'error': 'No selected file'}), 400 if file and allowed_file(file.filename): filename = secure_filename(file.filename) # Unique filename unique_filename = f"{uuid.uuid4().hex}_{filename}" upload_path = current_app.config['UPLOAD_FOLDER'] if not os.path.exists(upload_path): os.makedirs(upload_path) file.save(os.path.join(upload_path, unique_filename)) return jsonify({'url': f'/static/uploads/{unique_filename}'}), 201 return jsonify({'error': 'File type not allowed'}), 400 # Serve static files @static_bp.route('/static/uploads/') def uploaded_file(filename): return send_from_directory(current_app.config['UPLOAD_FOLDER'], filename) # Auth @bp.route('/login', methods=['POST']) def login(): data = request.get_json() username = data.get('username') password = data.get('password') user = User.query.filter_by(username=username).first() if user and user.check_password(password): access_token = create_access_token(identity=username) return jsonify(access_token=access_token, username=username), 200 return jsonify({"msg": "Bad username or password"}), 401 # User Management @bp.route('/users', methods=['GET']) @jwt_required() def get_users(): users = User.query.all() return jsonify([{'id': u.id, 'username': u.username, 'created_at': u.created_at} for u in users]) @bp.route('/users', methods=['POST']) @jwt_required() def create_user(): data = request.get_json() if User.query.filter_by(username=data['username']).first(): return jsonify({'error': 'User already exists'}), 400 user = User(username=data['username']) user.set_password(data['password']) db.session.add(user) db.session.commit() return jsonify({'message': 'User created'}), 201 @bp.route('/users/', methods=['PUT']) @jwt_required() def update_user(id): user = User.query.get_or_404(id) data = request.get_json() if 'password' in data and data['password']: user.set_password(data['password']) db.session.commit() return jsonify({'message': 'User updated'}) @bp.route('/users/', methods=['DELETE']) @jwt_required() def delete_user(id): user = User.query.get_or_404(id) if user.username == 'admin': return jsonify({'error': 'Cannot delete admin'}), 403 db.session.delete(user) db.session.commit() return jsonify({'message': 'User deleted'}) # Strategic Cooperation @bp.route('/strategic-cooperation', methods=['GET']) def get_strategic_cooperation(): items = StrategicCooperation.query.all() return jsonify([{'id': i.id, 'name': i.name, 'description': i.description, 'image_url': i.image_url, 'link': i.link} for i in items]) @bp.route('/strategic-cooperation', methods=['POST']) @jwt_required() def create_strategic_cooperation(): data = request.get_json() item = StrategicCooperation(name=data['name'], description=data.get('description'), image_url=data.get('image_url'), link=data.get('link')) db.session.add(item) db.session.commit() return jsonify({'message': 'Created', 'id': item.id}), 201 @bp.route('/strategic-cooperation/', methods=['PUT']) @jwt_required() def update_strategic_cooperation(id): item = StrategicCooperation.query.get_or_404(id) data = request.get_json() item.name = data.get('name', item.name) item.description = data.get('description', item.description) item.image_url = data.get('image_url', item.image_url) item.link = data.get('link', item.link) db.session.commit() return jsonify({'message': 'Updated'}) @bp.route('/strategic-cooperation/', methods=['DELETE']) @jwt_required() def delete_strategic_cooperation(id): item = StrategicCooperation.query.get_or_404(id) db.session.delete(item) db.session.commit() return jsonify({'message': 'Deleted'}) # Partners @bp.route('/partners', methods=['GET']) def get_partners(): items = Partner.query.all() return jsonify([{'id': i.id, 'name': i.name, 'image_url': i.image_url, 'link': i.link} for i in items]) @bp.route('/partners', methods=['POST']) @jwt_required() def create_partner(): data = request.get_json() item = Partner(name=data['name'], image_url=data.get('image_url'), link=data.get('link')) db.session.add(item) db.session.commit() return jsonify({'message': 'Created', 'id': item.id}), 201 @bp.route('/partners/', methods=['PUT']) @jwt_required() def update_partner(id): item = Partner.query.get_or_404(id) data = request.get_json() item.name = data.get('name', item.name) item.image_url = data.get('image_url', item.image_url) item.link = data.get('link', item.link) db.session.commit() return jsonify({'message': 'Updated'}) @bp.route('/partners/', methods=['DELETE']) @jwt_required() def delete_partner(id): item = Partner.query.get_or_404(id) db.session.delete(item) db.session.commit() return jsonify({'message': 'Deleted'}) # Carousel @bp.route('/carousels', methods=['GET']) def get_carousels(): location = request.args.get('location') query = Carousel.query if location: query = query.filter_by(location=location) items = query.order_by(Carousel.sort_order).all() return jsonify([{'id': i.id, 'image_url': i.image_url, 'link': i.link, 'location': i.location, 'sort_order': i.sort_order} for i in items]) @bp.route('/carousels', methods=['POST']) @jwt_required() def create_carousel(): data = request.get_json() item = Carousel( image_url=data['image_url'], link=data.get('link'), location=data['location'], sort_order=data.get('sort_order', 0) ) db.session.add(item) db.session.commit() return jsonify({'message': 'Created', 'id': item.id}), 201 @bp.route('/carousels/', methods=['PUT']) @jwt_required() def update_carousel(id): item = Carousel.query.get_or_404(id) data = request.get_json() item.image_url = data.get('image_url', item.image_url) item.link = data.get('link', item.link) item.location = data.get('location', item.location) item.sort_order = data.get('sort_order', item.sort_order) db.session.commit() return jsonify({'message': 'Updated'}) @bp.route('/carousels/', methods=['DELETE']) @jwt_required() def delete_carousel(id): item = Carousel.query.get_or_404(id) db.session.delete(item) db.session.commit() return jsonify({'message': 'Deleted'}) # Case Categories @bp.route('/case-categories', methods=['GET']) def get_case_categories(): section = request.args.get('section') query = CaseCategory.query if section: query = query.filter_by(section=section) items = query.all() return jsonify([{'id': i.id, 'name': i.name, 'section': i.section} for i in items]) @bp.route('/case-categories', methods=['POST']) @jwt_required() def create_case_category(): data = request.get_json() item = CaseCategory(name=data['name'], section=data['section']) db.session.add(item) db.session.commit() return jsonify({'message': 'Created', 'id': item.id}), 201 @bp.route('/case-categories/', methods=['PUT']) @jwt_required() def update_case_category(id): item = CaseCategory.query.get_or_404(id) data = request.get_json() item.name = data.get('name', item.name) item.section = data.get('section', item.section) db.session.commit() return jsonify({'message': 'Updated'}) @bp.route('/case-categories/', methods=['DELETE']) @jwt_required() def delete_case_category(id): item = CaseCategory.query.get_or_404(id) db.session.delete(item) db.session.commit() return jsonify({'message': 'Deleted'}) # Cooperation Cases @bp.route('/cases', methods=['GET']) def get_cases(): section = request.args.get('section') category_id = request.args.get('category_id') query = CooperationCase.query if section: query = query.filter_by(section=section) if category_id: query = query.filter_by(category_id=category_id) items = query.all() return jsonify([{ 'id': i.id, 'title': i.title, 'image_url': i.image_url, 'description': i.description, 'section': i.section, 'category_id': i.category_id, 'category_name': i.category.name if i.category else None } for i in items]) @bp.route('/cases', methods=['POST']) @jwt_required() def create_case(): data = request.get_json() item = CooperationCase( title=data['title'], image_url=data.get('image_url'), description=data.get('description'), section=data['section'], category_id=data.get('category_id') ) db.session.add(item) db.session.commit() return jsonify({'message': 'Created', 'id': item.id}), 201 @bp.route('/cases/', methods=['PUT']) @jwt_required() def update_case(id): item = CooperationCase.query.get_or_404(id) data = request.get_json() item.title = data.get('title', item.title) item.image_url = data.get('image_url', item.image_url) item.description = data.get('description', item.description) item.section = data.get('section', item.section) item.category_id = data.get('category_id', item.category_id) db.session.commit() return jsonify({'message': 'Updated'}) @bp.route('/cases/', methods=['DELETE']) @jwt_required() def delete_case(id): item = CooperationCase.query.get_or_404(id) db.session.delete(item) db.session.commit() return jsonify({'message': 'Deleted'}) # News @bp.route('/news', methods=['GET']) def get_news(): items = News.query.order_by(News.publish_time.desc()).all() return jsonify([{ 'id': i.id, 'title': i.title, 'image_url': i.image_url, 'author': i.author, 'publish_time': i.publish_time, 'created_at': i.created_at } for i in items]) @bp.route('/news/', methods=['GET']) def get_news_detail(id): item = News.query.get_or_404(id) return jsonify({ 'id': item.id, 'title': item.title, 'content': item.content, 'image_url': item.image_url, 'author': item.author, 'publish_time': item.publish_time, 'created_at': item.created_at }) @bp.route('/news', methods=['POST']) @jwt_required() def create_news(): data = request.get_json() item = News( title=data['title'], content=data.get('content'), image_url=data.get('image_url'), author=data.get('author') ) db.session.add(item) db.session.commit() return jsonify({'message': 'Created', 'id': item.id}), 201 @bp.route('/news/', methods=['PUT']) @jwt_required() def update_news(id): item = News.query.get_or_404(id) data = request.get_json() item.title = data.get('title', item.title) item.content = data.get('content', item.content) item.image_url = data.get('image_url', item.image_url) item.author = data.get('author', item.author) db.session.commit() return jsonify({'message': 'Updated'}) @bp.route('/news/', methods=['DELETE']) @jwt_required() def delete_news(id): item = News.query.get_or_404(id) db.session.delete(item) db.session.commit() return jsonify({'message': 'Deleted'}) # Development History @bp.route('/development-history', methods=['GET']) def get_development_history(): items = DevelopmentHistory.query.order_by(DevelopmentHistory.year.desc()).all() return jsonify([{'id': i.id, 'year': i.year, 'title': i.title, 'description': i.description} for i in items]) @bp.route('/development-history', methods=['POST']) @jwt_required() def create_development_history(): data = request.get_json() item = DevelopmentHistory( year=data['year'], title=data['title'], description=data.get('description') ) db.session.add(item) db.session.commit() return jsonify({'message': 'Created', 'id': item.id}), 201 @bp.route('/development-history/', methods=['PUT']) @jwt_required() def update_development_history(id): item = DevelopmentHistory.query.get_or_404(id) data = request.get_json() item.year = data.get('year', item.year) item.title = data.get('title', item.title) item.description = data.get('description', item.description) db.session.commit() return jsonify({'message': 'Updated'}) @bp.route('/development-history/', methods=['DELETE']) @jwt_required() def delete_development_history(id): item = DevelopmentHistory.query.get_or_404(id) db.session.delete(item) db.session.commit() return jsonify({'message': 'Deleted'}) # Honors @bp.route('/honors', methods=['GET']) def get_honors(): items = Honor.query.all() return jsonify([{'id': i.id, 'title': i.title, 'image_url': i.image_url} for i in items]) @bp.route('/honors', methods=['POST']) @jwt_required() def create_honor(): data = request.get_json() item = Honor( title=data['title'], image_url=data.get('image_url') ) db.session.add(item) db.session.commit() return jsonify({'message': 'Created', 'id': item.id}), 201 @bp.route('/honors/', methods=['PUT']) @jwt_required() def update_honor(id): item = Honor.query.get_or_404(id) data = request.get_json() item.title = data.get('title', item.title) item.image_url = data.get('image_url', item.image_url) db.session.commit() return jsonify({'message': 'Updated'}) @bp.route('/honors/', methods=['DELETE']) @jwt_required() def delete_honor(id): item = Honor.query.get_or_404(id) db.session.delete(item) db.session.commit() return jsonify({'message': 'Deleted'}) # Company Info @bp.route('/company-info', methods=['GET']) def get_company_info(): info = CompanyInfo.query.first() if not info: return jsonify({}) return jsonify({ 'id': info.id, 'intro_content': info.intro_content, 'intro_image_url': info.intro_image_url, 'vision': info.vision, 'mission': info.mission, 'values': info.values, 'phone': info.phone, 'email': info.email, 'qrcode_url': info.qrcode_url }) @bp.route('/company-info', methods=['POST', 'PUT']) @jwt_required() def update_company_info(): info = CompanyInfo.query.first() data = request.get_json() if not info: info = CompanyInfo() db.session.add(info) info.intro_content = data.get('intro_content', info.intro_content) info.intro_image_url = data.get('intro_image_url', info.intro_image_url) info.vision = data.get('vision', info.vision) info.mission = data.get('mission', info.mission) info.values = data.get('values', info.values) info.phone = data.get('phone', info.phone) info.email = data.get('email', info.email) info.qrcode_url = data.get('qrcode_url', info.qrcode_url) db.session.commit() return jsonify({'message': 'Updated'})