feat: add owner field, fix header issue and use zhCN for element-plus
This commit is contained in:
@@ -9,6 +9,9 @@ class Item(models.Model):
|
|||||||
('in_use', '使用中'),
|
('in_use', '使用中'),
|
||||||
('maintenance', '维护中'),
|
('maintenance', '维护中'),
|
||||||
('damaged', '损坏'),
|
('damaged', '损坏'),
|
||||||
|
('lost', '丢失'),
|
||||||
|
('abandoned', '已弃用'),
|
||||||
|
('prohibited', '禁止借用'),
|
||||||
]
|
]
|
||||||
|
|
||||||
name = models.CharField(max_length=100, verbose_name='物品名称')
|
name = models.CharField(max_length=100, verbose_name='物品名称')
|
||||||
@@ -17,6 +20,7 @@ class Item(models.Model):
|
|||||||
category = models.CharField(max_length=50, verbose_name='物品类别')
|
category = models.CharField(max_length=50, verbose_name='物品类别')
|
||||||
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='available', verbose_name='物品状态')
|
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='available', verbose_name='物品状态')
|
||||||
location = models.CharField(max_length=100, blank=True, verbose_name='存放位置')
|
location = models.CharField(max_length=100, blank=True, verbose_name='存放位置')
|
||||||
|
owner = models.CharField(max_length=100, blank=True, null=True, verbose_name='所有者')
|
||||||
purchase_date = models.DateField(null=True, blank=True, verbose_name='购买日期')
|
purchase_date = models.DateField(null=True, blank=True, verbose_name='购买日期')
|
||||||
value = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True, verbose_name='价值')
|
value = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True, verbose_name='价值')
|
||||||
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
|
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class ItemSerializer(serializers.ModelSerializer):
|
|||||||
model = Item
|
model = Item
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'name', 'description', 'serial_number', 'category', 'status',
|
'id', 'name', 'description', 'serial_number', 'category', 'status',
|
||||||
'location', 'purchase_date', 'value', 'created_at', 'updated_at',
|
'location', 'owner', 'purchase_date', 'value', 'created_at', 'updated_at',
|
||||||
'current_user'
|
'current_user'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
<template>
|
||||||
|
<el-header class="app-header">
|
||||||
|
<div class="header-content">
|
||||||
|
<h1 class="logo">爱特工作室物品管理系统</h1>
|
||||||
|
<el-menu
|
||||||
|
mode="horizontal"
|
||||||
|
:default-active="$route.path"
|
||||||
|
router
|
||||||
|
class="nav-menu"
|
||||||
|
>
|
||||||
|
<el-menu-item index="/">
|
||||||
|
<el-icon><House /></el-icon>
|
||||||
|
首页
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="/items">
|
||||||
|
<el-icon><Box /></el-icon>
|
||||||
|
物品管理
|
||||||
|
</el-menu-item>
|
||||||
|
<el-menu-item index="/usage">
|
||||||
|
<el-icon><Document /></el-icon>
|
||||||
|
使用记录
|
||||||
|
</el-menu-item>
|
||||||
|
</el-menu>
|
||||||
|
</div>
|
||||||
|
</el-header>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'AppHeader'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.app-header {
|
||||||
|
background-color: #ffffff;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,.12), 0 0 6px rgba(0,0,0,.04);
|
||||||
|
height: 60px !important;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 20px;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
color: #409eff;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-menu {
|
||||||
|
border-bottom: none;
|
||||||
|
width: 60%;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-menu .el-menu-item {
|
||||||
|
border-bottom: none;
|
||||||
|
height: 60px;
|
||||||
|
line-height: 60px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
+20
-1
@@ -4,6 +4,23 @@ import router from './router'
|
|||||||
import ElementPlus from 'element-plus'
|
import ElementPlus from 'element-plus'
|
||||||
import 'element-plus/dist/index.css'
|
import 'element-plus/dist/index.css'
|
||||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||||
|
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
|
||||||
|
|
||||||
|
const debounce = (fn, delay) => {
|
||||||
|
let timeoutId
|
||||||
|
return (...args) => {
|
||||||
|
clearTimeout(timeoutId)
|
||||||
|
timeoutId = setTimeout(() => fn.apply(null, args), delay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const _ResizeObserver = window.ResizeObserver
|
||||||
|
window.ResizeObserver = class ResizeObserver extends _ResizeObserver {
|
||||||
|
constructor(callback) {
|
||||||
|
callback = debounce(callback, 20)
|
||||||
|
super(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
@@ -12,6 +29,8 @@ for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
|||||||
app.component(key, component)
|
app.component(key, component)
|
||||||
}
|
}
|
||||||
|
|
||||||
app.use(ElementPlus)
|
app.use(ElementPlus, {
|
||||||
|
locale: zhCn,
|
||||||
|
})
|
||||||
app.use(router)
|
app.use(router)
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|||||||
@@ -1,30 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-header>
|
<AppHeader />
|
||||||
<div class="header-content">
|
|
||||||
<h1 class="logo">爱特工作室物品管理系统</h1>
|
|
||||||
<el-menu
|
|
||||||
mode="horizontal"
|
|
||||||
:default-active="$route.path"
|
|
||||||
router
|
|
||||||
class="nav-menu"
|
|
||||||
>
|
|
||||||
<el-menu-item index="/">
|
|
||||||
<el-icon><House /></el-icon>
|
|
||||||
首页
|
|
||||||
</el-menu-item>
|
|
||||||
<el-menu-item index="/items">
|
|
||||||
<el-icon><Box /></el-icon>
|
|
||||||
物品管理
|
|
||||||
</el-menu-item>
|
|
||||||
<el-menu-item index="/usage">
|
|
||||||
<el-icon><Document /></el-icon>
|
|
||||||
使用记录
|
|
||||||
</el-menu-item>
|
|
||||||
</el-menu>
|
|
||||||
</div>
|
|
||||||
</el-header>
|
|
||||||
<div class="dashboard">
|
<div class="dashboard">
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="42">
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-card class="stat-card">
|
<el-card class="stat-card">
|
||||||
<div class="stat-content">
|
<div class="stat-content">
|
||||||
@@ -77,6 +54,58 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-card class="stat-card">
|
||||||
|
<div class="stat-content">
|
||||||
|
<div class="stat-icon damaged">
|
||||||
|
<el-icon><WarningFilled /></el-icon>
|
||||||
|
</div>
|
||||||
|
<div class="stat-info">
|
||||||
|
<h3>{{ stats.damaged }}</h3>
|
||||||
|
<p>损坏</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-card class="stat-card">
|
||||||
|
<div class="stat-content">
|
||||||
|
<div class="stat-icon lost">
|
||||||
|
<el-icon><QuestionFilled /></el-icon>
|
||||||
|
</div>
|
||||||
|
<div class="stat-info">
|
||||||
|
<h3>{{ stats.lost }}</h3>
|
||||||
|
<p>丢失</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-card class="stat-card">
|
||||||
|
<div class="stat-content">
|
||||||
|
<div class="stat-icon abandoned">
|
||||||
|
<el-icon><Delete /></el-icon>
|
||||||
|
</div>
|
||||||
|
<div class="stat-info">
|
||||||
|
<h3>{{ stats.abandoned }}</h3>
|
||||||
|
<p>已弃用</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-card class="stat-card">
|
||||||
|
<div class="stat-content">
|
||||||
|
<div class="stat-icon prohibited">
|
||||||
|
<el-icon><Lock /></el-icon>
|
||||||
|
</div>
|
||||||
|
<div class="stat-info">
|
||||||
|
<h3>{{ stats.prohibited }}</h3>
|
||||||
|
<p>禁止借用</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row :gutter="20" style="margin-top: 20px;">
|
<el-row :gutter="20" style="margin-top: 20px;">
|
||||||
@@ -127,16 +156,24 @@
|
|||||||
<script>
|
<script>
|
||||||
import { itemService, usageService } from '../services/api'
|
import { itemService, usageService } from '../services/api'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
import AppHeader from '../components/AppHeader.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
|
components: {
|
||||||
|
AppHeader
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
stats: {
|
stats: {
|
||||||
total: 0,
|
total: 0,
|
||||||
available: 0,
|
available: 0,
|
||||||
inUse: 0,
|
inUse: 0,
|
||||||
maintenance: 0
|
maintenance: 0,
|
||||||
|
damaged: 0,
|
||||||
|
lost: 0,
|
||||||
|
abandoned: 0,
|
||||||
|
prohibited: 0,
|
||||||
},
|
},
|
||||||
currentUsages: [],
|
currentUsages: [],
|
||||||
recentItems: []
|
recentItems: []
|
||||||
@@ -156,6 +193,10 @@ export default {
|
|||||||
this.stats.available = items.filter(item => item.status === 'available').length
|
this.stats.available = items.filter(item => item.status === 'available').length
|
||||||
this.stats.inUse = items.filter(item => item.status === 'in_use').length
|
this.stats.inUse = items.filter(item => item.status === 'in_use').length
|
||||||
this.stats.maintenance = items.filter(item => item.status === 'maintenance').length
|
this.stats.maintenance = items.filter(item => item.status === 'maintenance').length
|
||||||
|
this.stats.damaged = items.filter(item => item.status === 'damaged').length
|
||||||
|
this.stats.lost = items.filter(item => item.status === 'lost').length
|
||||||
|
this.stats.abandoned = items.filter(item => item.status === 'abandoned').length
|
||||||
|
this.stats.prohibited = items.filter(item => item.status === 'prohibited').length
|
||||||
|
|
||||||
// 获取最新物品
|
// 获取最新物品
|
||||||
this.recentItems = items.slice(0, 5)
|
this.recentItems = items.slice(0, 5)
|
||||||
@@ -177,7 +218,10 @@ export default {
|
|||||||
'available': 'success',
|
'available': 'success',
|
||||||
'in_use': 'warning',
|
'in_use': 'warning',
|
||||||
'maintenance': 'info',
|
'maintenance': 'info',
|
||||||
'damaged': 'danger'
|
'damaged': 'danger',
|
||||||
|
'lost': 'danger',
|
||||||
|
'abandoned': 'info',
|
||||||
|
'prohibited': 'warning',
|
||||||
}
|
}
|
||||||
return typeMap[status] || 'info'
|
return typeMap[status] || 'info'
|
||||||
},
|
},
|
||||||
@@ -186,7 +230,10 @@ export default {
|
|||||||
'available': '可用',
|
'available': '可用',
|
||||||
'in_use': '使用中',
|
'in_use': '使用中',
|
||||||
'maintenance': '维护中',
|
'maintenance': '维护中',
|
||||||
'damaged': '损坏'
|
'damaged': '损坏',
|
||||||
|
'lost': '丢失',
|
||||||
|
'abandoned': '已弃用',
|
||||||
|
'prohibited': '禁止借用',
|
||||||
}
|
}
|
||||||
return textMap[status] || '未知'
|
return textMap[status] || '未知'
|
||||||
}
|
}
|
||||||
@@ -195,43 +242,6 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.el-header {
|
|
||||||
background-color: #ffffff;
|
|
||||||
box-shadow: 0 2px 4px rgba(0,0,0,.12), 0 0 6px rgba(0,0,0,.04);
|
|
||||||
height: 60px !important;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 20px;
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-content {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
color: #409eff;
|
|
||||||
font-size: 20px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-menu {
|
|
||||||
border-bottom: none;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-menu .el-menu-item {
|
|
||||||
border-bottom: none;
|
|
||||||
height: 60px;
|
|
||||||
line-height: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard {
|
.dashboard {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
@@ -273,6 +283,22 @@ export default {
|
|||||||
background-color: #909399;
|
background-color: #909399;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stat-icon.damaged {
|
||||||
|
background-color: #f56c6c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-icon.lost {
|
||||||
|
background-color: #f59e0b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-icon.abandoned {
|
||||||
|
background-color: #8e8e8e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-icon.prohibited {
|
||||||
|
background-color: #409eff;
|
||||||
|
}
|
||||||
|
|
||||||
.stat-info h3 {
|
.stat-info h3 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
|
|||||||
@@ -1,28 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-header>
|
<AppHeader />
|
||||||
<div class="header-content">
|
|
||||||
<h1 class="logo">爱特工作室物品管理系统</h1>
|
|
||||||
<el-menu
|
|
||||||
mode="horizontal"
|
|
||||||
:default-active="$route.path"
|
|
||||||
router
|
|
||||||
class="nav-menu"
|
|
||||||
>
|
|
||||||
<el-menu-item index="/">
|
|
||||||
<el-icon><House /></el-icon>
|
|
||||||
首页
|
|
||||||
</el-menu-item>
|
|
||||||
<el-menu-item index="/items">
|
|
||||||
<el-icon><Box /></el-icon>
|
|
||||||
物品管理
|
|
||||||
</el-menu-item>
|
|
||||||
<el-menu-item index="/usage">
|
|
||||||
<el-icon><Document /></el-icon>
|
|
||||||
使用记录
|
|
||||||
</el-menu-item>
|
|
||||||
</el-menu>
|
|
||||||
</div>
|
|
||||||
</el-header>
|
|
||||||
<div class="item-detail">
|
<div class="item-detail">
|
||||||
<div class="detail-header">
|
<div class="detail-header">
|
||||||
<el-button @click="$router.go(-1)" style="margin-bottom: 20px;">
|
<el-button @click="$router.go(-1)" style="margin-bottom: 20px;">
|
||||||
@@ -60,11 +37,17 @@
|
|||||||
<el-option label="使用中" value="in_use" />
|
<el-option label="使用中" value="in_use" />
|
||||||
<el-option label="维护中" value="maintenance" />
|
<el-option label="维护中" value="maintenance" />
|
||||||
<el-option label="损坏" value="damaged" />
|
<el-option label="损坏" value="damaged" />
|
||||||
|
<el-option label="丢失" value="lost" />
|
||||||
|
<el-option label="已弃用" value="abandoned" />
|
||||||
|
<el-option label="禁止借用" value="prohibited" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="位置">
|
<el-form-item label="位置">
|
||||||
<el-input v-model="editableItem.location" />
|
<el-input v-model="editableItem.location" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="所有者">
|
||||||
|
<el-input v-model="editableItem.owner" :disabled="!editMode" placeholder="请输入所有者姓名" />
|
||||||
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="购买日期">
|
<el-form-item label="购买日期">
|
||||||
@@ -160,10 +143,14 @@
|
|||||||
<script>
|
<script>
|
||||||
import { itemService } from '../services/api'
|
import { itemService } from '../services/api'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
import AppHeader from '../components/AppHeader.vue'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ItemDetail',
|
name: 'ItemDetail',
|
||||||
|
components: {
|
||||||
|
AppHeader
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
id: {
|
id: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -220,25 +207,6 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.el-header {
|
|
||||||
background-color: #ffffff;
|
|
||||||
box-shadow: 0 2px 4px rgba(0,0,0,.12), 0 0 6px rgba(0,0,0,.04);
|
|
||||||
height: 60px !important;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 20px;
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-content {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-detail {
|
.item-detail {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-header>
|
<AppHeader />
|
||||||
<div class="header-content">
|
|
||||||
<h1 class="logo">爱特工作室物品管理系统</h1>
|
|
||||||
<el-menu
|
|
||||||
mode="horizontal"
|
|
||||||
:default-active="$route.path"
|
|
||||||
router
|
|
||||||
class="nav-menu"
|
|
||||||
>
|
|
||||||
<el-menu-item index="/">
|
|
||||||
<el-icon><House /></el-icon>
|
|
||||||
首页
|
|
||||||
</el-menu-item>
|
|
||||||
<el-menu-item index="/items">
|
|
||||||
<el-icon><Box /></el-icon>
|
|
||||||
物品管理
|
|
||||||
</el-menu-item>
|
|
||||||
<el-menu-item index="/usage">
|
|
||||||
<el-icon><Document /></el-icon>
|
|
||||||
使用记录
|
|
||||||
</el-menu-item>
|
|
||||||
</el-menu>
|
|
||||||
</div>
|
|
||||||
</el-header>
|
|
||||||
<div class="item-list">
|
<div class="item-list">
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<el-button type="primary" @click="showAddDialog = true">
|
<el-button type="primary" @click="showAddDialog = true">
|
||||||
@@ -46,6 +23,9 @@
|
|||||||
<el-option label="使用中" value="in_use" />
|
<el-option label="使用中" value="in_use" />
|
||||||
<el-option label="维护中" value="maintenance" />
|
<el-option label="维护中" value="maintenance" />
|
||||||
<el-option label="损坏" value="damaged" />
|
<el-option label="损坏" value="damaged" />
|
||||||
|
<el-option label="丢失" value="lost" />
|
||||||
|
<el-option label="已弃用" value="abandoned" />
|
||||||
|
<el-option label="禁止借用" value="prohibited" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -61,6 +41,14 @@
|
|||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column prop="owner" label="所有者">
|
||||||
|
<template #default="scope">
|
||||||
|
<span v-if="scope.row.owner">
|
||||||
|
{{ scope.row.owner }}
|
||||||
|
</span>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="current_user" label="当前使用者">
|
<el-table-column prop="current_user" label="当前使用者">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span v-if="scope.row.current_user">
|
<span v-if="scope.row.current_user">
|
||||||
@@ -122,6 +110,9 @@
|
|||||||
<el-form-item label="购买日期">
|
<el-form-item label="购买日期">
|
||||||
<el-date-picker v-model="newItem.purchase_date" type="date" />
|
<el-date-picker v-model="newItem.purchase_date" type="date" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="所有者">
|
||||||
|
<el-input v-model="newItem.owner" placeholder="请输入所有者姓名" />
|
||||||
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="showAddDialog = false">取消</el-button>
|
<el-button @click="showAddDialog = false">取消</el-button>
|
||||||
@@ -173,15 +164,64 @@
|
|||||||
<el-button type="primary" @click="confirmReturn">确认归还</el-button>
|
<el-button type="primary" @click="confirmReturn">确认归还</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 编辑物品对话框 -->
|
||||||
|
<el-dialog v-model="showEditDialog" title="编辑物品" width="600px">
|
||||||
|
<el-form :model="editForm" label-width="100px" :rules="itemRules" ref="editForm">
|
||||||
|
<el-form-item label="物品名称" prop="name">
|
||||||
|
<el-input v-model="editForm.name" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="序列号" prop="serial_number">
|
||||||
|
<el-input v-model="editForm.serial_number" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="类别" prop="category">
|
||||||
|
<el-input v-model="editForm.category" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态">
|
||||||
|
<el-select v-model="editForm.status">
|
||||||
|
<el-option label="可用" value="available" />
|
||||||
|
<el-option label="使用中" value="in_use" />
|
||||||
|
<el-option label="维护中" value="maintenance" />
|
||||||
|
<el-option label="损坏" value="damaged" />
|
||||||
|
<el-option label="丢失" value="lost" />
|
||||||
|
<el-option label="已弃用" value="abandoned" />
|
||||||
|
<el-option label="禁止借用" value="prohibited" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="描述">
|
||||||
|
<el-input type="textarea" v-model="editForm.description" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="位置">
|
||||||
|
<el-input v-model="editForm.location" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="价值">
|
||||||
|
<el-input-number v-model="editForm.value" :precision="2" :min="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="购买日期">
|
||||||
|
<el-date-picker v-model="editForm.purchase_date" type="date" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="所有者" prop="owner_id">
|
||||||
|
<el-input v-model="editForm.owner" placeholder="请输入所有者姓名" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="showEditDialog = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="updateItem">保存修改</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { itemService, userService } from '../services/api'
|
import { itemService, userService } from '../services/api'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
import AppHeader from '../components/AppHeader.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ItemList',
|
name: 'ItemList',
|
||||||
|
components: {
|
||||||
|
AppHeader
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
items: [],
|
items: [],
|
||||||
@@ -192,6 +232,7 @@ export default {
|
|||||||
showAddDialog: false,
|
showAddDialog: false,
|
||||||
showBorrowDialog: false,
|
showBorrowDialog: false,
|
||||||
showReturnDialog: false,
|
showReturnDialog: false,
|
||||||
|
showEditDialog: false,
|
||||||
currentItem: null,
|
currentItem: null,
|
||||||
newItem: {
|
newItem: {
|
||||||
name: '',
|
name: '',
|
||||||
@@ -200,7 +241,8 @@ export default {
|
|||||||
description: '',
|
description: '',
|
||||||
location: '',
|
location: '',
|
||||||
value: null,
|
value: null,
|
||||||
purchase_date: null
|
purchase_date: null,
|
||||||
|
owner: ''
|
||||||
},
|
},
|
||||||
borrowForm: {
|
borrowForm: {
|
||||||
user_id: null,
|
user_id: null,
|
||||||
@@ -212,6 +254,18 @@ export default {
|
|||||||
condition_after: '',
|
condition_after: '',
|
||||||
return_notes: ''
|
return_notes: ''
|
||||||
},
|
},
|
||||||
|
editForm: {
|
||||||
|
id: null,
|
||||||
|
name: '',
|
||||||
|
serial_number: '',
|
||||||
|
category: '',
|
||||||
|
status: '',
|
||||||
|
description: '',
|
||||||
|
location: '',
|
||||||
|
value: null,
|
||||||
|
purchase_date: null,
|
||||||
|
owner: ''
|
||||||
|
},
|
||||||
itemRules: {
|
itemRules: {
|
||||||
name: [{ required: true, message: '请输入物品名称', trigger: 'blur' }],
|
name: [{ required: true, message: '请输入物品名称', trigger: 'blur' }],
|
||||||
serial_number: [{ required: true, message: '请输入序列号', trigger: 'blur' }],
|
serial_number: [{ required: true, message: '请输入序列号', trigger: 'blur' }],
|
||||||
@@ -272,8 +326,9 @@ export default {
|
|||||||
this.$router.push(`/items/${id}`)
|
this.$router.push(`/items/${id}`)
|
||||||
},
|
},
|
||||||
editItem(item) {
|
editItem(item) {
|
||||||
// TODO: 实现编辑功能
|
this.currentItem = item
|
||||||
ElMessage.info('编辑功能开发中')
|
this.editForm = { ...item }
|
||||||
|
this.showEditDialog = true
|
||||||
},
|
},
|
||||||
borrowItem(item) {
|
borrowItem(item) {
|
||||||
this.currentItem = item
|
this.currentItem = item
|
||||||
@@ -317,7 +372,8 @@ export default {
|
|||||||
description: '',
|
description: '',
|
||||||
location: '',
|
location: '',
|
||||||
value: null,
|
value: null,
|
||||||
purchase_date: null
|
purchase_date: null,
|
||||||
|
owner: ''
|
||||||
}
|
}
|
||||||
await this.loadItems()
|
await this.loadItems()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -352,12 +408,38 @@ export default {
|
|||||||
ElMessage.error('归还失败')
|
ElMessage.error('归还失败')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async updateItem() {
|
||||||
|
try {
|
||||||
|
await this.$refs.editForm.validate()
|
||||||
|
|
||||||
|
const itemData = { ...this.editForm }
|
||||||
|
|
||||||
|
// 格式化购买日期
|
||||||
|
if (itemData.purchase_date) {
|
||||||
|
const date = new Date(itemData.purchase_date)
|
||||||
|
itemData.purchase_date = date.getFullYear() + '-' +
|
||||||
|
String(date.getMonth() + 1).padStart(2, '0') + '-' +
|
||||||
|
String(date.getDate()).padStart(2, '0')
|
||||||
|
}
|
||||||
|
|
||||||
|
await itemService.updateItem(itemData.id, itemData)
|
||||||
|
ElMessage.success('物品信息更新成功')
|
||||||
|
this.showEditDialog = false
|
||||||
|
await this.loadItems()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('更新物品失败:', error)
|
||||||
|
ElMessage.error('更新物品失败')
|
||||||
|
}
|
||||||
|
},
|
||||||
getStatusType(status) {
|
getStatusType(status) {
|
||||||
const typeMap = {
|
const typeMap = {
|
||||||
'available': 'success',
|
'available': 'success',
|
||||||
'in_use': 'warning',
|
'in_use': 'warning',
|
||||||
'maintenance': 'info',
|
'maintenance': 'info',
|
||||||
'damaged': 'danger'
|
'damaged': 'danger',
|
||||||
|
'lost': 'danger',
|
||||||
|
'abandoned': 'info',
|
||||||
|
'prohibited': 'warning'
|
||||||
}
|
}
|
||||||
return typeMap[status] || 'info'
|
return typeMap[status] || 'info'
|
||||||
},
|
},
|
||||||
@@ -366,7 +448,10 @@ export default {
|
|||||||
'available': '可用',
|
'available': '可用',
|
||||||
'in_use': '使用中',
|
'in_use': '使用中',
|
||||||
'maintenance': '维护中',
|
'maintenance': '维护中',
|
||||||
'damaged': '损坏'
|
'damaged': '损坏',
|
||||||
|
'lost': '丢失',
|
||||||
|
'abandoned': '已弃用',
|
||||||
|
'prohibited': '禁止借用'
|
||||||
}
|
}
|
||||||
return textMap[status] || '未知'
|
return textMap[status] || '未知'
|
||||||
}
|
}
|
||||||
@@ -375,25 +460,6 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.el-header {
|
|
||||||
background-color: #ffffff;
|
|
||||||
box-shadow: 0 2px 4px rgba(0,0,0,.12), 0 0 6px rgba(0,0,0,.04);
|
|
||||||
height: 60px !important;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 20px;
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-content {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-list {
|
.item-list {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-header>
|
<AppHeader />
|
||||||
<div class="header-content">
|
|
||||||
<h1 class="logo">爱特工作室物品管理系统</h1>
|
|
||||||
<el-menu
|
|
||||||
mode="horizontal"
|
|
||||||
:default-active="$route.path"
|
|
||||||
router
|
|
||||||
class="nav-menu"
|
|
||||||
>
|
|
||||||
<el-menu-item index="/">
|
|
||||||
<el-icon><House /></el-icon>
|
|
||||||
首页
|
|
||||||
</el-menu-item>
|
|
||||||
<el-menu-item index="/items">
|
|
||||||
<el-icon><Box /></el-icon>
|
|
||||||
物品管理
|
|
||||||
</el-menu-item>
|
|
||||||
<el-menu-item index="/usage">
|
|
||||||
<el-icon><Document /></el-icon>
|
|
||||||
使用记录
|
|
||||||
</el-menu-item>
|
|
||||||
</el-menu>
|
|
||||||
</div>
|
|
||||||
</el-header>
|
|
||||||
<div class="item-usage">
|
<div class="item-usage">
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<h2>使用记录</h2>
|
<h2>使用记录</h2>
|
||||||
@@ -176,9 +153,13 @@
|
|||||||
import { usageService, userService } from '../services/api'
|
import { usageService, userService } from '../services/api'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
import AppHeader from '../components/AppHeader.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ItemUsage',
|
name: 'ItemUsage',
|
||||||
|
components: {
|
||||||
|
AppHeader
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
usages: [],
|
usages: [],
|
||||||
@@ -312,25 +293,6 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.el-header {
|
|
||||||
background-color: #ffffff;
|
|
||||||
box-shadow: 0 2px 4px rgba(0,0,0,.12), 0 0 6px rgba(0,0,0,.04);
|
|
||||||
height: 60px !important;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 20px;
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-content {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-usage {
|
.item-usage {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user