Missing message for key "index.title"

本文介绍了如何在Struts框架中正确配置ApplicationResources.properties文件,确保国际化消息资源能够被正常加载。通过在struts-config.xml及web.xml中指定路径,解决找不到消息资源的问题。

Missing message for key "index.title"

                                      

问题是找不ApplicationResources.properties
或者:Cannot find message resources under key org.apache.struts.action.MESSAGE
问题是找不ApplicationResources.properties
这个要在文件:struts-config 中设置
如:ApplicationResources.properties放在classes/book的文件下,就可以设如下:
</action-mappings>
<message-resources parameter="book/ApplicationResources"/>
</struts-config>

在web.xml中
<init-param>
<param-name>application</param-name>
<param-value>ApplicationResources</param-value>
</init-param>

 
我看到项目里有一个这样的js文件,我还需要配置这个dialog吗,如果不需要,怎么使用。 /********************************** * @FilePath: naiveTools.js * @Author: Ronnie Zhang * @LastEditor: Ronnie Zhang * @LastEditTime: 2023/12/04 22:45:20 * @Email: zclzone@outlook.com * Copyright © 2023 Ronnie Zhang(大脸怪) | https://isme.top **********************************/ import * as NaiveUI from 'naive-ui' import { useAppStore } from '@/store' import { isNullOrUndef } from '@/utils' export function setupMessage(NMessage) { class Message { static instance constructor() { // 单例模式 if (Message.instance) return Message.instance Message.instance = this this.message = {} this.removeTimer = {} } removeMessage(key, duration = 5000) { this.removeTimer[key] && clearTimeout(this.removeTimer[key]) this.removeTimer[key] = setTimeout(() => { this.message[key]?.destroy() }, duration) } destroy(key, duration = 200) { setTimeout(() => { this.message[key]?.destroy() }, duration) } showMessage(type, content, option = {}) { if (Array.isArray(content)) { return content.forEach(msg => NMessage[type](msg, option)) } if (!option.key) { return NMessage[type](content, option) } const currentMessage = this.message[option.key] if (currentMessage) { currentMessage.type = type currentMessage.content = content } else { this.message[option.key] = NMessage[type](content, { ...option, duration: 0, onAfterLeave: () => { delete this.message[option.key] }, }) } this.removeMessage(option.key, option.duration) } loading(content, option) { this.showMessage('loading', content, option) } success(content, option) { this.showMessage('success', content, option) } error(content, option) { this.showMessage('error', content, option) } info(content, option) { this.showMessage('info', content, option) } warning(content, option) { this.showMessage('warning', content, option) } } return new Message() } export function setupDialog(NDialog) { NDialog.confirm = function (option = {}) { const showIcon = !isNullOrUndef(option.title) return NDialog[option.type || 'warning']({ showIcon, positiveText: '确定', negativeText: '取消', onPositiveClick: option.confirm, onNegativeClick: option.cancel, onMaskClick: option.cancel, ...option, }) } return NDialog } export function setupNaiveDiscreteApi() { const appStore = useAppStore() const configProviderProps = computed(() => ({ theme: appStore.isDark ? NaiveUI.darkTheme : undefined, themeOverrides: useAppStore().naiveThemeOverrides, })) const { message, dialog, notification, loadingBar } = NaiveUI.createDiscreteApi( ['message', 'dialog', 'notification', 'loadingBar'], { configProviderProps }, ) window.$loadingBar = loadingBar window.$notification = notification window.$message = setupMessage(message) window.$dialog = setupDialog(dialog) }
最新发布
10-23
from flask import Flask, request, jsonify, make_response from flask_sqlalchemy import SQLAlchemy from music21 import converter, note, stream, pitch import datetime from werkzeug.security import generate_password_hash, check_password_hash import re from functools import wraps app = Flask(__name__) # 需自行修改数据库连接信息 app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///music_app.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) # 用户模型 class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) password = db.Column(db.String(120), nullable=False) role = db.Column(db.String(20), nullable=False) # 'teacher' or 'student' def set_password(self, password): # 密码强度校验 if not re.match(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$', password): raise ValueError("Password must be at least 8 characters long and contain at least one uppercase letter, one lowercase letter, and one digit.") self.password = generate_password_hash(password) def check_password(self, password): return check_password_hash(self.password, password) # 作业模型 class Assignment(db.Model): id = db.Column(db.Integer, primary_key=True) teacher_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) title = db.Column(db.String(200), nullable=False) content = db.Column(db.Text, nullable=False) deadline = db.Column(db.DateTime, nullable=False) answer = db.Column(db.Text, nullable=False) assignment_type = db.Column(db.String(50), nullable=False) # 新增作业类型字段 # 学生提交作业模型 class Submission(db.Model): id = db.Column(db.Integer, primary_key=True) student_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) assignment_id = db.Column(db.Integer, db.ForeignKey('assignment.id'), nullable=False) answer = db.Column(db.Text, nullable=False) score = db.Column(db.Float) # 权限验证装饰器 def token_required(f): @wraps(f) def decorated(*args, **kwargs): token = None if 'x-access-token' in request.headers: token = request.headers['x-access-token'] if not token: return jsonify({'message': 'Token is missing!'}), 401 try: user = User.query.filter_by(id=token).first() if not user: return jsonify({'message': 'Invalid token!'}), 401 except: return jsonify({'message': 'Invalid token!'}), 401 return f(user, *args, **kwargs) return decorated # 注册接口 @app.route('/register', methods=['POST']) def register(): data = request.get_json() username = data.get('username') password = data.get('password') role = data.get('role') if not username or not password or not role: return jsonify({"message": "Missing required fields"}), 400 if User.query.filter_by(username=username).first(): return jsonify({"message": "Username already exists"}), 400 new_user = User(username=username, role=role) try: new_user.set_password(password) except ValueError as e: return jsonify({"message": str(e)}), 400 db.session.add(new_user) db.session.commit() return jsonify({"message": "User registered successfully"}), 201 # 登录接口 @app.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): return jsonify({"message": "Login successful", "role": user.role, "x-access-token": user.id}), 200 else: return jsonify({"message": "Invalid username or password"}), 401 # 老师布置作业接口 @app.route('/assignments', methods=['POST']) @token_required def create_assignment(user): if user.role != 'teacher': return jsonify({"message": "Only teachers can create assignments"}), 403 data = request.get_json() teacher_id = user.id title = data.get('title') content = data.get('content') deadline_str = data.get('deadline') answer = data.get('answer') assignment_type = data.get('assignment_type') # 获取作业类型 if not title or not content or not deadline_str or not answer or not assignment_type: return jsonify({"message": "Missing required fields"}), 400 try: deadline = datetime.datetime.strptime(deadline_str, '%Y-%m-%d %H:%M:%S') except ValueError: return jsonify({"message": "Invalid deadline format. Use 'YYYY-MM-DD HH:MM:SS'"}), 400 new_assignment = Assignment(teacher_id=teacher_id, title=title, content=content, deadline=deadline, answer=answer, assignment_type=assignment_type) db.session.add(new_assignment) db.session.commit() return jsonify({"message": "Assignment created successfully"}), 201 # 学生提交作业接口 @app.route('/submissions', methods=['POST']) @token_required def submit_assignment(user): if user.role != 'student': return jsonify({"message": "Only students can submit assignments"}), 403 data = request.get_json() student_id = user.id assignment_id = data.get('assignment_id') answer = data.get('answer') if not assignment_id or not answer: return jsonify({"message": "Missing required fields"}), 400 assignment = Assignment.query.get(assignment_id) if not assignment: return jsonify({"message": "Assignment not found"}), 404 if datetime.datetime.now() > assignment.deadline: return jsonify({"message": "Assignment deadline has passed"}), 400 # 重复提交控制 existing_submission = Submission.query.filter_by(student_id=student_id, assignment_id=assignment_id).first() if existing_submission: return jsonify({"message": "You have already submitted this assignment"}), 400 # 自动批阅 score = 0 if answer == assignment.answer: score = 100 new_submission = Submission(student_id=student_id, assignment_id=assignment_id, answer=answer, score=score) db.session.add(new_submission) db.session.commit() musicxml, _ = convert_and_grade(answer, assignment.answer) return jsonify({"message": "Assignment submitted successfully", "score": score, "musicxml": musicxml}), 201 # 老师查看学生作业情况接口 @app.route('/teachers/<int:teacher_id>/submissions', methods=['GET']) @token_required def view_submissions(user, teacher_id): if user.role != 'teacher' or user.id != teacher_id: return jsonify({"message": "You are not authorized to view these submissions"}), 403 page = request.args.get('page', 1, type=int) per_page = request.args.get('per_page', 10, type=int) assignments = Assignment.query.filter_by(teacher_id=teacher_id).paginate(page=page, per_page=per_page, error_out=False) submissions = [] for assignment in assignments.items: sub_list = Submission.query.filter_by(assignment_id=assignment.id).all() for sub in sub_list: student = User.query.get(sub.student_id) submissions.append({ "assignment_title": assignment.title, "student_username": student.username, "answer": sub.answer, "score": sub.score }) return jsonify(submissions), 200 # 学生查看自己的作业/提交记录接口 @app.route('/students/<int:student_id>/submissions', methods=['GET']) @token_required def view_student_submissions(user, student_id): if user.role != 'student' or user.id != student_id: return jsonify({"message": "You are not authorized to view these submissions"}), 403 page = request.args.get('page', 1, type=int) per_page = request.args.get('per_page', 10, type=int) submissions = Submission.query.filter_by(student_id=student_id).paginate(page=page, per_page=per_page, error_out=False) result = [] for sub in submissions.items: assignment = Assignment.query.get(sub.assignment_id) result.append({ "assignment_title": assignment.title, "answer": sub.answer, "score": sub.score }) return jsonify(result), 200 # 简谱转五线谱并批阅(扩展支持高低音和休止符) def convert_and_grade(jianpu, answer): try: s = stream.Stream() for note_str in jianpu.split(): if note_str == '0': # 处理休止符 n = note.Rest() else: # 处理高低音,这里简单示例,实际可能需要更复杂处理 # 假设高音用 '+' 后缀,低音用 '-' 后缀 if note_str.endswith('+'): n = note.Note(note_str[:-1]) n.octave += 1 elif note_str.endswith('-'): n = note.Note(note_str[:-1]) n.octave -= 1 else: n = note.Note(note_str) s.append(n) # 简单评分逻辑,可根据需求扩展 correct_count = sum([1 for i, j in zip(jianpu.split(), answer.split()) if i == j]) total_count = len(answer.split()) score = (correct_count / total_count) * 100 if total_count > 0 else 0 return s.write('musicxml'), score except Exception as e: return None, 0 # 老师查询作业接口,可按类型分类 @app.route('/teachers/<int:teacher_id>/assignments', methods=['GET']) @token_required def view_assignments(user, teacher_id): if user.role != 'teacher' or user.id != teacher_id: return jsonify({"message": "You are not authorized to view these assignments"}), 403 assignment_type = request.args.get('assignment_type') if assignment_type: assignments = Assignment.query.filter_by(teacher_id=teacher_id, assignment_type=assignment_type).all() else: assignments = Assignment.query.filter_by(teacher_id=teacher_id).all() result = [] for assignment in assignments: result.append({ "id": assignment.id, "title": assignment.title, "content": assignment.content, "deadline": assignment.deadline.strftime('%Y-%m-%d %H:%M:%S'), "answer": assignment.answer, "assignment_type": assignment.assignment_type }) return jsonify(result), 200 # 成绩统计接口 @app.route('/teachers/<int:teacher_id>/statistics', methods=['GET']) @token_required def view_statistics(user, teacher_id): if user.role != 'teacher' or user.id != teacher_id: return jsonify({"message": "You are not authorized to view these statistics"}), 403 assignments = Assignment.query.filter_by(teacher_id=teacher_id).all() total_students = User.query.filter_by(role='student').count() total_assignments = len(assignments) total_submissions = 0 average_score = 0 for assignment in assignments: sub_list = Submission.query.filter_by(assignment_id=assignment.id).all() total_submissions += len(sub_list) scores = [sub.score for sub in sub_list] if scores: average_score += sum(scores) / len(scores) if total_assignments > 0: average_score /= total_assignments return jsonify({ "total_students": total_students, "total_assignments": total_assignments, "total_submissions": total_submissions, "average_score": average_score }), 200 if __name__ == '__main__': with app.app_context(): db.create_all() app.run(debug=True)把上面的代码按照我下面的要求修改,如果你一次性写不完分2下写给我,一、学生端功能闭环(避免漏操作) 1. 新增“未提交作业查询接口”:学生能查看所有“未截止且未提交”的作业,按截止时间倒序排序(优先显示快截止的),避免漏做。需关联 Assignment 和 Submission 表,筛选“学生未提交”的作业。 2. 提交作业支持“重新提交”:当前重复提交直接拦截,可改为允许覆盖(需提示“重新提交会覆盖原分数”),满足学生修改答案的需求,只需在 submit_assignment 接口中,若存在旧提交则更新 answer 和 score,而非创建新记录。 二、老师端教学辅助(提升管理效率) 1. 作业详情补充“提交率统计”:在老师查看作业列表(view_assignments)时,增加“已提交人数/总学生数”“提交率”字段(如“30/50,60%”),方便老师快速掌握作业完成情况。 2. 新增“人工复评接口”:老师可修改系统评分并添加评语,需在 Submission 表加 teacher_comment 字段,同时新增接口允许老师传入 submission_id、new_score、comment 进行更新。 三、数据与体验细节(降低使用门槛) 1. MusicXML返回优化:当前 convert_and_grade 可能返回 None,需在接口中判断,若为 None 则返回“简谱格式错误,无法生成五线谱”的友好提示,避免前端接收异常数据。 2. 作业内容支持“音频链接存储”:当前 Assignment.content 可存储音频文件路径(如 /audio/melody1.mid),需新增“获取作业音频接口”(如 /assignments/<<int:assignment_id>/audio),返回音频文件流,学生做题时可直接播放(无需手动上传)。 3. 接口返回“格式化时间”:所有涉及时间的字段(如作业截止时间、提交时间),统一返回格式化字符串(如 2025-12-31 23:59:59),避免前端处理 datetime 类型数据出错。 四、部署前安全收尾(避免线上风险) 1. 关闭Debug模式:线上部署时需将 app.run(debug=True) 改为 app.run(debug=False),并配置 app.config['SECRET_KEY'](随机字符串),避免暴露代码和敏感信息。 2. 音频文件权限控制:若后端托管音频文件,需在“获取音频接口”中加Token校验,确保只有已登录用户能访问,避免音频文件被非法下载。
10-13
Thanks to your work so far, the library now has a functioning system. However, librarians have reported that some records in the CSV files are corrupted with invalid values. This has caused misbehaviour in the system, sometimes even crashing during busy exam periods, creating unnecessary stress for students. In real-world software engineering, robustness and correctness are just as important as functionality. Programs must gracefully handle unexpected situations and invalid inputs without failing. Two key approaches developers use are: Assertions: Internal checks that validate assumptions made by the programmer (e.g., "This variable should never be negative"). Assertions are mainly used during development and debugging. Defensive programming: Validates inputs and usage patterns to prevent invalid or unexpected behaviour at runtime. This includes checking for correct types, value ranges, and providing helpful error messages when something goes wrong. Description In this task, you will extend your library system by adding custom error handling to make it more robust. Python already raises built-in errors, but here you must define and use custom exceptions (in custom_errors.py) to handle library-specific error conditions. Building upon Task 3, update your user.py and book.py modules to handle invalid input, and modify task4.py to handle exceptions gracefully so that the system does not crash. You must ensure that this system is: Correct: Through use of assert to validate assumptions in your logic. Safe: Through defensive programming techniques that prevent invalid inputs (e.g. wrong types, negative amounts). In this task we will be using custom errors as python will already raise some of these errors when we execute invalid code. Our new errors are located in cusom_errors.py. You must use these custom errors, please see rubric for related penalties in this task. After auditing the CSV data, the librarian has introduced new validation rules to be applied in addition to the requirements described in Tasks 1–3. These rules strengthen data quality and prevent corrupted records from entering the system. Always include a helpful and descriptive error message when raising errors. Doing so contributes to the readability and overall quality of your assignment. Users Every user must have a password. Passwords cannot be empty. Every word in a user's name must contain only alphabetic characters. Numbers, symbols, and special characters are not allowed. Department is mandatory for students and staff, but must remain empty for other users. The only valid departments are: IT, Business, Arts, Science, Engineering, Education, Medicine and Library. Books The library only recognizes two valid book types: physical and online. The following fields are required for all books: Title, Author, Year Each book may have at most 5 keywords. Each word in keywords must consist of letters and numbers only. The only allowed special character is the hyphen (-). Loans Every loan record must be associated with an existing user and an existing book. The due date is a required field and cannot be left empty. Defensive Programming The following exceptions are provided to you in custom_errors.py: CustomTypeError: A value is the wrong type (e.g. a string instead of a float or int). CustomValueError: A value is of the correct type but invalid (e.g. negative copies). CustomDateError: Raised when a date is in the wrong format or when the date logic is invalid (e.g., borrow date occurs in the future). MissingRequiredFieldError: Raised when a required field is missing. UserNotFoundError or BookNotFoundError: Raised when a loan references a user or book that does not exist. CustomOperationError : Raised when an invalid borrow or return action is attempted. CustomLimitError: Raised when a user exceeds their quota or borrowing limit. CustomKeyError: Occurs when you try to access a key in the dictionary that doesn't exist.
10-18
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值