ModelSelection.vue 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. <template>
  2. <div class="model-container">
  3. <!-- 模型选择下拉菜单 -->
  4. <el-dropdown @command="handleModelTypeChange" trigger="click" :hide-on-click="true" style="margin-bottom: 5px">
  5. <span class="el-dropdown-link">
  6. {{ selectedModelTypeLabel }}<el-icon class="el-icon--right"><ArrowDown /></el-icon>
  7. </span>
  8. <template #dropdown>
  9. <el-dropdown-menu>
  10. <el-dropdown-item
  11. v-for="type in modelTypes"
  12. :key="type.value"
  13. :command="type.value"
  14. :disabled="selectedModelType === type.value"
  15. >
  16. {{ type.label }}
  17. </el-dropdown-item>
  18. </el-dropdown-menu>
  19. </template>
  20. </el-dropdown>
  21. <!-- 加载失败提示 -->
  22. <el-alert
  23. v-if="errorOccurred"
  24. :title="`加载数据失败: ${errorMessage}`"
  25. type="error"
  26. show-icon
  27. style="margin-bottom: 5px"
  28. />
  29. <!-- 动态加载的模型信息按表格显示 -->
  30. <el-table
  31. v-if="selectedModelType && filteredModels.length > 0 && !loading"
  32. :data="pagedFilteredModels"
  33. style="width: 100%"
  34. border
  35. height="calc(100vh - 300px)"
  36. >
  37. <el-table-column prop="ModelID" label="序号" min-width="80" />
  38. <el-table-column prop="Model_name" label="模型名称" min-width="180" />
  39. <el-table-column prop="Data_type" label="数据类型" min-width="120" />
  40. <el-table-column prop="Performance_score" label="性能评分" min-width="120" />
  41. <el-table-column prop="Created_at" label="创建时间" min-width="180" />
  42. <el-table-column label="操作" min-width="100">
  43. <template #default="scope">
  44. <el-button size="small" @click="selectModel(scope.row)">选择</el-button>
  45. </template>
  46. </el-table-column>
  47. </el-table>
  48. <!-- 分页控制 -->
  49. <div
  50. class="demo-pagination-block"
  51. v-if="selectedModelType && filteredModels.length > 0"
  52. style="text-align: center; margin-top: 20px;"
  53. >
  54. <el-pagination
  55. v-model:current-page="currentPage"
  56. v-model:page-size="pageSize"
  57. :page-sizes="[10, 20, 30, 40]"
  58. layout="total, sizes, prev, pager, next, jumper"
  59. :total="filteredModels.length"
  60. @size-change="handleSizeChange"
  61. @current-change="handleCurrentChange"
  62. />
  63. </div>
  64. <!-- 切换模型按钮 -->
  65. <div
  66. v-if="selectedModel && !loading"
  67. style="text-align: center; margin-top: 5px"
  68. >
  69. <el-button type="success" size="small" @click="switchModel">切换模型</el-button>
  70. </div>
  71. <!-- 当没有选择任何模型类型时显示提示信息 -->
  72. <div
  73. v-if="!selectedModelType && !loading && !errorOccurred"
  74. style="text-align: center; padding-top: 5px"
  75. >
  76. 请选择一个模型类型以查看详细信息。
  77. </div>
  78. <!-- 当筛选结果为空时显示提示信息 -->
  79. <div
  80. v-if="selectedModelType && filteredModels.length === 0 && !loading && !errorOccurred"
  81. style="text-align: center; padding-top: 5px"
  82. >
  83. 没有找到与所选模型类型匹配的数据。
  84. </div>
  85. </div>
  86. </template>
  87. <script lang="ts" setup>
  88. import { ref, onMounted, computed } from 'vue';
  89. import axios from 'axios';
  90. import { ElMessage } from 'element-plus';
  91. import { ArrowDown } from '@element-plus/icons-vue';
  92. import { table } from '@/API/menus';
  93. interface ModelData {
  94. ModelID: number;
  95. Model_name: string;
  96. Model_type: string;
  97. Created_at: string;
  98. Description: string;
  99. DatasetID: string;
  100. ModelFilePath: string;
  101. Data_type: string;
  102. Performance_score: number;
  103. MAE: number;
  104. RMSE: number;
  105. CV_score: string;
  106. }
  107. interface Dataset {
  108. id: any;
  109. name: string;
  110. description: string;
  111. type: string;
  112. count: number;
  113. status: string;
  114. uploadTime: string;
  115. selected: boolean;
  116. }
  117. const loading = ref(true);
  118. const allModels = ref<ModelData[]>([]);
  119. const rows = ref<Dataset[]>([]);
  120. const selectedModelType = ref<string>("");
  121. const selectedModelTypeLabel = ref<string>("请选择模型类型");
  122. const selectedModel = ref<ModelData | null>(null);
  123. const modelTypes = [
  124. { value: "reduce", label: "降酸模型(Reduce Model)" },
  125. { value: "reflux", label: "反酸模型(Reflux Model)" },
  126. ];
  127. // 分页相关的变量
  128. const currentPage = ref(1);
  129. const pageSize = ref(10);
  130. // 获取所有模型数据
  131. const fetchAllModels = async () => {
  132. try {
  133. const requestBody = { table: "Models" };
  134. const response = await table(requestBody);
  135. allModels.value = response.data.rows.map((row: any) => ({
  136. ...row,
  137. selected: false,
  138. }));
  139. } catch (error) {
  140. let errorMessageVal = "未知错误";
  141. if (error && typeof error === 'object' && 'message' in error) {
  142. errorMessageVal = (error as { message?: string }).message || errorMessageVal;
  143. }
  144. console.error("Error fetching data:", errorMessageVal);
  145. ElMessage.error("数据加载失败:" + errorMessageVal);
  146. errorOccurred.value = true;
  147. errorMessage.value = errorMessageVal;
  148. } finally {
  149. loading.value = false;
  150. }
  151. };
  152. // 获取所有数据集数据
  153. const fetchData = async () => {
  154. try {
  155. const response = await table({ table: 'Datasets' });
  156. return response.data.rows;
  157. } catch (error) {
  158. let errorMessageVal = '未知错误';
  159. if (error && typeof error === 'object' && 'message' in error) {
  160. errorMessageVal = (error as { message?: string }).message || errorMessageVal;
  161. }
  162. console.error('Error fetching data:', errorMessageVal);
  163. throw new Error(errorMessageVal); // 重新抛出带有详细信息的新错误
  164. }
  165. };
  166. // 加载数据集数据
  167. const LoadData = async () => {
  168. try {
  169. rows.value = (await fetchData()).map(
  170. (row: {
  171. Dataset_ID: any;
  172. Dataset_name: any;
  173. Dataset_description: any;
  174. Dataset_type: any;
  175. Row_count: any;
  176. Status: any;
  177. Uploaded_at: any;
  178. }) => ({
  179. id: row.Dataset_ID,
  180. name: row.Dataset_name,
  181. description: row.Dataset_description,
  182. type: row.Dataset_type,
  183. count: row.Row_count,
  184. status: row.Status,
  185. uploadTime: row.Uploaded_at,
  186. selected: false,
  187. })
  188. );
  189. } catch (error) {
  190. let errorMessageVal = '未知错误';
  191. if (error && typeof error === 'object' && 'message' in error) {
  192. errorMessageVal = (error as { message?: string }).message || errorMessageVal;
  193. }
  194. console.error('Error fetching data:', errorMessageVal);
  195. ElMessage.error('数据加载失败:' + errorMessageVal);
  196. errorOccurred.value = true;
  197. errorMessage.value = errorMessageVal;
  198. } finally {
  199. loading.value = false;
  200. }
  201. };
  202. // 根据选择的模型类型计算要展示的数据
  203. const filteredModels = computed(() => {
  204. if (!selectedModelType.value) return [];
  205. // 根据选定的模型类型(降酸或反酸)进行筛选
  206. return allModels.value.filter(m => m.Data_type === selectedModelType.value);
  207. });
  208. // 分页后的过滤数据
  209. const pagedFilteredModels = computed(() => {
  210. const start = (currentPage.value - 1) * pageSize.value;
  211. const end = start + pageSize.value;
  212. return filteredModels.value.slice(start, end);
  213. });
  214. // 过滤后的数据集数据
  215. const filteredRows = computed(() =>
  216. selectedModelType.value ? rows.value.filter((row) => row.type === selectedModelType.value) : []
  217. );
  218. // 分页后的过滤数据集数据
  219. const pagedFilteredRows = computed(() => {
  220. const start = (currentPage.value - 1) * pageSize.value;
  221. const end = start + pageSize.value;
  222. return filteredRows.value.slice(start, end);
  223. });
  224. const handleModelTypeChange = (value: string) => {
  225. selectedModelType.value = value;
  226. const selectedType = modelTypes.find(type => type.value === value);
  227. if (selectedType) {
  228. selectedModelTypeLabel.value = selectedType.label;
  229. ElMessage.success(`已切换到 ${selectedType.label}`);
  230. }
  231. selectedModel.value = null; // 清空已选中的模型
  232. currentPage.value = 1; // 当模型类型改变时重置当前页码
  233. };
  234. const selectModel = (model: ModelData) => {
  235. selectedModel.value = model;
  236. };
  237. // 分页事件处理
  238. const handleSizeChange = (val: number) => {
  239. pageSize.value = val;
  240. };
  241. const handleCurrentChange = (val: number) => {
  242. currentPage.value = val;
  243. };
  244. // 切换模型状态
  245. const switchModel = async () => {
  246. if (!selectedModel.value) {
  247. ElMessage.warning("请先选择一个模型");
  248. return;
  249. }
  250. try {
  251. await axios.post("https://127.0.0.1:5000/switch-model", {
  252. model_id: selectedModel.value.ModelID,
  253. model_name: selectedModel.value.Model_name,
  254. });
  255. ElMessage.success(`模型 ${selectedModel.value.Model_name} 切换成功`);
  256. selectedModel.value = null; // 清空已选中的模型
  257. } catch (error) {
  258. let message = "未知错误";
  259. if (error && typeof error === "object" && "message" in error) {
  260. message = (error as { message?: string }).message || message;
  261. }
  262. console.error("Failed to switch model:", message);
  263. ElMessage.error("模型切换失败:" + message);
  264. }
  265. };
  266. const errorOccurred = ref(false);
  267. const errorMessage = ref('');
  268. const selectedRows = ref<Dataset[]>([]);
  269. onMounted(() => {
  270. fetchAllModels();
  271. LoadData();
  272. });
  273. </script>
  274. <style scoped>
  275. .model-container {
  276. display: grid;
  277. gap: 10px;
  278. padding: 10px;
  279. background-color: #f9fafb;
  280. border-radius: 8px;
  281. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  282. height: 100%; /* 让容器高度占满父元素 */
  283. }
  284. .example-showcase .el-dropdown-link {
  285. cursor: pointer;
  286. color: var(--el-color-primary);
  287. display: flex;
  288. align-items: center;
  289. }
  290. /* 移除下拉菜单的边框 */
  291. .el-popper.is-light {
  292. border: none !important;
  293. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  294. }
  295. .el-table {
  296. width: 100%;
  297. margin-top: 10px;
  298. border-radius: 8px; /* 添加圆角 */
  299. }
  300. :deep( .el-table th) {
  301. background-color: #61e054 !important;
  302. color: #fff;
  303. }
  304. :deep( .el-table td),
  305. :deep( .el-table th) {
  306. padding: 8px 0;
  307. }
  308. :deep( .el-table__row:nth-child(odd)) {
  309. background-color: #e4fbe5 !important;
  310. }
  311. /* 禁用项样式 */
  312. :deep( .el-dropdown-menu__item.is-disabled) {
  313. color: #c0c4cc !important;
  314. cursor: not-allowed !important;
  315. }
  316. </style>