ModelSelection.vue 9.1 KB

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