Browse Source

实验记录接口

feature/layout_0214
zhangjiming 5 months ago
parent
commit
ad2a9d2dc6
  1. 8
      src/App.vue
  2. 17
      src/services/experience/experienceList.ts
  3. 10
      src/stores/setting.ts
  4. 21
      src/stores/user.ts
  5. 94
      src/views/expeRecord/index.vue
  6. 3
      src/views/userManage/UserManage.vue

8
src/App.vue

@ -8,9 +8,12 @@ import { useSettingStore } from "./stores/setting";
import { getLiquidList } from "./services/liquid/liquidManage";
import { useStatusStore } from "./stores/status";
import { ElMessage } from "element-plus";
import { getUserList } from "./services/user/userManager";
import { useUserStore } from "./stores/user";
const router = useRouter();
const settingStore = useSettingStore();
const statusStore = useStatusStore();
const userStore = useUserStore();
const wsClient = createWebSocket(sharedWsUrl);
wsClient.dataOb.subscribe(data => {
@ -47,6 +50,11 @@ onMounted(() => {
settingStore.setContainerConf(res.data);
}
});
getUserList({ pageNum: 1, pageSize: 9999 }).then(res => {
if (res.success) {
userStore.setUserList(res.data.list);
}
});
});
</script>

17
src/services/experience/experienceList.ts

@ -0,0 +1,17 @@
import type { BaseResponse } from "../httpRequest";
import httpRequest from "../httpRequest";
export type ExperienceRecord = {
id: number;
name: string;
startTime: string;
createUser: number;
};
export function getExperienceRecords(params: { pageNum: number; pageSize: number }) {
return httpRequest<BaseResponse<{ list: ExperienceRecord[]; total: number }>>({ url: "/api/tasks/list", params });
}
export function deleteExperienceRecords(ids: string) {
return httpRequest<BaseResponse>({ url: `/api/tasks/${ids}`, method: "DELETE" });
}

10
src/stores/setting.ts

@ -24,8 +24,8 @@ export const useSettingStore = defineStore("setting", () => {
};
// 酸液列表 ID映射表: 使用方法 liquidIdMap.value[液体ID] -> Liquid对象
const liquidIdMap = computed(() => {
return R.reduce(
(acc: { [p: number]: Liquid }, curr: Liquid) => {
return R.reduce<Liquid, { [p: number]: Liquid }>(
(acc, curr) => {
acc[curr.id] = curr;
return acc;
},
@ -39,10 +39,8 @@ export const useSettingStore = defineStore("setting", () => {
return containerConf.value.filter(c => c.type === 0);
});
// 配置了酸液的桶
const heatContainerWithLiquid = computed(() => {
return heatContainers.value
.filter(c => c.solutionId)
.map(c => ({ ...c, solution: liquidIdMap.value[c.solutionId] } as ContainerWithLiquid));
const heatContainerWithLiquid = computed<ContainerWithLiquid[]>(() => {
return heatContainers.value.filter(c => c.solutionId).map(c => ({ ...c, solution: liquidIdMap.value[c.solutionId] }));
});
// 配置了桶的酸液
const availableLiquids = computed(() => {

21
src/stores/user.ts

@ -1,6 +1,7 @@
import type { User } from "@/services/user/userManager";
import { defineStore } from "pinia";
import { ref } from "vue";
import { computed, ref } from "vue";
import * as R from "ramda";
export const useUserStore = defineStore("user", () => {
const user = ref<User | undefined>();
@ -8,5 +9,21 @@ export const useUserStore = defineStore("user", () => {
user.value = usr;
};
return { user, setUser };
const userList = ref<User[] | undefined>();
const setUserList = (users: User[]) => {
userList.value = users;
};
const userIdMap = computed(() => {
return R.reduce<User, { [p: number]: User }>(
(acc, curr) => {
acc[curr.id] = curr;
return acc;
},
{},
userList.value || []
);
});
return { user, setUser, userList, setUserList, userIdMap };
});

94
src/views/expeRecord/index.vue

@ -1,33 +1,49 @@
<template>
<div class="component-page">
<section class="flex items-center h-20 gap-3 pl-3">
<button class="btn-light px-3 py-1 text-xs">导出</button>
<button :disabled="opDisable" class="btn-light px-3 py-1 text-xs disabled:btn-light-disabled">删除</button>
<button :disabled="selectedIds.length === 0" class="btn-light px-3 py-1 text-xs disabled:btn-light-disabled">导出</button>
<button
:disabled="selectedIds.length === 0"
class="btn-light px-3 py-1 text-xs disabled:btn-light-disabled"
@click="onDeleteRecords">
删除
</button>
</section>
<section>
<header class="h-10 flex items-center bg-[#000]/[0.02] text-xs pr-3 text-text">
<div class="w-10 self-stretch flex justify-center items-center">
<img class="w-4 h-4" src="@/assets/Icon-unselect.svg" alt="icon" />
<img
class="w-4 h-4"
:src="
selectedIds.length > 0
? selectedIds.length === recordList.length
? icon_select
: icon_partial
: icon_unselect
"
alt="icon" />
</div>
<p class="w-[10rem]">时间</p>
<p class="w-[10rem]">时间</p>
<p class="w-[8rem]">用户名</p>
<p>实验记录</p>
<p>实验记录</p>
</header>
<div class="h-10 flex items-center text-xs pr-3 text-[#6e6e6e] border-b border-b-[#f8f8f8]">
<div
v-for="record in recordList"
:key="record.id"
class="h-10 flex items-center text-xs pr-3 text-[#6e6e6e] border-b border-b-[#f8f8f8]"
@click="onItemSelect(record)">
<div class="w-10 self-stretch flex justify-center items-center">
<img class="w-4 h-4" :src="isSelect ? icon_select : icon_unselect" alt="" />
<img class="w-4 h-4" :src="selectedIds.includes(record.id) ? icon_select : icon_unselect" alt="" />
</div>
<p class="w-[10rem]">2025年6月24日 13:16:45</p>
<p class="w-[8rem]">admin</p>
<p>实验记录xxxxxx</p>
<p class="w-[10rem]">{{ record.startTime }}</p>
<p class="w-[8rem]">{{ userStore.userIdMap[record.createUser].nickname }}</p>
<p class="flex-auto">{{ record.name }}</p>
</div>
</section>
<van-overlay :show="showEditDialog">
<div class="flex justify-center items-center h-full">
</div>
<div class="flex justify-center items-center h-full"></div>
</van-overlay>
</div>
</template>
@ -35,10 +51,56 @@
<script lang="ts" setup>
import icon_unselect from "@/assets/Icon-unselect.svg";
import icon_select from "@/assets/Icon-select.svg";
import { ref } from "vue";
import icon_partial from "@/assets/Icon-partial-select.svg";
import { onMounted, ref } from "vue";
import { deleteExperienceRecords, getExperienceRecords, type ExperienceRecord } from "@/services/experience/experienceList";
import { showToast } from "vant";
import { useUserStore } from "@/stores/user";
const isSelect = ref<boolean>(true);
const opDisable = ref<boolean>(true);
const userStore = useUserStore();
const showEditDialog = ref<boolean>(false);
const recordList = ref<ExperienceRecord[]>([]);
const selectedIds = ref<number[]>([]);
function getRecords() {
getExperienceRecords({ pageNum: 1, pageSize: 9999 }).then(res => {
if (res.success) {
recordList.value = res.data.list;
} else {
showToast(res.msg);
}
});
}
onMounted(() => {
getRecords();
});
function onItemSelect(record: ExperienceRecord) {
if (selectedIds.value.includes(record.id)) {
selectedIds.value = selectedIds.value.filter(id => id !== record.id);
} else {
selectedIds.value = [...selectedIds.value, record.id];
}
}
function onSelectAll() {
if (selectedIds.value.length === recordList.value.length) {
selectedIds.value = [];
} else {
selectedIds.value = recordList.value.map(record => record.id);
}
}
function onDeleteRecords() {
if (selectedIds.value.length === 0) return;
deleteExperienceRecords(selectedIds.value.join(",")).then(res => {
if (res.success) {
selectedIds.value = [];
getRecords();
} else {
showToast(res.msg);
}
});
}
</script>

3
src/views/userManage/UserManage.vue

@ -60,7 +60,9 @@ import { showToast } from "vant";
import { onMounted, ref } from "vue";
import { createUser, deleteUser, getUserList, type User } from "@/services/user/userManager";
import AddUser from "./components/AddUser.vue";
import { useUserStore } from "@/stores/user";
const userStore = useUserStore()
const showEditDialog = ref<boolean>(false);
const userList = ref<User[]>([]);
@ -70,6 +72,7 @@ function getUsers() {
getUserList({ pageNum: 1, pageSize: 9999 }).then(res => {
if (res.success) {
userList.value = res.data.list;
userStore.setUserList(res.data.list);
} else {
showToast(res.msg);
}

Loading…
Cancel
Save