You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

590 lines
12 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="page-container">
<view class="header-section">
<view class="back-btn" @click="goBack">
<text class="back-icon"></text>
<text class="back-text">返回</text>
</view>
<text class="header-title">设备关键件</text>
</view>
<view class="search-section">
<view class="search-wrapper">
<view class="search-icon">
<text class="iconfont icon-search"></text>
</view>
<input
v-model="searchKeyword"
class="search-input"
type="text"
placeholder="请输入关键件编码或名称"
placeholder-class="input-placeholder"
@input="handleSearch"
/>
<view v-if="searchKeyword" class="clear-btn" @click="clearSearch">
<text class="clear-icon">×</text>
</view>
</view>
</view>
<scroll-view scroll-y class="content-scroll">
<view class="keypart-list">
<view
v-for="(item, index) in keypartList"
:key="index"
class="keypart-card"
>
<view class="card-header">
<view class="header-left">
<text class="keypart-name">{{ item.name }}</text>
<text class="keypart-code">编码: {{ item.code }}</text>
</view>
<view class="card-actions">
<view class="action-btn edit-btn" @click.stop="handleEdit(item)">
<text class="action-icon">✎</text>
</view>
<view class="action-btn delete-btn" @click.stop="handleDelete(item)">
<text class="action-icon">🗑</text>
</view>
</view>
</view>
<view class="card-body">
<view class="card-row">
<text class="card-label">描述</text>
<text class="card-value">{{ item.description || '-' }}</text>
</view>
<view class="card-row">
<text class="card-label">数量</text>
<text class="card-value">{{ item.count }}</text>
</view>
<view class="card-row">
<text class="card-label">备注</text>
<text class="card-value">{{ item.remark || '-' }}</text>
</view>
</view>
</view>
</view>
</scroll-view>
<view class="add-btn" @click="showAddForm">
<text class="add-icon">+</text>
</view>
<uni-popup ref="addPopup" type="center" background-color="#fff">
<view class="popup-content">
<view class="popup-header">
<text class="popup-title">{{ isEdit ? '编辑关键件' : '新增关键件' }}</text>
<view class="popup-close" @click="hideAddForm">
<text class="close-icon">×</text>
</view>
</view>
<view class="form-content">
<view class="form-item">
<text class="form-label">关键件编码 <text class="required">*</text></text>
<input
v-model="formData.code"
class="form-input"
type="text"
placeholder="请输入关键件编码"
/>
</view>
<view class="form-item">
<text class="form-label">关键件名称 <text class="required">*</text></text>
<input
v-model="formData.name"
class="form-input"
type="text"
placeholder="请输入关键件名称"
/>
</view>
<view class="form-item">
<text class="form-label">描述</text>
<textarea
v-model="formData.description"
class="form-textarea"
placeholder="请输入描述"
:maxlength="200"
/>
</view>
<view class="form-item">
<text class="form-label">数量</text>
<input
v-model="formData.count"
class="form-input"
type="number"
placeholder="请输入数量"
/>
</view>
<view class="form-item">
<text class="form-label">备注</text>
<textarea
v-model="formData.remark"
class="form-textarea"
placeholder="请输入备注"
:maxlength="200"
/>
</view>
</view>
<view class="form-footer">
<view class="footer-btn cancel-btn" @click="hideAddForm">
<text class="btn-text">取消</text>
</view>
<view class="footer-btn confirm-btn" @click="handleSave">
<text class="btn-text"></text>
</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script setup>
import { ref, reactive } from 'vue';
const addPopup = ref(null);
const searchKeyword = ref('');
const isEdit = ref(false);
const formData = reactive({
code: '',
name: '',
description: '',
count: '',
remark: ''
});
const keypartList = reactive([
{ code: 'KP001', name: '电机', description: 'Y2系列三相异步电机', count: 2, remark: '设备核心动力部件' },
{ code: 'KP002', name: '变频器', description: '37kW变频器', count: 1, remark: '电机调速控制' },
{ code: 'KP003', name: 'PLC控制器', description: '西门子S7-1200', count: 1, remark: '设备控制系统' },
{ code: 'KP004', name: '伺服驱动器', description: '2kW伺服驱动器', count: 2, remark: '精确位置控制' },
{ code: 'KP005', name: '滚珠丝杠', description: 'F4004滚珠丝杠', count: 2, remark: '线性传动部件' },
{ code: 'KP006', name: '直线导轨', description: 'HGR20直线导轨', count: 4, remark: '滑动支撑部件' }
]);
function goBack() {
uni.navigateBack();
}
function handleSearch() {
console.log('搜索:', searchKeyword.value);
}
function clearSearch() {
searchKeyword.value = '';
}
function handleEdit(item) {
isEdit.value = true;
formData.code = item.code;
formData.name = item.name;
formData.description = item.description;
formData.count = item.count;
formData.remark = item.remark;
addPopup.value.open();
}
function handleDelete(item) {
uni.showModal({
title: '确认删除',
content: `确定要删除"${item.name}"吗?`,
success: () => {
uni.showToast({
title: '删除成功',
icon: 'success'
});
}
});
}
function showAddForm() {
isEdit.value = false;
resetForm();
addPopup.value.open();
}
function hideAddForm() {
addPopup.value.close();
resetForm();
}
function resetForm() {
formData.code = '';
formData.name = '';
formData.description = '';
formData.count = '';
formData.remark = '';
}
function handleSave() {
if (!formData.code || !formData.name) {
uni.showToast({
title: '请填写必填项',
icon: 'none'
});
return;
}
uni.showToast({
title: '保存成功',
icon: 'success'
});
hideAddForm();
resetForm();
}
</script>
<style lang="scss" scoped>
.page-container {
min-height: 100vh;
background-color: #f0f2f5;
}
.header-section {
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
padding: 60rpx 40rpx 40rpx 30rpx;
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
.back-btn {
display: flex;
align-items: center;
position: absolute;
left: 30rpx;
top: 50%;
transform: translateY(-50%);
&:active {
opacity: 0.7;
}
.back-icon {
font-size: 48rpx;
color: #ffffff;
margin-right: 8rpx;
}
.back-text {
font-size: 28rpx;
color: #ffffff;
}
}
.header-title {
font-size: 34rpx;
font-weight: bold;
color: #ffffff;
}
.search-section {
background: #ffffff;
padding: 24rpx 30rpx;
margin-bottom: 20rpx;
}
.search-wrapper {
display: flex;
align-items: center;
background: #f5f7fa;
border-radius: 48rpx;
padding: 0 24rpx;
}
.search-icon {
margin-right: 20rpx;
.iconfont {
font-size: 36rpx;
color: #666666;
}
}
.search-input {
flex: 1;
height: 72rpx;
font-size: 28rpx;
color: #333333;
background: transparent;
}
.input-placeholder {
color: #999999;
}
.clear-btn {
width: 48rpx;
height: 48rpx;
display: flex;
align-items: center;
justify-content: center;
&:active {
opacity: 0.7;
}
.clear-icon {
font-size: 36rpx;
color: #999999;
}
}
.content-scroll {
flex: 1;
height: calc(100vh - 260rpx);
}
.keypart-list {
display: flex;
flex-direction: column;
align-items: center;
padding: 0 24rpx;
padding-bottom: 120rpx;
}
.keypart-card {
width: 100%;
background: #ffffff;
border-radius: 20rpx;
padding: 28rpx;
margin-bottom: 20rpx;
box-sizing: border-box;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
padding-bottom: 20rpx;
border-bottom: 2rpx solid #f0f2f5;
}
.header-left {
display: flex;
flex-direction: column;
}
.keypart-name {
font-size: 32rpx;
font-weight: 600;
color: #1a3a5c;
margin-bottom: 8rpx;
}
.keypart-code {
font-size: 24rpx;
color: #999999;
}
.card-actions {
display: flex;
gap: 16rpx;
}
.action-btn {
width: 64rpx;
height: 64rpx;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
&:active {
opacity: 0.7;
transform: scale(0.95);
}
.action-icon {
font-size: 32rpx;
color: #ffffff;
}
}
.edit-btn {
background: #1a3a5c;
}
.delete-btn {
background: #ff4d4f;
}
.card-body {
display: flex;
flex-direction: column;
}
.card-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16rpx;
&:last-child {
margin-bottom: 0;
}
}
.card-label {
font-size: 26rpx;
color: #999999;
}
.card-value {
font-size: 28rpx;
color: #333333;
flex: 1;
text-align: right;
}
.add-btn {
position: fixed;
bottom: 120rpx;
right: 30rpx;
width: 100rpx;
height: 100rpx;
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 24rpx rgba(26, 58, 92, 0.3);
z-index: 999;
&:active {
transform: scale(0.95);
}
.add-icon {
font-size: 60rpx;
color: #ffffff;
font-weight: bold;
}
}
.popup-content {
width: 600rpx;
background: #ffffff;
border-radius: 20rpx;
overflow: hidden;
}
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx;
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
}
.popup-title {
font-size: 32rpx;
font-weight: 600;
color: #ffffff;
}
.popup-close {
width: 48rpx;
height: 48rpx;
display: flex;
align-items: center;
justify-content: center;
&:active {
opacity: 0.7;
}
.close-icon {
font-size: 36rpx;
color: #ffffff;
}
}
.form-content {
padding: 32rpx;
}
.form-item {
margin-bottom: 24rpx;
}
.form-label {
display: block;
font-size: 28rpx;
color: #333333;
margin-bottom: 12rpx;
}
.required {
color: #ff4d4f;
margin-left: 4rpx;
}
.form-input {
width: 100%;
height: 80rpx;
padding: 0 24rpx;
font-size: 28rpx;
background: #f5f7fa;
border-radius: 12rpx;
border: 2rpx solid #e8eaed;
box-sizing: border-box;
}
.form-textarea {
width: 100%;
min-height: 120rpx;
padding: 16rpx 24rpx;
font-size: 28rpx;
background: #f5f7fa;
border-radius: 12rpx;
border: 2rpx solid #e8eaed;
box-sizing: border-box;
resize: none;
}
.form-footer {
display: flex;
gap: 16rpx;
margin-top: 32rpx;
}
.footer-btn {
flex: 1;
height: 88rpx;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
&:active {
opacity: 0.8;
}
.btn-text {
font-size: 28rpx;
font-weight: 500;
}
}
.cancel-btn {
background: #f5f7fa;
.btn-text {
color: #666666;
}
}
.confirm-btn {
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
.btn-text {
color: #ffffff;
}
}
</style>