初始化
This commit is contained in:
commit
8a19c93d22
5
.editorconfig
Normal file
5
.editorconfig
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[*.{js,jsx,ts,tsx,vue}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
23
.gitignore
vendored
Normal file
23
.gitignore
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/dist
|
||||||
|
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
24
README.md
Normal file
24
README.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# ecs_vue
|
||||||
|
|
||||||
|
## Project setup
|
||||||
|
```
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and hot-reloads for development
|
||||||
|
```
|
||||||
|
npm run serve
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiles and minifies for production
|
||||||
|
```
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lints and fixes files
|
||||||
|
```
|
||||||
|
npm run lint
|
||||||
|
```
|
||||||
|
|
||||||
|
### Customize configuration
|
||||||
|
See [Configuration Reference](https://cli.vuejs.org/config/).
|
5
babel.config.js
Normal file
5
babel.config.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
presets: [
|
||||||
|
'@vue/cli-plugin-babel/preset'
|
||||||
|
]
|
||||||
|
}
|
19
jsconfig.json
Normal file
19
jsconfig.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"module": "esnext",
|
||||||
|
"baseUrl": "./",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"src/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"lib": [
|
||||||
|
"esnext",
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"scripthost"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
22322
package-lock.json
generated
Normal file
22322
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
51
package.json
Normal file
51
package.json
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"name": "ecs_vue",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"serve": "vue-cli-service serve",
|
||||||
|
"build": "vue-cli-service build",
|
||||||
|
"lint": "vue-cli-service lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"core-js": "^3.8.3",
|
||||||
|
"vue": "^3.2.13",
|
||||||
|
"vue-router": "^4.0.3",
|
||||||
|
"vuex": "^4.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.12.16",
|
||||||
|
"@babel/eslint-parser": "^7.12.16",
|
||||||
|
"@vue/cli-plugin-babel": "~5.0.0",
|
||||||
|
"@vue/cli-plugin-eslint": "~5.0.0",
|
||||||
|
"@vue/cli-plugin-router": "~5.0.0",
|
||||||
|
"@vue/cli-plugin-vuex": "~5.0.0",
|
||||||
|
"@vue/cli-service": "~5.0.0",
|
||||||
|
"@vue/eslint-config-standard": "^6.1.0",
|
||||||
|
"eslint": "^7.32.0",
|
||||||
|
"eslint-plugin-import": "^2.25.3",
|
||||||
|
"eslint-plugin-node": "^11.1.0",
|
||||||
|
"eslint-plugin-promise": "^5.1.0",
|
||||||
|
"eslint-plugin-vue": "^8.0.3"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"root": true,
|
||||||
|
"env": {
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"plugin:vue/vue3-essential",
|
||||||
|
"@vue/standard"
|
||||||
|
],
|
||||||
|
"parserOptions": {
|
||||||
|
"parser": "@babel/eslint-parser"
|
||||||
|
},
|
||||||
|
"rules": {}
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"> 1%",
|
||||||
|
"last 2 versions",
|
||||||
|
"not dead",
|
||||||
|
"not ie 11"
|
||||||
|
]
|
||||||
|
}
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
17
public/index.html
Normal file
17
public/index.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||||
|
</noscript>
|
||||||
|
<div id="app"></div>
|
||||||
|
<!-- built files will be auto injected -->
|
||||||
|
</body>
|
||||||
|
</html>
|
26
src/App.vue
Normal file
26
src/App.vue
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<template>
|
||||||
|
<router-view/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#app {
|
||||||
|
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
text-align: center;
|
||||||
|
color: #2c3e50;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #2c3e50;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a.router-link-exact-active {
|
||||||
|
color: #42b983;
|
||||||
|
}
|
||||||
|
</style>
|
BIN
src/assets/logo.png
Normal file
BIN
src/assets/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
6
src/main.js
Normal file
6
src/main.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { createApp } from 'vue'
|
||||||
|
import App from './App.vue'
|
||||||
|
import router from './router'
|
||||||
|
import store from './store'
|
||||||
|
|
||||||
|
createApp(App).use(store).use(router).mount('#app')
|
56
src/router/index.js
Normal file
56
src/router/index.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
|
import Login from '../views/auth/Login.vue'
|
||||||
|
import Register from '../views/auth/Register.vue'
|
||||||
|
import AdminDashboard from '../views/admin/AdminDashboard.vue'
|
||||||
|
import StaffDashboard from '../views/staff/StaffDashboard.vue'
|
||||||
|
import CustomerDashboard from '../views/customer/CustomerDashboard.vue'
|
||||||
|
import CustomerHome from '../views/customer/CustomerHome.vue'
|
||||||
|
|
||||||
|
const routes = [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
redirect: '/login'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/login',
|
||||||
|
name: 'Login',
|
||||||
|
component: Login
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/register',
|
||||||
|
name: 'Register',
|
||||||
|
component: Register
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/admin',
|
||||||
|
name: 'AdminDashboard',
|
||||||
|
component: AdminDashboard,
|
||||||
|
meta: { requiresAuth: true, role: 'admin' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/staff',
|
||||||
|
name: 'StaffDashboard',
|
||||||
|
component: StaffDashboard,
|
||||||
|
meta: { requiresAuth: true, role: 'staff' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/customer',
|
||||||
|
name: 'CustomerDashboard',
|
||||||
|
component: CustomerDashboard,
|
||||||
|
meta: { requiresAuth: true, role: 'customer' },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
name: 'CustomerHome',
|
||||||
|
component: CustomerHome
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const router = createRouter({
|
||||||
|
history: createWebHistory(process.env.BASE_URL),
|
||||||
|
routes
|
||||||
|
})
|
||||||
|
|
||||||
|
export default router
|
14
src/store/index.js
Normal file
14
src/store/index.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { createStore } from 'vuex'
|
||||||
|
|
||||||
|
export default createStore({
|
||||||
|
state: {
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
},
|
||||||
|
modules: {
|
||||||
|
}
|
||||||
|
})
|
143
src/views/admin/AdminDashboard.vue
Normal file
143
src/views/admin/AdminDashboard.vue
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
<template>
|
||||||
|
<div class="admin-dashboard">
|
||||||
|
<header class="dashboard-header">
|
||||||
|
<h1>管理员控制台</h1>
|
||||||
|
<button @click="logout">退出登录</button>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="dashboard-content">
|
||||||
|
<nav class="sidebar">
|
||||||
|
<ul>
|
||||||
|
<li @click="currentView = 'staff'">员工管理</li>
|
||||||
|
<li @click="currentView = 'customers'">顾客管理</li>
|
||||||
|
<li @click="currentView = 'services'">服务管理</li>
|
||||||
|
<li @click="currentView = 'reports'">统计报表</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="main-content">
|
||||||
|
<!-- 员工管理 -->
|
||||||
|
<div v-if="currentView === 'staff'" class="staff-management">
|
||||||
|
<h2>员工管理</h2>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>员工ID</th>
|
||||||
|
<th>姓名</th>
|
||||||
|
<th>职位</th>
|
||||||
|
<th>联系方式</th>
|
||||||
|
<th>操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="staff in staffList" :key="staff.id">
|
||||||
|
<td>{{ staff.id }}</td>
|
||||||
|
<td>{{ staff.name }}</td>
|
||||||
|
<td>{{ staff.position }}</td>
|
||||||
|
<td>{{ staff.contact }}</td>
|
||||||
|
<td>
|
||||||
|
<button @click="editStaff(staff)">编辑</button>
|
||||||
|
<button @click="deleteStaff(staff.id)">删除</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 其他视图可以根据需要添加 -->
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'AdminDashboard',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
currentView: 'staff',
|
||||||
|
staffList: [
|
||||||
|
{ id: 1, name: '张三', position: '护工', contact: '13800138000' },
|
||||||
|
{ id: 2, name: '李四', position: '护士', contact: '13800138001' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
logout () {
|
||||||
|
// 实现退出登录逻辑
|
||||||
|
this.$router.push('/login')
|
||||||
|
},
|
||||||
|
editStaff (staff) {
|
||||||
|
// 实现编辑员工逻辑
|
||||||
|
console.log('编辑员工:', staff)
|
||||||
|
},
|
||||||
|
deleteStaff (staffId) {
|
||||||
|
// 实现删除员工逻辑
|
||||||
|
console.log('删除员工:', staffId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.admin-dashboard {
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-header {
|
||||||
|
background: #2c3e50;
|
||||||
|
color: white;
|
||||||
|
padding: 1rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-content {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
width: 200px;
|
||||||
|
background: #34495e;
|
||||||
|
color: white;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar li {
|
||||||
|
padding: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar li:hover {
|
||||||
|
background: #2c3e50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
flex: 1;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 8px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
</style>
|
102
src/views/auth/Login.vue
Normal file
102
src/views/auth/Login.vue
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
<template>
|
||||||
|
<div class="login-container">
|
||||||
|
<div class="login-box">
|
||||||
|
<h2>登录系统</h2>
|
||||||
|
<form @submit.prevent="handleLogin">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>用户名</label>
|
||||||
|
<input type="text" v-model="username" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>密码</label>
|
||||||
|
<input type="password" v-model="password" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>用户类型</label>
|
||||||
|
<select v-model="userType">
|
||||||
|
<option value="admin">管理员</option>
|
||||||
|
<option value="staff">员工</option>
|
||||||
|
<option value="customer">顾客</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit">登录</button>
|
||||||
|
</form>
|
||||||
|
<!-- 添加注册链接 -->
|
||||||
|
<div class="form-footer">
|
||||||
|
<p>还没有账号?<router-link to="/register">立即注册</router-link></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'Login',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
userType: 'customer'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleLogin () {
|
||||||
|
// 实现登录逻辑
|
||||||
|
console.log('登录信息:', this.username, this.password, this.userType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.login-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-box {
|
||||||
|
width: 400px;
|
||||||
|
padding: 20px;
|
||||||
|
background: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 10px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, select {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
background: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-footer {
|
||||||
|
margin-top: 15px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-footer a {
|
||||||
|
color: #4CAF50;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-footer a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
</style>
|
110
src/views/auth/Register.vue
Normal file
110
src/views/auth/Register.vue
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
<template>
|
||||||
|
<div class="register-container">
|
||||||
|
<div class="register-box">
|
||||||
|
<h2>注册账号</h2>
|
||||||
|
<form @submit.prevent="handleRegister">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>用户名</label>
|
||||||
|
<input type="text" v-model="username" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>密码</label>
|
||||||
|
<input type="password" v-model="password" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>确认密码</label>
|
||||||
|
<input type="password" v-model="confirmPassword" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>用户类型</label>
|
||||||
|
<select v-model="userType">
|
||||||
|
<option value="customer">顾客</option>
|
||||||
|
<option value="staff">员工</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit">注册</button>
|
||||||
|
</form>
|
||||||
|
<!-- 添加登录链接 -->
|
||||||
|
<div class="form-footer">
|
||||||
|
<p>已有账号?<router-link to="/login">立即登录</router-link></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'Register',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
confirmPassword: '',
|
||||||
|
userType: 'customer'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleRegister () {
|
||||||
|
if (this.password !== this.confirmPassword) {
|
||||||
|
alert('两次输入的密码不一致!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 实现注册逻辑
|
||||||
|
console.log('注册信息:', this.username, this.password, this.userType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.register-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-box {
|
||||||
|
width: 400px;
|
||||||
|
padding: 20px;
|
||||||
|
background: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 10px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, select {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
background: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-footer {
|
||||||
|
margin-top: 15px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-footer a {
|
||||||
|
color: #4CAF50;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-footer a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
</style>
|
80
src/views/customer/CustomerDashboard.vue
Normal file
80
src/views/customer/CustomerDashboard.vue
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<template>
|
||||||
|
<div class="customer-dashboard">
|
||||||
|
<header class="dashboard-header">
|
||||||
|
<h1>顾客服务中心</h1>
|
||||||
|
<nav class="main-nav">
|
||||||
|
<router-link to="/customer" class="nav-link">首页</router-link>
|
||||||
|
<router-link to="/customer/services" class="nav-link">服务预约</router-link>
|
||||||
|
<router-link to="/customer/schedule" class="nav-link">我的日程</router-link>
|
||||||
|
<router-link to="/customer/profile" class="nav-link">个人信息</router-link>
|
||||||
|
</nav>
|
||||||
|
<button @click="logout">退出登录</button>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="dashboard-content">
|
||||||
|
<router-view></router-view>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'CustomerDashboard',
|
||||||
|
methods: {
|
||||||
|
logout () {
|
||||||
|
this.$router.push('/login')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.customer-dashboard {
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-header {
|
||||||
|
background: #2c3e50;
|
||||||
|
color: white;
|
||||||
|
padding: 1rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-nav {
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link {
|
||||||
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link:hover,
|
||||||
|
.nav-link.router-link-active {
|
||||||
|
background: rgba(255,255,255,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-content {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background: #45a049;
|
||||||
|
}
|
||||||
|
</style>
|
237
src/views/customer/CustomerHome.vue
Normal file
237
src/views/customer/CustomerHome.vue
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
<template>
|
||||||
|
<div class="customer-home">
|
||||||
|
<!-- 轮播图部分 -->
|
||||||
|
<div class="carousel">
|
||||||
|
<div class="carousel-container" :style="{ transform: `translateX(-${currentIndex * 100}%)` }">
|
||||||
|
<div v-for="(slide, index) in slides" :key="index" class="carousel-slide">
|
||||||
|
<img :src="slide.image" :alt="slide.title">
|
||||||
|
<div class="slide-content">
|
||||||
|
<h2>{{ slide.title }}</h2>
|
||||||
|
<p>{{ slide.description }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="carousel-dots">
|
||||||
|
<span
|
||||||
|
v-for="(slide, index) in slides"
|
||||||
|
:key="index"
|
||||||
|
:class="{ active: currentIndex === index }"
|
||||||
|
@click="setSlide(index)"
|
||||||
|
></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 系统介绍部分 -->
|
||||||
|
<div class="system-intro">
|
||||||
|
<h1>养老服务系统</h1>
|
||||||
|
<div class="intro-cards">
|
||||||
|
<div class="intro-card">
|
||||||
|
<i class="fas fa-heart"></i>
|
||||||
|
<h3>专业照护</h3>
|
||||||
|
<p>提供24小时专业护理服务,确保老年人得到细致周到的照顾</p>
|
||||||
|
</div>
|
||||||
|
<div class="intro-card">
|
||||||
|
<i class="fas fa-user-md"></i>
|
||||||
|
<h3>医疗保障</h3>
|
||||||
|
<p>配备专业医疗团队,定期体检,及时响应健康需求</p>
|
||||||
|
</div>
|
||||||
|
<div class="intro-card">
|
||||||
|
<i class="fas fa-hands-helping"></i>
|
||||||
|
<h3>生活照料</h3>
|
||||||
|
<p>提供饮食起居、清洁卫生等全方位生活服务</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 服务特色部分 -->
|
||||||
|
<div class="service-features">
|
||||||
|
<h2>我们的服务特色</h2>
|
||||||
|
<div class="features-grid">
|
||||||
|
<div class="feature">
|
||||||
|
<h3>个性化服务</h3>
|
||||||
|
<p>根据每位老人的具体需求,制定个性化的护理方案</p>
|
||||||
|
</div>
|
||||||
|
<div class="feature">
|
||||||
|
<h3>智能监护</h3>
|
||||||
|
<p>采用现代化设备,实时监测老人的身体状况</p>
|
||||||
|
</div>
|
||||||
|
<div class="feature">
|
||||||
|
<h3>营养配餐</h3>
|
||||||
|
<p>专业营养师搭配,确保营养均衡</p>
|
||||||
|
</div>
|
||||||
|
<div class="feature">
|
||||||
|
<h3>文娱活动</h3>
|
||||||
|
<p>丰富多样的文化娱乐活动,丰富晚年生活</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'CustomerHome',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
currentIndex: 0,
|
||||||
|
slides: [
|
||||||
|
{
|
||||||
|
image: '/images/slide1.jpg', // 需要添加实际的图片路径
|
||||||
|
title: '温馨舒适的生活环境',
|
||||||
|
description: '为老年人提供宾至如归的居住体验'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image: '/images/slide2.jpg',
|
||||||
|
title: '专业的医疗护理团队',
|
||||||
|
description: '24小时专业护理,保障老年人健康'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image: '/images/slide3.jpg',
|
||||||
|
title: '丰富多彩的文娱活动',
|
||||||
|
description: '让晚年生活充满欢乐与活力'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setSlide (index) {
|
||||||
|
this.currentIndex = index
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
// 自动轮播
|
||||||
|
setInterval(() => {
|
||||||
|
this.currentIndex = (this.currentIndex + 1) % this.slides.length
|
||||||
|
}, 5000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.customer-home {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 轮播图样式 */
|
||||||
|
.carousel {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 500px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-container {
|
||||||
|
display: flex;
|
||||||
|
transition: transform 0.5s ease-in-out;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-slide {
|
||||||
|
min-width: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-slide img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-content {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 50px;
|
||||||
|
left: 50px;
|
||||||
|
color: white;
|
||||||
|
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-dots {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 20px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-dots span {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(255,255,255,0.5);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.carousel-dots span.active {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 系统介绍样式 */
|
||||||
|
.system-intro {
|
||||||
|
padding: 50px 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-cards {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 30px;
|
||||||
|
margin-top: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-card {
|
||||||
|
flex: 1;
|
||||||
|
max-width: 300px;
|
||||||
|
padding: 30px;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||||
|
transition: transform 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-card:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro-card i {
|
||||||
|
font-size: 40px;
|
||||||
|
color: #4CAF50;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 服务特色样式 */
|
||||||
|
.service-features {
|
||||||
|
background: #f5f5f5;
|
||||||
|
padding: 50px 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
|
gap: 30px;
|
||||||
|
margin-top: 40px;
|
||||||
|
padding: 0 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature {
|
||||||
|
background: white;
|
||||||
|
padding: 30px;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2 {
|
||||||
|
color: #2c3e50;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
color: #34495e;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
</style>
|
144
src/views/staff/StaffDashboard.vue
Normal file
144
src/views/staff/StaffDashboard.vue
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
<template>
|
||||||
|
<div class="staff-dashboard">
|
||||||
|
<header class="dashboard-header">
|
||||||
|
<h1>员工工作台</h1>
|
||||||
|
<button @click="logout">退出登录</button>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="dashboard-content">
|
||||||
|
<nav class="sidebar">
|
||||||
|
<ul>
|
||||||
|
<li @click="currentView = 'tasks'">工作任务</li>
|
||||||
|
<li @click="currentView = 'schedule'">排班表</li>
|
||||||
|
<li @click="currentView = 'customers'">顾客信息</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="main-content">
|
||||||
|
<!-- 工作任务视图 -->
|
||||||
|
<div v-if="currentView === 'tasks'" class="tasks-view">
|
||||||
|
<h2>今日工作任务</h2>
|
||||||
|
<div class="task-list">
|
||||||
|
<div v-for="task in tasks" :key="task.id" class="task-card">
|
||||||
|
<h3>{{ task.title }}</h3>
|
||||||
|
<p>顾客:{{ task.customer }}</p>
|
||||||
|
<p>时间:{{ task.time }}</p>
|
||||||
|
<p>状态:{{ task.status }}</p>
|
||||||
|
<button @click="completeTask(task.id)">完成任务</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'StaffDashboard',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
currentView: 'tasks',
|
||||||
|
tasks: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: '晨间护理',
|
||||||
|
customer: '王老先生',
|
||||||
|
time: '08:00-09:00',
|
||||||
|
status: '待完成'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: '用药提醒',
|
||||||
|
customer: '李奶奶',
|
||||||
|
time: '09:30-10:00',
|
||||||
|
status: '待完成'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
logout () {
|
||||||
|
this.$router.push('/login')
|
||||||
|
},
|
||||||
|
completeTask (taskId) {
|
||||||
|
// 实现完成任务逻辑
|
||||||
|
console.log('完成任务:', taskId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.staff-dashboard {
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-header {
|
||||||
|
background: #2c3e50;
|
||||||
|
color: white;
|
||||||
|
padding: 1rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-content {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
width: 200px;
|
||||||
|
background: #34495e;
|
||||||
|
color: white;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar li {
|
||||||
|
padding: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar li:hover {
|
||||||
|
background: #2c3e50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
flex: 1;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-list {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-card {
|
||||||
|
background: white;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background: #45a049;
|
||||||
|
}
|
||||||
|
</style>
|
4
vue.config.js
Normal file
4
vue.config.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
const { defineConfig } = require('@vue/cli-service')
|
||||||
|
module.exports = defineConfig({
|
||||||
|
transpileDependencies: true
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user