174 lines
6.1 KiB
Vue
174 lines
6.1 KiB
Vue
<template>
|
|
<section class="login-shell login-industrial-stage login-production-layout">
|
|
<div class="login-kinetic-field" aria-hidden="true">
|
|
<span class="login-depth-grid"></span>
|
|
<span class="login-scan-plane login-scan-plane-a"></span>
|
|
<span class="login-scan-plane login-scan-plane-b"></span>
|
|
<span class="login-data-thread login-data-thread-a"></span>
|
|
<span class="login-data-thread login-data-thread-b"></span>
|
|
<span class="login-data-thread login-data-thread-c"></span>
|
|
<span class="login-heat-column login-heat-column-a"></span>
|
|
<span class="login-heat-column login-heat-column-b"></span>
|
|
<span class="login-heat-column login-heat-column-c"></span>
|
|
</div>
|
|
|
|
<main class="login-production-cockpit" @click.stop>
|
|
<section class="login-line-area" aria-label="百华五金冲压产线">
|
|
<div class="login-line-brand">
|
|
<img class="login-logo login-logo-wordmark" src="/logo.png" alt="宁波百华智能科技有限公司 logo" />
|
|
<div>
|
|
<span>百华智能</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="login-production-line" aria-hidden="true">
|
|
<div class="login-line-floor"></div>
|
|
<span class="login-forge-beam login-forge-beam-a"></span>
|
|
<span class="login-forge-beam login-forge-beam-b"></span>
|
|
|
|
<div class="login-coil">
|
|
<span></span>
|
|
<span></span>
|
|
<span></span>
|
|
</div>
|
|
|
|
<div class="login-feeder-line">
|
|
<span class="login-metal-strip login-metal-strip-a"></span>
|
|
<span class="login-metal-strip login-metal-strip-b"></span>
|
|
<span class="login-metal-strip login-metal-strip-c"></span>
|
|
</div>
|
|
|
|
<div class="login-line-machine">
|
|
<div class="login-press-machine">
|
|
<span class="login-press-aura"></span>
|
|
<span class="login-press-arm"></span>
|
|
<span class="login-press-hammer"></span>
|
|
<span class="login-press-die"></span>
|
|
<span class="login-spark login-spark-a"></span>
|
|
<span class="login-spark login-spark-b"></span>
|
|
<span class="login-spark login-spark-c"></span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="login-inspection-gate">
|
|
<span></span>
|
|
<span></span>
|
|
</div>
|
|
|
|
<div class="login-stamped-stack">
|
|
<span></span>
|
|
<span></span>
|
|
<span></span>
|
|
</div>
|
|
|
|
<div class="login-part-runner">
|
|
<span></span>
|
|
<span></span>
|
|
<span></span>
|
|
</div>
|
|
|
|
<div class="login-console-link"></div>
|
|
</div>
|
|
|
|
<div class="login-line-labels" aria-label="生产流向">
|
|
<article class="login-conveyor-label">
|
|
<AppIcon name="material" />
|
|
<span>卷料入线</span>
|
|
</article>
|
|
<article class="login-conveyor-label">
|
|
<AppIcon name="production" />
|
|
<span>冲压成型</span>
|
|
</article>
|
|
<article class="login-conveyor-label">
|
|
<AppIcon name="quality" />
|
|
<span>质检扫描</span>
|
|
</article>
|
|
<article class="login-conveyor-label">
|
|
<AppIcon name="warehouseFinished" />
|
|
<span>成品入库</span>
|
|
</article>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="login-console-dock" aria-label="系统登录">
|
|
<span class="login-dock-rail login-dock-rail-a" aria-hidden="true"></span>
|
|
<span class="login-dock-rail login-dock-rail-b" aria-hidden="true"></span>
|
|
<span class="login-dock-floor" aria-hidden="true"></span>
|
|
|
|
<div class="login-console-frame">
|
|
<div class="login-control-console">
|
|
<div class="login-panel-head">
|
|
<h2>百华智能五金 ERP</h2>
|
|
</div>
|
|
|
|
<form class="login-form" @submit.prevent="handleLogin">
|
|
<label class="login-input-shell">
|
|
<span>账号</span>
|
|
<div class="login-input-frame">
|
|
<AppIcon name="employee" />
|
|
<input v-model.trim="form.username" type="text" autocomplete="username" placeholder="请输入系统账号" />
|
|
</div>
|
|
</label>
|
|
|
|
<label class="login-input-shell">
|
|
<span>密码</span>
|
|
<div class="login-input-frame">
|
|
<AppIcon name="permissions" />
|
|
<input v-model="form.password" type="password" autocomplete="current-password" placeholder="请输入登录密码" />
|
|
</div>
|
|
</label>
|
|
|
|
<div class="login-actions">
|
|
<button class="primary-button login-submit-button" type="submit" :disabled="submitting">
|
|
<span>{{ submitting ? "正在校验身份..." : "进入智能工厂" }}</span>
|
|
<AppIcon name="arrowRight" />
|
|
</button>
|
|
<p v-if="message" class="form-message">{{ message }}</p>
|
|
<p v-if="errorMessage" class="form-error">{{ errorMessage }}</p>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
</section>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { reactive, ref } from "vue";
|
|
import { useRoute, useRouter } from "vue-router";
|
|
|
|
import AppIcon from "../components/AppIcon.vue";
|
|
import { login, saveSession } from "../services/api";
|
|
|
|
const router = useRouter();
|
|
const route = useRoute();
|
|
|
|
const form = reactive({
|
|
username: "",
|
|
password: ""
|
|
});
|
|
|
|
const submitting = ref(false);
|
|
const message = ref("");
|
|
const errorMessage = ref("");
|
|
|
|
async function handleLogin() {
|
|
submitting.value = true;
|
|
message.value = "";
|
|
errorMessage.value = "";
|
|
|
|
try {
|
|
const user = await login(form.username, form.password);
|
|
saveSession(user);
|
|
message.value = `欢迎回来,${user.display_name}`;
|
|
const redirect = typeof route.query.redirect === "string" ? route.query.redirect : "/";
|
|
router.push(redirect);
|
|
} catch (error) {
|
|
errorMessage.value = error.message || "登录失败";
|
|
} finally {
|
|
submitting.value = false;
|
|
}
|
|
}
|
|
</script>
|