上传文件至 src/views
This commit is contained in:
185
src/views/ApprovalList.vue
Normal file
185
src/views/ApprovalList.vue
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page-container">
|
||||||
|
<UserMenu />
|
||||||
|
|
||||||
|
<form @submit.prevent="search" class="search-form">
|
||||||
|
<label>From:</label>
|
||||||
|
<input type="date" v-model="form.startDate" required />
|
||||||
|
|
||||||
|
<label>To:</label>
|
||||||
|
<input type="date" v-model="form.endDate" required />
|
||||||
|
|
||||||
|
<button type="submit">検索</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<table v-if="form.sizaiList?.length > 0" class="outputtable">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>資材ID</th>
|
||||||
|
<th>資材名</th>
|
||||||
|
<th>数量</th>
|
||||||
|
<th>カテゴリー</th>
|
||||||
|
<th>購入依頼者</th>
|
||||||
|
<th>購入依頼部門</th>
|
||||||
|
<th>状態</th>
|
||||||
|
<th>依頼日</th>
|
||||||
|
<th>承認</th>
|
||||||
|
<th>却下</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(item, index) in form.sizaiList" :key="index">
|
||||||
|
<td>{{ item.id }}</td>
|
||||||
|
<td>
|
||||||
|
<ApprovalDetail :targetId="item.id">{{ item.name }}</ApprovalDetail>
|
||||||
|
</td>
|
||||||
|
<td>{{ item.num }}</td>
|
||||||
|
<td>{{ item.category_name }}</td>
|
||||||
|
<td>{{ item.request_user_name }}</td>
|
||||||
|
<td>{{ item.request_dept_name }}</td>
|
||||||
|
<td>{{ item.status_name }}</td>
|
||||||
|
<td>{{ item.request_date }}</td>
|
||||||
|
<td>
|
||||||
|
<template v-if="item.status == 1 || item.status == 3">
|
||||||
|
<a href="#" @click.prevent="approval(item.id)">承認</a>
|
||||||
|
</template>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<template v-if="item.status == 1">
|
||||||
|
<a href="#" @click.prevent="reject(item.id)">却下</a>
|
||||||
|
</template>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div v-else style="text-align: center; margin-top: 20px">
|
||||||
|
データがありません
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { reactive, onMounted } from "vue";
|
||||||
|
import axios from "axios";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import UserMenu from "../components/UserMenu.vue";
|
||||||
|
import ApprovalDetail from "../components/ApprovalDetail.vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const form = reactive({
|
||||||
|
startDate: "",
|
||||||
|
endDate: "",
|
||||||
|
sizaiList: [],
|
||||||
|
targetId: null,
|
||||||
|
message: "",
|
||||||
|
messageflag: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchList = () => {
|
||||||
|
axios
|
||||||
|
.get("/api/approvalList/init")
|
||||||
|
.then((res) => {
|
||||||
|
const response = res.data;
|
||||||
|
if (!response.success) {
|
||||||
|
ElMessage.error(response.message || "初期化失敗しました");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Object.assign(form, response.data);
|
||||||
|
if (!form.sizaiList) form.sizaiList = [];
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
if ([401, 403].includes(err.response?.status)) {
|
||||||
|
ElMessage.error("ログイン情報が無効です。再度ログインしてください。");
|
||||||
|
router.push("/login");
|
||||||
|
} else {
|
||||||
|
ElMessage.error("サーバーエラーが発生しました");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(fetchList);
|
||||||
|
|
||||||
|
const search = () => {
|
||||||
|
axios
|
||||||
|
.post("/api/approvalList/search", {
|
||||||
|
startDate: form.startDate,
|
||||||
|
endDate: form.endDate,
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
Object.assign(form, res.data);
|
||||||
|
if (!form.sizaiList) form.sizaiList = [];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const approval = (id) => {
|
||||||
|
if (!confirm("本当に承認しますか?")) return;
|
||||||
|
axios
|
||||||
|
.post("/api/approvalList/approval", {
|
||||||
|
targeId: id,
|
||||||
|
startDate: form.startDate,
|
||||||
|
endDate: form.endDate,
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
const response = res.data;
|
||||||
|
if (!response.success) {
|
||||||
|
ElMessage.error(response.message || "承認失敗しました");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Object.assign(form, res.data);
|
||||||
|
if (!form.sizaiList) form.sizaiList = [];
|
||||||
|
ElMessage.success(response.message || "承認完了しました");
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
ElMessage.error("サーバーエラーが発生しました");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const reject = (id) => {
|
||||||
|
if (!confirm("本当に却下しますか?")) return;
|
||||||
|
axios
|
||||||
|
.post("/api/approvalList/reject", {
|
||||||
|
targeId: id,
|
||||||
|
startDate: form.startDate,
|
||||||
|
endDate: form.endDate,
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
const response = res.data;
|
||||||
|
if (!response.success) {
|
||||||
|
ElMessage.error(response.message || "却下失敗しました");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Object.assign(form, response.data);
|
||||||
|
if (!form.sizaiList) form.sizaiList = [];
|
||||||
|
ElMessage.success(response.message || "却下完了しました");
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
ElMessage.error("サーバーエラーが発生しました");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@import "@/assets/common.css";
|
||||||
|
|
||||||
|
.page-container {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.search-form {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
</style>
|
166
src/views/DeleverAct.vue
Normal file
166
src/views/DeleverAct.vue
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page-container">
|
||||||
|
<UserMenu />
|
||||||
|
|
||||||
|
<form @submit.prevent="search" class="search-form">
|
||||||
|
<select v-model="form.deptId" required>
|
||||||
|
<option disabled value="">選択してください</option>
|
||||||
|
<option v-for="dept in state.deptList" :key="dept.id" :value="dept.id">
|
||||||
|
{{ dept.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<button type="submit">検索</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<table v-if="state.sizaiList.length > 0" class="outputtable">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>資材ID</th>
|
||||||
|
<th>資材名</th>
|
||||||
|
<th>数量</th>
|
||||||
|
<th>カテゴリー</th>
|
||||||
|
<th>購入依頼者</th>
|
||||||
|
<th>購入依頼部門</th>
|
||||||
|
<th>状態</th>
|
||||||
|
<th>依頼日</th>
|
||||||
|
<th>納品</th>
|
||||||
|
<th>QRコード</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(item, index) in state.sizaiList" :key="index">
|
||||||
|
<td>{{ item.id }}</td>
|
||||||
|
<td>{{ item.name }}</td>
|
||||||
|
<td>{{ item.num }}</td>
|
||||||
|
<td>{{ item.category_name }}</td>
|
||||||
|
<td>{{ item.request_user_name }}</td>
|
||||||
|
<td>{{ item.request_dept_name }}</td>
|
||||||
|
<td>{{ item.status_name }}</td>
|
||||||
|
<td>{{ item.request_date }}</td>
|
||||||
|
<td>
|
||||||
|
<template v-if="item.status == 2 || item.status == 4">
|
||||||
|
<a href="#" @click.prevent="delever(item.id)">納品</a>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<span style="color: red">納品</span>
|
||||||
|
</template>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<el-popover placement="top" trigger="hover" width="auto">
|
||||||
|
<template #reference>
|
||||||
|
<span style="cursor: pointer; color: blue">QRコード</span>
|
||||||
|
</template>
|
||||||
|
<QrCode :id="item.id" />
|
||||||
|
</el-popover>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div v-else style="text-align: center; margin-top: 20px">
|
||||||
|
データがありません
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { reactive, onMounted } from "vue";
|
||||||
|
import axios from "axios";
|
||||||
|
import UserMenu from "../components/UserMenu.vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import QrCode from "../components/QrCode.vue";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const form = reactive({
|
||||||
|
deptId: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
deptList: [],
|
||||||
|
sizaiList: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchList = () => {
|
||||||
|
axios
|
||||||
|
.get("/api/delever/init")
|
||||||
|
.then((res) => {
|
||||||
|
const response = res.data;
|
||||||
|
if (!response.success) {
|
||||||
|
ElMessage.error(response.message || "初期化失敗しました");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.deptList = response.data.deptList;
|
||||||
|
state.sizaiList = response.data.sizaiList || [];
|
||||||
|
|
||||||
|
form.deptId =
|
||||||
|
response.data.deptId ||
|
||||||
|
(state.deptList.length > 0 ? state.deptList[0].id : "");
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
if ([401, 403].includes(err.response?.status)) {
|
||||||
|
ElMessage.error("ログイン情報が無効です。再度ログインしてください。");
|
||||||
|
router.push("/login");
|
||||||
|
} else {
|
||||||
|
ElMessage.error("サーバーエラーが発生しました");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(fetchList);
|
||||||
|
|
||||||
|
const search = () => {
|
||||||
|
axios
|
||||||
|
.post("/api/delever/search", {
|
||||||
|
deptId: form.deptId,
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
const response = res.data;
|
||||||
|
if (!response.success) {
|
||||||
|
ElMessage.error(response.message || "検索失敗しました");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.sizaiList = response.data.sizaiList || [];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const delever = (id) => {
|
||||||
|
if (!confirm("納品に操作しますか?")) return;
|
||||||
|
axios
|
||||||
|
.post("/api/delever/act", {
|
||||||
|
id,
|
||||||
|
deptId: form.deptId,
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
const response = res.data;
|
||||||
|
if (!response.success) {
|
||||||
|
ElMessage.error(response.message || "納品失敗しました");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.sizaiList = response.data.sizaiList || [];
|
||||||
|
search();
|
||||||
|
ElMessage.success(response.message || "納品完了しました");
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
ElMessage.error("サーバーエラーが発生しました");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@import "@/assets/common.css";
|
||||||
|
|
||||||
|
.page-container {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
251
src/views/InStore.vue
Normal file
251
src/views/InStore.vue
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page-container">
|
||||||
|
<UserMenu />
|
||||||
|
|
||||||
|
<form @submit.prevent="search" class="search-form">
|
||||||
|
<button @click="scanQR">QRコード読取</button>
|
||||||
|
<div v-show="isScanning">
|
||||||
|
<div id="reader" style="width: 300px"></div>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
id="target"
|
||||||
|
v-model="form.id"
|
||||||
|
type="number"
|
||||||
|
placeholder="資材IDを入力"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<button type="submit">検索</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form @submit.prevent="submitForm">
|
||||||
|
<table class="inputtable">
|
||||||
|
<tr>
|
||||||
|
<td>資材ID</td>
|
||||||
|
<td>{{ form.id }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>資材名</td>
|
||||||
|
<td>{{ form.name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>数量</td>
|
||||||
|
<td>{{ form.num }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>カテゴリー</td>
|
||||||
|
<td>{{ form.category_name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>状態</td>
|
||||||
|
<td>{{ form.status_name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>倉庫</td>
|
||||||
|
<td v-if="form.status === '5' || form.status === '7'">
|
||||||
|
<select v-model="form.souko_id" required>
|
||||||
|
<option disabled value="">選択してください</option>
|
||||||
|
<option
|
||||||
|
v-for="sou in state.soukoList"
|
||||||
|
:key="sou.id"
|
||||||
|
:value="sou.id"
|
||||||
|
>
|
||||||
|
{{ sou.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td v-else>
|
||||||
|
{{ form.souko_name || "-" }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>購入依頼者</td>
|
||||||
|
<td>{{ form.request_user_name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>購入依頼部門</td>
|
||||||
|
<td>{{ form.request_dept_name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>依頼日</td>
|
||||||
|
<td>{{ form.request_date }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>発注日</td>
|
||||||
|
<td>{{ form.order_date }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>納品日</td>
|
||||||
|
<td>{{ form.delivery_date }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>入庫日</td>
|
||||||
|
<td>{{ form.instore_date }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>出庫日</td>
|
||||||
|
<td>{{ form.outstore_date }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>備考</td>
|
||||||
|
<td>{{ form.note }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div
|
||||||
|
v-if="form.status === '5' || form.status === '7'"
|
||||||
|
style="margin-top: 20px"
|
||||||
|
>
|
||||||
|
<button type="submit">入庫</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { reactive, ref, onMounted } from "vue";
|
||||||
|
import axios from "axios";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import UserMenu from "../components/UserMenu.vue";
|
||||||
|
import { Html5Qrcode } from "html5-qrcode";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const form = reactive({
|
||||||
|
id: "",
|
||||||
|
name: "",
|
||||||
|
num: "",
|
||||||
|
category_name: "",
|
||||||
|
status_name: "",
|
||||||
|
status: 0,
|
||||||
|
souko_id: "",
|
||||||
|
souko_name: "",
|
||||||
|
request_user_name: "",
|
||||||
|
request_dept_name: "",
|
||||||
|
request_date: "",
|
||||||
|
order_date: "",
|
||||||
|
delivery_date: "",
|
||||||
|
instore_date: "",
|
||||||
|
outstore_date: "",
|
||||||
|
note: "",
|
||||||
|
deptId: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
soukoList: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const isScanning = ref(false);
|
||||||
|
|
||||||
|
const scanQR = () => {
|
||||||
|
isScanning.value = true;
|
||||||
|
const html5QrCode = new Html5Qrcode("reader");
|
||||||
|
html5QrCode
|
||||||
|
.start(
|
||||||
|
{ facingMode: "environment" },
|
||||||
|
{
|
||||||
|
fps: 10,
|
||||||
|
qrbox: 250,
|
||||||
|
},
|
||||||
|
(decodedText) => {
|
||||||
|
form.id = decodedText;
|
||||||
|
isScanning.value = false;
|
||||||
|
html5QrCode
|
||||||
|
.stop()
|
||||||
|
.then(() => {
|
||||||
|
/* 停止成功時の処理 */
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
/* 停止失敗時の処理 */
|
||||||
|
});
|
||||||
|
search();
|
||||||
|
},
|
||||||
|
(errorMessage) => {
|
||||||
|
console.warn("読み取りエラー: ", errorMessage);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.catch((err) => {
|
||||||
|
ElMessage.error("QRコード読み取りに失敗しました");
|
||||||
|
isScanning.value = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchList = async () => {
|
||||||
|
try {
|
||||||
|
const res = await axios.get("/api/inStore/init");
|
||||||
|
const response = res.data;
|
||||||
|
if (!response.success) {
|
||||||
|
ElMessage.error(response.message || "初期化に失敗しました");
|
||||||
|
router.push("/login");
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
ElMessage.error("サーバーエラーが発生しました");
|
||||||
|
router.push("/login");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const search = async () => {
|
||||||
|
if (!form.id || form.id === "") {
|
||||||
|
ElMessage.warning("資材IDを入力してください");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await axios.post("/api/inStore/search", { id: form.id });
|
||||||
|
const response = res.data;
|
||||||
|
|
||||||
|
if (!response.success) {
|
||||||
|
ElMessage.error(response.message || "検索失敗しました");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = response.data;
|
||||||
|
if (!data) {
|
||||||
|
ElMessage.error("資材データが見つかりませんでした");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(form, data.sizai);
|
||||||
|
state.soukoList = data.soukoList || [];
|
||||||
|
} catch (err) {
|
||||||
|
ElMessage.error("検索中にサーバーエラーが発生しました");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const submitForm = async () => {
|
||||||
|
if (!confirm("入庫に操作しますか?")) return;
|
||||||
|
axios
|
||||||
|
.post("/api/inStore/act", { sizai: { ...form } })
|
||||||
|
.then((res) => {
|
||||||
|
const response = res.data;
|
||||||
|
if (!response.success) {
|
||||||
|
ElMessage.error(response.message || "入庫失敗しました");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Object.assign(form, response.data.sizai);
|
||||||
|
ElMessage.success(response.message || "入庫完了しました");
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
ElMessage.error("サーバーエラーが発生しました");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(fetchList);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@import "@/assets/common.css";
|
||||||
|
|
||||||
|
.page-container {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
156
src/views/OrderAct.vue
Normal file
156
src/views/OrderAct.vue
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page-container">
|
||||||
|
<UserMenu />
|
||||||
|
|
||||||
|
<form @submit.prevent="search" class="search-form">
|
||||||
|
<select v-model="form.deptId" required>
|
||||||
|
<option disabled value="">選択してください</option>
|
||||||
|
<option v-for="dept in state.deptList" :key="dept.id" :value="dept.id">
|
||||||
|
{{ dept.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<button type="submit">検索</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<table v-if="state.sizaiList.length > 0" class="outputtable">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>資材ID</th>
|
||||||
|
<th>資材名</th>
|
||||||
|
<th>数量</th>
|
||||||
|
<th>カテゴリー</th>
|
||||||
|
<th>購入依頼者</th>
|
||||||
|
<th>購入依頼部門</th>
|
||||||
|
<th>状態</th>
|
||||||
|
<th>依頼日</th>
|
||||||
|
<th>発注</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="(item, index) in state.sizaiList" :key="index">
|
||||||
|
<td>{{ item.id }}</td>
|
||||||
|
<td>{{ item.name }}</td>
|
||||||
|
<td>{{ item.num }}</td>
|
||||||
|
<td>{{ item.category_name }}</td>
|
||||||
|
<td>{{ item.request_user_name }}</td>
|
||||||
|
<td>{{ item.request_dept_name }}</td>
|
||||||
|
<td>{{ item.status_name }}</td>
|
||||||
|
<td>{{ item.request_date }}</td>
|
||||||
|
<td>
|
||||||
|
<template v-if="item.status == 2">
|
||||||
|
<a href="#" @click.prevent="order(item.id)">発注</a>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<span style="color: red">発注済み</span>
|
||||||
|
</template>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div v-else style="text-align: center; margin-top: 20px">
|
||||||
|
データがありません
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { reactive, onMounted } from "vue";
|
||||||
|
import axios from "axios";
|
||||||
|
import UserMenu from "../components/UserMenu.vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const form = reactive({
|
||||||
|
deptId: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
deptList: [],
|
||||||
|
sizaiList: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchList = () => {
|
||||||
|
axios
|
||||||
|
.get("/api/order/init")
|
||||||
|
.then((res) => {
|
||||||
|
const response = res.data;
|
||||||
|
if (!response.success) {
|
||||||
|
ElMessage.error(response.message || "初期化失敗しました");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.deptList = response.data.deptList;
|
||||||
|
state.sizaiList = response.data.sizaiList || [];
|
||||||
|
|
||||||
|
form.deptId =
|
||||||
|
response.data.deptId ||
|
||||||
|
(state.deptList.length > 0 ? state.deptList[0].id : "");
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
if ([401, 403].includes(err.response?.status)) {
|
||||||
|
ElMessage.error("ログイン情報が無効です。再度ログインしてください。");
|
||||||
|
router.push("/login");
|
||||||
|
} else {
|
||||||
|
ElMessage.error("サーバーエラーが発生しました");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(fetchList);
|
||||||
|
|
||||||
|
const search = () => {
|
||||||
|
axios
|
||||||
|
.post("/api/order/search", {
|
||||||
|
deptId: form.deptId,
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
const response = res.data;
|
||||||
|
if (!response.success) {
|
||||||
|
ElMessage.error(response.message || "検索失敗しました");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.sizaiList = response.data.sizaiList || [];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const order = (id) => {
|
||||||
|
if (!confirm("本当に注文しますか?")) return;
|
||||||
|
axios
|
||||||
|
.post("/api/order/act", {
|
||||||
|
id,
|
||||||
|
deptId: form.deptId,
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
const response = res.data;
|
||||||
|
if (!response.success) {
|
||||||
|
ElMessage.error(response.message || "注文失敗しました");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.sizaiList = response.data.sizaiList || [];
|
||||||
|
search();
|
||||||
|
ElMessage.success(response.message || "注文完了しました");
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
ElMessage.error("サーバーエラーが発生しました");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@import "@/assets/common.css";
|
||||||
|
|
||||||
|
.page-container {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-form {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
Reference in New Issue
Block a user