当前位置:文档之家› 学习管理系统源代码v1.0

学习管理系统源代码v1.0

<?phpsession_cache_limiter('none');session_start();//print_r($_SESSION);$path = "../libraries/";/** The configuration file.*/require_once $path."configuration.php";header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the pasttry {$currentUser = EfrontUser :: checkUserAccess();$smarty -> assign("T_CURRENT_USER", $currentUser);} catch (Exception $e) {if ($e -> getCode() == EfrontUserException :: USER_NOT_LOGGED_IN) {setcookie('c_request', htmlspecialchars_decode(http_build_query($_GET)), time() + 300, false, false, false, true);}eF_redirect("index.php?ctg=expired");exit;}if ($GLOBALS['currentTheme'] -> options['sidebar_interface']) {header("location:".$_SESSION['s_type'].".php".($_SERVER['QUERY_STRING'] ? "?".$_SERVER['QUERY_STRING'] : ''));//$smarty -> assign("T_SIDEBAR_URL", ""); // set an empty source for horizontal sidebars //$smarty -> assign("T_SIDEFRAME_WIDTH", 0);}$smarty -> assign("T_SIDEBAR_MODE", $GLOBALS['currentTheme'] -> options['sidebar_interface']); if ($GLOBALS['currentTheme'] -> options['sidebar_width']) {$smarty -> assign("T_SIDEFRAME_WIDTH", $GLOBALS['currentTheme'] -> options['sidebar_width']); } else {$smarty -> assign("T_SIDEFRAME_WIDTH", 175);}if (isset($_SESSION['previousSideUrl'])) {$smarty -> assign("T_SIDEBAR_URL", $_SESSION['previousSideUrl']);}if (isset($_GET['dashboard']) && $_SESSION['s_type'] == "administrator") {$smarty -> assign("T_MAIN_URL", $_SESSION['s_type'].".php?ctg=personal&user=". $_GET['dashboard']);} elseif (isset($_GET['dashboard']) || $_GET['ctg'] == 'personal') {$smarty -> assign("T_MAIN_URL", $_SESSION['s_type'].".php?ctg=personal");} elseif (isset($_GET['ctg']) || $_GET['ctg'] == 'landing_page') {$smarty -> assign("T_MAIN_URL", $_SESSION['s_type'].".php?ctg=landing_page");} else {if (isset($_SESSION['previousMainUrl'])) {$smarty -> assign("T_MAIN_URL", $_SESSION['previousMainUrl']);}}if (isset($_SESSION['s_type'])) {$smarty -> display($_SESSION['s_type']."page.tpl");} else {eF_redirect("index.php");}><?phpsession_cache_limiter('none');session_start();$path = "../libraries/";include_once $path."configuration.php";header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the pasttry {if (isset($_GET['login']) && $_SESSION['s_login']) {$currentUser = EfrontUserFactory::factory($_SESSION['s_login']);$additionalAccounts = unserialize($currentUser -> user['additional_accounts']);if (in_array($_GET['login'], $additionalAccounts)) {$newUser = EfrontUserFactory::factory($_GET['login']);$lessonID = $_SESSION['s_lessons_ID'];$courseID = $_SESSION['s_courses_ID'];$currentUser -> logout(session_id());$newUser -> login($newUser -> user['password'], true);if ($_SESSION['s_type'] != 'administrator' && $lessonID) {if ($courseID) {setcookie('c_request',$_SESSION['s_type'].'.php?lessons_ID='.$lessonID."&from_course=".$courseID, time() + 300, false, false, false, true);} else {setcookie('c_request', $_SESSION['s_type'].'.php?lessons_ID='.$lessonID, time() + 300);}}unset($_SESSION['referer']);$redirectPage = $GLOBALS['configuration']['login_redirect_page'];if ($redirectPage == "user_dashboard" && $newUser -> user['user_type'] != "administrator") { echo 'userpage.php?ctg=personal';}elseif (strpos($redirectPage, "module") !== false) {echo 'userpage.php?ctg=landing_page';} else {echo 'userpage.php';}}}} catch (Exception $e) {handleAjaxExceptions($e);}><?phpsession_cache_limiter('none');session_start();$path = "../libraries/";include_once $path."configuration.php";header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the pasttry {$languages = EfrontSystem::getLanguages(true);if (isset($_GET['lessons_ID']) && eF_checkParameter($_GET['lessons_ID'], 'id')) {$lesson = new EfrontLesson($_GET['lessons_ID']);$lessonInformation = $lesson -> getInformation();//$lessonInformation['language'] = $languages[$lesson -> lesson['languages_NAME']];if ($lessonInformation['professors']) {foreach ($lessonInformation['professors'] as $value) {$professorsString[] = formatLogin($value['login']);}$lessonInformation['professors'] = implode(", ", $professorsString);}$lesson -> lesson['price'] ? $priceString = formatPrice($lesson -> lesson['price'], array($lesson -> options['recurring'], $lesson -> options['recurring_duration']), true) : $priceString = false; $lessonInformation['price_string'] = $priceString;// if (!$lessonInformation['price']) {// unset($lessonInformation['price_string']);// }try {if ($_GET['from_course'] && eF_checkParameter($_GET['from_course'], 'id')) {$course = new EfrontCourse($_GET['from_course']);$schedule = $course -> getLessonScheduleInCourse($lesson);$lessonInformation['from_timestamp'] = $schedule['start_date'];$lessonInformation['to_timestamp'] = $schedule['end_date'];}} catch (Exception $e) {};if ($lesson -> lesson['course_only']) {$lessonCourses = $lesson -> getCourses();if (!empty($lessonCourses)) {foreach ($lessonCourses as $value) {$lessonInformation['lesson_courses'][] = $value['name'];}$lessonInformation['lesson_courses'] = implode(", ", $lessonInformation['lesson_courses']); }}foreach ($lessonInformation as $key => $value) {if ($value) {$value = str_replace ("\n","<br />", $value);switch ($key) {case 'language' : $GLOBALS['configuration']['onelanguage'] OR $tooltipInfo[] = '<div class = "infoEntry"><span>'._LANGUAGE."</span><span>: $languages[$value]</span></div>"; break;case 'professors' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._PROFESSORS."</span><span>: $value</span></div>"; break;case 'content' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._CONTENTUNITS."</span><span>: $value</span></div>"; break;case 'tests' : $GLOBALS['configuration']['disable_tests'] != 1 ? $tooltipInfo[] = '<div class = "infoEntry"><span>'._TESTS."</span><span>: $value</span></div>" : null; break;case 'projects' : $GLOBALS['configuration']['disable_projects'] != 1 ? $tooltipInfo[] = '<divclass = "infoEntry"><span>'._PROJECTS."</span><span>: $value</span></div>" : null; break;case 'course_dependency' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._DEPENDSON."</span><span>: $value</span></div>"; break;case 'from_timestamp' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._AVAILABLEFROM."</span><span>: ".formatTimestamp($value, 'time_nosec')."</span></div>";break;case 'to_timestamp' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._AVAILABLEUNTIL."</span><span>: ".formatTimestamp($value, 'time_nosec')."</span></div>"; break;case 'general_description': $tooltipInfo[] = '<div class = "infoEntry"><span>'._DESCRIPTION."</span><span>: $value</span></div>"; break;case 'assessment' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._ASSESSMENT."</span><span>: $value</span></div>"; break;case 'objectives' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._OBJECTIVES."</span><span>: $value</span></div>"; break;case 'lesson_topics' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._LESSONTOPICS."</span><span>: $value</span></div>"; break;case 'resources' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._RESOURCES."</span><span>: $value</span></div>"; break;case 'other_info' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._OTHERINFO."</span><span>: $value</span></div>"; break;case 'price_string' : !$lesson -> lesson['course_only'] ? $tooltipInfo[] = '<div class = "infoEntry"><span>'._PRICE."</span><span>: $value</span></div>" : null; break;case 'lesson_courses' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._PARTOFCOURSES."</span><span>: $value</span></div>"; break;default: break;}}}if ($string = implode("", $tooltipInfo)) {echo '<html '.($GLOBALS['rtl'] ? 'dir = "rtl"' : '').' >'.$string.'</html>';} else {echo _NODATAFOUND;}}if (isset($_GET['courses_ID']) && eF_checkParameter($_GET['courses_ID'], 'id')) {$course = new EfrontCourse($_GET['courses_ID']);$courseInformation = $course -> getInformation();if ($courseInformation['professors']) {foreach ($courseInformation['professors'] as $value) {$professorsString[] = formatLogin($value['login']);}$courseInformation['professors'] = implode(", ", $professorsString);}$course -> course['price'] ? $priceString = formatPrice($course -> course['price'], array($course -> options['recurring'], $course -> options['recurring_duration']), true) : $priceString = false; $courseInformation['price_string'] = $priceString;foreach ($courseInformation as $key => $value) {if ($value) {$value = str_replace ("\n","<br />", $value);switch ($key) {case 'language' : $GLOBALS['configuration']['onelanguage'] OR $tooltipInfo[] = '<div class = "infoEntry"><span>'._LANGUAGE."</span><span>: $languages[$value]</span></div>"; break;case 'professors' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._PROFESSORS."</span><span>: $value</span></div>"; break;case 'lessons_number' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._LESSONS."</span><span>: $value</span></div>"; break;case 'instances' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._COURSEINSTANCES."</span><span>: $value</span></div>"; break;case 'general_description': $tooltipInfo[] = '<div class = "infoEntry"><span>'._DESCRIPTION."</span><span>: $value</span></div>"; break;case 'assessment' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._ASSESSMENT."</span><span>: $value</span></div>"; break;case 'objectives' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._OBJECTIVES."</span><span>: $value</span></div>"; break;case 'lesson_topics' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._COURSETOPICS."</span><span>: $value</span></div>"; break;case 'resources' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._RESOURCES."</span><span>: $value</span></div>"; break;case 'other_info' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._OTHERINFO."</span><span>: $value</span></div>"; break;case 'price_string' : $tooltipInfo[] = '<div class = "infoEntry"><span>'._PRICE."</span><span>: $value</span></div>"; break;default: break;}}}if ($course -> course['depends_on']) {try {$dependsOn = new EfrontCourse($course -> course['depends_on']);$tooltipInfo[] = '<div class = "infoEntry"><span>'._DEPENDSON."</span><span>:".$dependsOn->course['name']."</span></div>";} catch (Exception $e) {}}if ($string = implode("", $tooltipInfo)) {echo $string;} else {echo _NODATAFOUND;}}// For eFront socialif (isset($_GET['common_lessons']) && isset($_GET['user1']) && isset($_GET['user2']) && eF_checkParameter($_GET['user1'], 'login') && eF_checkParameter($_GET['user2'], 'login')) {$user1 = EfrontUserFactory::factory($_GET['user1']);if ($user1->getType() != "administrator") {$common_lessons = $user1 -> getCommonLessons($_GET['user2']);// pr($common_lessons);foreach ($common_lessons as $id => $lesson) {if (strlen($lesson['name'])>25) {$lesson['name'] = substr($lesson['name'],0,22) . "...";}$tooltipInfo[] = '<div class = "infoEntry"><span>'.$lesson['name']."</span><span></span></div>";}if ($string = implode("", $tooltipInfo)) {echo $string;} else {echo _NODATAFOUND;}} else {echo _NODATAFOUND;}}} catch (Exception $e) {echo ($e -> getMessage().' ('.$e -> getCode().')'); //No ajax error handling here, since we want the info to appear in the popup}><?php/*** Respond to ajax query returing a list** @package eFront*/session_cache_limiter('none');session_start();header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past$path = "../libraries/";/** Configuration file.*/include_once $path."configuration.php";try {$currentUser = EfrontUser :: checkUserAccess();} catch (Exception $e) {echo "<script>parent.location = 'index.php?logout=true&message=".urlencode($e -> getMessage().' ('.$e -> getCode().')')."&message_type=failure'</script>"; //This way the frameset will revert back to single frame, and the annoying effect of 2 index.php, one in each frame, will not happenexit;}eF_checkParameter($_POST['preffix'], 'text') OR $_POST['preffix'] = '%';switch ($_GET['ask_type']) {case 'users': askUsers(); break;case 'tests': askTests(); break;case 'feedback': askFeedback(); break;case 'projects': askProjects(); break;case 'lesson': case 'lessons': askLessons(); break;case 'group' : case 'groups': askGroups(); break;case 'course': case 'courses': askCourses(); break;case 'branch': case 'branches': askBranches(); break;case 'skill': case 'skills': askSkills(); break;default: break;}function highlightSearch($search_results, $search_criteria, $bgcolor='Yellow'){$start_tag = '<span style="vertical-align:top;background-color: '.$bgcolor.'">';$end_tag = '</span>';$search_results = str_ireplace($search_criteria, $start_tag . $search_criteria . $end_tag, $search_results);return $search_results;}function askUsers() {// $_POST['preffix'] = "%"; // Useful for debuggingif (isset($_POST['preffix'])) {if (mb_strpos($_POST['preffix'], ";") === false) {$user = $_POST['preffix'];} else {$user = mb_substr(strrchr($_POST['preffix'], ";"), 1);}}//pr($_SESSION);$users = array();if (isset($user) && $user) {$preffix = $user;// Return active users for statistics:// - admins: all// - supervisors: all supervised (in Enterprise)// - professors: studentsif (isset($_GET['supervisors'])) {$users = eF_getTableData("users u, module_hcd_employee_works_at_branch wb", "distinct u.login,,u.surname,er_type,er_types_ID", "u.login=ers_LOGIN and wb.supervisor=1 and u.active = 1 and (login like '$preffix%' OR name like '$preffix%' OR surname like '$preffix%' OR user_type like '$preffix%')", "login");} elseif (!isset($_GET['messaging'])) {if ($_SESSION['s_type'] == "administrator") {$users = eF_getTableData("users", "login,name,surname,user_type,user_types_ID", "active = 1 and (login like '$preffix%' OR name like '$preffix%' OR surname like '$preffix%' OR user_type like '$preffix%')", "login");} else {// Get students of professor$user = EfrontUserFactory :: factory($_SESSION['s_login']);$students = $user -> getProfessorStudents();$logins = array();$size = sizeof($students);for ($i = 0; $i < $size; $i++) {if (!in_array($students[$i], $logins)){$logins[] = $students[$i];}}$logins[] = $_SESSION['s_login'];//pr($logins);$students_list = "'".implode("','", $logins)."'";$users = eF_getTableData("users", "login,name,surname,user_type,user_types_ID", "login IN ($students_list) AND (login like '$preffix%' OR name like '$preffix%' OR surname like '$preffix%' OR user_type like '$preffix%')", "login");}// Return active users for messaging:// - admins: all// - supervisors: all// - users: other users with common group, lesson, course (or branch in Enterprise)} else {if ($_SESSION['s_type'] == "administrator") {$users = eF_getTableData("users", "login,name,surname,user_type,user_types_ID", "active = 1 and (login like '$preffix%' OR name like '$preffix%' OR surname like '$preffix%')", "login");$users[] = array('login' => "[*]",'name' => _ALLUSERS, 'surname' => _ALLUSERS);} else {$currentUser = EfrontUserFactory::factory($_SESSION['s_login']);$grant_full_access = false;if (!$grant_full_access) { // Used for correct handling in Enterprise and non-Enterprise editions$myGroupsIds = array_keys($currentUser -> getGroups());//echo "Groups<BR><BR><BR>";pr($myGroupsIds);if (!empty($myGroupsIds)) {$result = eF_getTableDataFlat("users JOIN users_to_groups", "distinct users_LOGIN", "users.active = 1 and users.login = users_to_ers_LOGIN AND groups_ID IN ('" . implode("','", $myGroupsIds) ."')");$logins = $result['users_LOGIN'];}$myLessonsIds = array_keys($currentUser -> getLessons());//pr($result);echo "Lessons<BR><BR><BR>";pr($myLessonsIds);if (!empty($myLessonsIds)) {$result = eF_getTableDataFlat("users JOIN users_to_lessons", "distinct users_LOGIN", "users.active = 1 and users.archive=0 and users_to_lessons.archive=0 and users.login = users_to_ers_LOGIN AND lessons_ID IN ('" . implode("','", $myLessonsIds) ."')");$logins = array();foreach($result['users_LOGIN'] as $login) {if (!in_array($login, $logins)){$logins[] = $login;}}}$myCoursesIds = eF_getTableDataFlat("users_to_courses", "courses_ID", "archive = 0 andusers_LOGIN = '". $currentUser -> user['login']."'");$myCoursesIds = $myCoursesIds['courses_ID'];//echo "Courses<BR><BR><BR>";pr($myCoursesIds);if (!empty($myCoursesIds)) {$result = eF_getTableDataFlat("users JOIN users_to_courses", "distinct users_LOGIN", "users.active = 1 and users.login = users_to_ers_LOGIN AND users.archive=0 and users_to_courses.archive=0 AND courses_ID IN ('" . implode("','", $myCoursesIds) ."')");foreach($result['users_LOGIN'] as $login) {if (!in_array($login, $logins)){$logins[] = $login;}}}$related_users_list = "'".implode("','", $logins)."'";$users = eF_getTableData("users", "distinct login,name,surname,user_type,user_types_ID", "login IN (". $related_users_list . ") AND (login like '$preffix%' OR name like '$preffix%' OR surname like '$preffix%')", "login");} else {$users = eF_getTableData("users", "distinct login,name,surname,user_type,user_types_ID", "login like '$preffix%' OR name like '$preffix%' OR surname like '$preffix%'", "login");}}if($_SESSION['s_type'] == "professor"){$users[] = array('login' => "[*]",'name' => _MYSTUDENTS, 'surname' => _MYSTUDENTS, 'user_type' => '[*]');}//pr($users);}}$str = '<ul>';for ($k = 0; $k < sizeof($users); $k++){/*$hilogin = highlightSearch($users[$k]['login'], $preffix);$hiname = highlightSearch($users[$k]['name'], $preffix);$hisurname = highlightSearch($users[$k]['surname'], $preffix); */$hilogin = $users[$k]['login'];$hiname = $users[$k]['name'];$hisurname = $users[$k]['surname'];$hiusertype = $users[$k]['user_types_ID'] ? $users[$k]['user_types_ID'] : $users[$k]['user_type'];if ($users[$k]['login'] == '[*]') {$formattedLogins[$users[$k]['login']] = $hiname;} else {$formattedLogins[$users[$k]['login']] = formatLogin(false, array('login' => $hilogin, 'name' => $hiname, 'surname' => $hisurname, 'user_type' => $hiusertype));}//$str = $str.'<li id='.$users[$k]['login'].'>'.$formattedLogin.'</li>';}//changed for case that two users (without common appearance) returned but one of them have common appearance with a third user (#1741)if ($GLOBALS['configuration']['username_format_resolve']) {formatLogin($_SESSION['s_login']);foreach ($formattedLogins as $key => $value) {if (isset($GLOBALS['_usernames'][$key])) {$formattedLogins[$key] = $GLOBALS['_usernames'][$key];}}}for ($k = 0; $k < sizeof($users); $k++){$str = $str.'<li id='.$users[$k]['login'].'>'.$formattedLogins[$users[$k]['login']].'</li>'; }$str = $str.'</ul>';echo $str;}function askTests() {$preffix = $_POST['preffix'];$currentUser = EfrontUserFactory :: factory($_SESSION['s_login']);if ($_SESSION['s_type'] == "administrator"){$tests_info = eF_getTableDataFlat("tests t, lessons l, content c", "t.id, as test_name, as lesson_name, l.originating_course ","c.lessons_ID=l.id AND t.content_ID=c.id AND c.ctg_type='tests' AND t.active=1 and t.lessons_ID = l.id AND like '%$preffix%'", ""); $scorm_tests_info = eF_getTableDataFlat("content c, lessons l", "c.id, as test_name, as lesson_name, l.originating_course ","c.active=1 and c.lessons_ID = l.id AND like '%$preffix%' and c.ctg_type = 'scorm_test'", "");} else {$tests_info = eF_getTableDataFlat("tests t, users_to_lessons ul, lessons l", "t.id, as test_name, as lesson_name, l.originating_course ", "ul.archive=0 and (er_type = 'professor' OR er_type =".$currentUser->user['user_types_ID'].") AND t.active=1 and t.lessons_ID = l.id AND ers_LOGIN='".$_SESSION['s_login']."' and ul.lessons_ID=l.id AND like '%$preffix%'", "");$scorm_tests_info = eF_getTableDataFlat("content c, users_to_lessons ul, lessons l", "c.id, as test_name, as lesson_name, l.originating_course ", "ul.archive=0 and (er_type = 'professor' OR er_type =".$currentUser->user['user_types_ID'].") AND c.active=1 and c.lessons_ID = l.id AND ers_LOGIN='".$_SESSION['s_login']."' and ul.lessons_ID=l.id AND like '%$preffix%' and c.ctg_type = 'scorm_test'", "");$lessons = $currentUser -> getLessons(false,'professor'); //must return tests for lessons that he has a professor role$lessons = array_keys($lessons);if (!empty($lessons)) {$lessonsStr = implode(',', $lessons);$legalTests = eF_getTableDataFlat("tests t, content c","t.id","t.content_ID=c.id AND c.ctg_type!='feedback' AND t.lessons_ID IN ($lessonsStr)");$legalTestsId = $legalTests['id'];$legalScormTests = eF_getTableDataFlat("content","id","lessons_ID IN ($lessonsStr)");$legalScormTestsId = $legalScormTests['id'];}}$result = eF_getTableDataFlat("courses", "id, name");if (!empty($result)) {$courseNames = array_combine($result['id'], $result['name']);} else {$courseNames = array();}$info_array = array();for ($i = 0 ; $i < sizeof($tests_info['test_name']) ; $i ++){$hiname = highlightSearch($tests_info['test_name'][$i], $preffix);$path_string = $tests_info['lesson_name'][$i]."&nbsp;&raquo;&nbsp;".$hiname;if ($courseNames[$tests_info['originating_course'][$i]]) {$path_string = $courseNames[$tests_info['originating_course'][$i]].'&nbsp;&raquo;&nbsp;'.$path_string;}if (empty($legalTestsId) || in_array($tests_info['id'][$i], $legalTestsId)) {$info_array[] = array('id' => $tests_info['id'][$i],'name' => $tests_info['test_name'][$i],'path_string' =>$path_string);}}for ($i = 0 ; $i < sizeof($scorm_tests_info['test_name']) ; $i ++){$hiname = highlightSearch($scorm_tests_info['test_name'][$i], $preffix);$path_string = $scorm_tests_info['lesson_name'][$i]."&nbsp;&raquo;&nbsp;".$hiname;if ($courseNames[$scorm_tests_info['originating_course'][$i]]) {$path_string = $courseNames[$scorm_tests_info['originating_course'][$i]].'&nbsp;&raquo;&nbsp;'.$path_string; }if (empty($legalScormTestsId) || in_array($scorm_tests_info['id'][$i], $legalScormTestsId)) { $info_array[] = array('id' => $scorm_tests_info['id'][$i],'name' => $scorm_tests_info['test_name'][$i],'path_string' =>$path_string);}}。

相关主题