feat/ui: 优化订单列表和详情页面,更新登录界面
- 移除 components.d.ts 中未使用的 VanCheckbox 组件引用 - 在 Detail 页面添加常用审批意见标签功能 - 调整 List 页面样式,优化搜索栏设计- 更新 Login 页面布局和样式,移除不必要的元素master
parent
411253a277
commit
92dd433eee
|
|
@ -11,7 +11,6 @@ declare module 'vue' {
|
|||
RouterView: typeof import('vue-router')['RouterView']
|
||||
VanButton: typeof import('vant/es')['Button']
|
||||
VanCellGroup: typeof import('vant/es')['CellGroup']
|
||||
VanCheckbox: typeof import('vant/es')['Checkbox']
|
||||
VanEmpty: typeof import('vant/es')['Empty']
|
||||
VanField: typeof import('vant/es')['Field']
|
||||
VanForm: typeof import('vant/es')['Form']
|
||||
|
|
@ -26,5 +25,6 @@ declare module 'vue' {
|
|||
VanSteps: typeof import('vant/es')['Steps']
|
||||
VanTab: typeof import('vant/es')['Tab']
|
||||
VanTabs: typeof import('vant/es')['Tabs']
|
||||
VanTag: typeof import('vant/es')['Tag']
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -372,7 +372,7 @@
|
|||
v-model:show="approvalDialogVisible"
|
||||
position="bottom"
|
||||
round
|
||||
:style="{ height: '40%' }"
|
||||
:style="{ height: '50%' }"
|
||||
>
|
||||
<div class="approval-dialog">
|
||||
<div class="dialog-header">
|
||||
|
|
@ -380,6 +380,25 @@
|
|||
<van-icon name="cross" @click="approvalDialogVisible = false"/>
|
||||
</div>
|
||||
<div class="dialog-body">
|
||||
<!-- 默认意见标签 -->
|
||||
<div class="opinion-tags">
|
||||
<div class="tags-title">常用意见</div>
|
||||
<div class="tags-container">
|
||||
<van-tag
|
||||
v-for="tag in getOpinionTags()"
|
||||
:key="tag"
|
||||
:type="selectedTag === tag ? 'primary' : 'default'"
|
||||
size="medium"
|
||||
@click="selectTag(tag)"
|
||||
class="opinion-tag"
|
||||
>
|
||||
{{ tag }}
|
||||
</van-tag>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 意见输入框 -->
|
||||
<div class="opinion-input">
|
||||
<van-field
|
||||
v-model="approvalOpinion"
|
||||
type="textarea"
|
||||
|
|
@ -390,6 +409,7 @@
|
|||
show-word-limit
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dialog-footer">
|
||||
<van-button
|
||||
type="primary"
|
||||
|
|
@ -432,6 +452,7 @@ const approvalDialogVisible = ref(false)
|
|||
const approvalOpinion = ref('')
|
||||
const currentApprovalStatus = ref<ApprovalStatus>(3)
|
||||
const submitting = ref(false)
|
||||
const selectedTag = ref('')
|
||||
|
||||
// Tab页签
|
||||
const activeTab = ref('order')
|
||||
|
|
@ -542,9 +563,48 @@ const previewFile = (file: AttachmentFile) => {
|
|||
const showApprovalDialog = (status: ApprovalStatus) => {
|
||||
currentApprovalStatus.value = status
|
||||
approvalOpinion.value = ''
|
||||
selectedTag.value = ''
|
||||
approvalDialogVisible.value = true
|
||||
}
|
||||
|
||||
// 获取默认意见标签
|
||||
const getOpinionTags = () => {
|
||||
if (currentApprovalStatus.value === 0) {
|
||||
// 驳回常用意见
|
||||
return [
|
||||
'资料不齐全,请补充相关文件',
|
||||
'订单金额需要重新核实',
|
||||
'客户信息有误,请修正',
|
||||
'产品配置不符合要求',
|
||||
'需要提供更多技术细节',
|
||||
'合同条款需要调整'
|
||||
]
|
||||
} else {
|
||||
// 通过常用意见
|
||||
return [
|
||||
'审核通过,订单信息完整',
|
||||
'符合公司政策,同意执行',
|
||||
'客户资质良好,建议通过',
|
||||
'产品配置合理,批准发货',
|
||||
'风险可控,同意此订单',
|
||||
'经审查无误,予以批准'
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// 选择标签
|
||||
const selectTag = (tag: string) => {
|
||||
if (selectedTag.value === tag) {
|
||||
// 如果点击的是已选中的标签,则取消选择并清空输入框
|
||||
selectedTag.value = ''
|
||||
approvalOpinion.value = ''
|
||||
} else {
|
||||
// 选择新标签并填入输入框
|
||||
selectedTag.value = tag
|
||||
approvalOpinion.value = tag
|
||||
}
|
||||
}
|
||||
|
||||
// 提交审批
|
||||
const submitApproval = async () => {
|
||||
if (!currentOrder.value || !currentOrder.value.todo) {
|
||||
|
|
@ -846,6 +906,7 @@ onMounted(async () => {
|
|||
.dialog-body {
|
||||
flex: 1;
|
||||
padding: var(--spacing-lg);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
|
|
@ -854,6 +915,45 @@ onMounted(async () => {
|
|||
}
|
||||
}
|
||||
|
||||
// 意见标签样式
|
||||
.opinion-tags {
|
||||
margin-bottom: var(--spacing-lg);
|
||||
|
||||
.tags-title {
|
||||
font-size: 14px;
|
||||
color: var(--text-color-secondary);
|
||||
margin-bottom: var(--spacing-md);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.tags-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--spacing-sm);
|
||||
|
||||
.opinion-tag {
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.opinion-input {
|
||||
.van-field {
|
||||
border: 1px solid var(--divider-color);
|
||||
border-radius: var(--border-radius-sm);
|
||||
background: var(--background-color-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.van-steps--vertical) {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,22 @@
|
|||
<template>
|
||||
<div class="order-list-page">
|
||||
<!-- 搜索栏 -->
|
||||
<div class="search-container">
|
||||
<van-search
|
||||
v-model="searchKeyword"
|
||||
placeholder="搜索订单编号、客户名称"
|
||||
@search="handleSearch"
|
||||
@clear="handleClear"
|
||||
/>
|
||||
class="custom-search"
|
||||
>
|
||||
<template #left-icon>
|
||||
<svg class="search-icon" viewBox="0 0 24 24" fill="none">
|
||||
<circle cx="11" cy="11" r="8" stroke="currentColor" stroke-width="2"/>
|
||||
<path d="M21 21L16.65 16.65" stroke="currentColor" stroke-width="2"/>
|
||||
</svg>
|
||||
</template>
|
||||
</van-search>
|
||||
</div>
|
||||
|
||||
<!-- 下拉刷新 -->
|
||||
<van-pull-refresh v-model="refreshing" @refresh="onRefresh">
|
||||
|
|
@ -134,39 +144,25 @@ onMounted(() => {
|
|||
<style lang="scss" scoped>
|
||||
.order-list-page {
|
||||
min-height: 100vh;
|
||||
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
||||
padding: 20px;
|
||||
background: #ffffff;
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.order-item {
|
||||
background: white;
|
||||
background: #ffffff;
|
||||
margin-bottom: 16px;
|
||||
padding: 20px;
|
||||
padding: 16px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 4px;
|
||||
background: linear-gradient(90deg, #1989fa, #07c160);
|
||||
}
|
||||
transition: all 0.2s ease;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid #f0f0f0;
|
||||
|
||||
&:active {
|
||||
transform: translateY(2px);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.1);
|
||||
transform: translateY(1px);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -182,35 +178,39 @@ onMounted(() => {
|
|||
.order-code {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
font-size: 12px;
|
||||
padding: 4px 10px;
|
||||
border-radius: 20px;
|
||||
padding: 4px 12px;
|
||||
border-radius: 12px;
|
||||
font-weight: 500;
|
||||
|
||||
&.pending {
|
||||
background-color: #FFF7E6;
|
||||
color: #FA8C16;
|
||||
background: #FFF3E0;
|
||||
color: #FF9800;
|
||||
border: 1px solid #FFE0B2;
|
||||
}
|
||||
|
||||
&.approved {
|
||||
background-color: #F6FFED;
|
||||
color: #52C41A;
|
||||
background: #E8F5E8;
|
||||
color: #4CAF50;
|
||||
border: 1px solid #C8E6C9;
|
||||
}
|
||||
|
||||
&.rejected {
|
||||
background-color: #FFF2F0;
|
||||
color: #FF4D4F;
|
||||
background: #FFEBEE;
|
||||
color: #F44336;
|
||||
border: 1px solid #FFCDD2;
|
||||
}
|
||||
}
|
||||
|
||||
.order-info {
|
||||
.info-row {
|
||||
display: flex;
|
||||
margin-bottom: 12px;
|
||||
margin-bottom: 8px;
|
||||
align-items: center;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
|
|
@ -218,19 +218,22 @@ onMounted(() => {
|
|||
|
||||
.label {
|
||||
width: 80px;
|
||||
color: #666;
|
||||
color: #666666;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.value {
|
||||
flex: 1;
|
||||
color: #333;
|
||||
color: #333333;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
word-break: break-all;
|
||||
line-height: 1.4;
|
||||
|
||||
&.amount {
|
||||
color: #FF6600;
|
||||
color: #1976D2;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
|
@ -238,31 +241,71 @@ onMounted(() => {
|
|||
}
|
||||
|
||||
.empty-state {
|
||||
padding: 60px 20px;
|
||||
padding: 80px 20px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
|
||||
:deep(.van-empty) {
|
||||
.van-empty__image {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
filter: drop-shadow(0 8px 32px rgba(102, 126, 234, 0.2));
|
||||
animation: float 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.van-empty__description {
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
font-size: 18px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
font-weight: 500;
|
||||
margin-top: 24px;
|
||||
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索栏容器
|
||||
.search-container {
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
// 搜索栏样式优化
|
||||
:deep(.van-search) {
|
||||
margin-bottom: 16px;
|
||||
border-radius: 12px;
|
||||
:deep(.custom-search) {
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12), 0 2px 8px rgba(0, 0, 0, 0.08);
|
||||
backdrop-filter: blur(20px);
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:focus-within {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15), 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.van-search__content {
|
||||
background: white;
|
||||
background: transparent;
|
||||
padding: 12px 16px;
|
||||
|
||||
.van-field__control {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
|
||||
&::placeholder {
|
||||
color: #999;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
color: #666;
|
||||
margin-right: 8px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -4,12 +4,31 @@
|
|||
<div class="login-header">
|
||||
<div class="logo-placeholder">
|
||||
<svg class="logo-icon" viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="40" fill="#1989fa" />
|
||||
<path d="M30,50 L45,65 L70,35" stroke="white" stroke-width="8" fill="none" />
|
||||
<!-- 立体盒子效果 -->
|
||||
<defs>
|
||||
<linearGradient id="topFace" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#4A90E2;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#357ABD;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="leftFace" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#357ABD;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#2E6B9D;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient id="rightFace" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#2E6B9D;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#1E4A6B;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<!-- 立体盒子 -->
|
||||
<!-- 顶面 -->
|
||||
<polygon points="20,35 50,20 80,35 50,50" fill="url(#topFace)" />
|
||||
<!-- 左面 -->
|
||||
<polygon points="20,35 50,50 50,80 20,65" fill="url(#leftFace)" />
|
||||
<!-- 右面 -->
|
||||
<polygon points="50,50 80,35 80,65 50,80" fill="url(#rightFace)" />
|
||||
</svg>
|
||||
</div>
|
||||
<h1 class="login-title">OMS</h1>
|
||||
<p class="login-subtitle">Order Management System</p>
|
||||
<h1 class="login-title">欢迎登录OMS</h1>
|
||||
</div>
|
||||
|
||||
<van-form @submit="onSubmit" class="login-form">
|
||||
|
|
@ -17,18 +36,11 @@
|
|||
<van-field
|
||||
v-model="username"
|
||||
name="username"
|
||||
label="用户名"
|
||||
placeholder="请输入用户名"
|
||||
:rules="[{ required: true, message: '请填写用户名' }]"
|
||||
label="账号"
|
||||
placeholder="请输入账号"
|
||||
:rules="[{ required: true, message: '请填写账号' }]"
|
||||
class="login-input"
|
||||
>
|
||||
<template #left-icon>
|
||||
<svg class="input-icon" viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="35" r="15" fill="none" stroke="#1989fa" stroke-width="8" />
|
||||
<path d="M25,85 Q50,65 75,85" stroke="#1989fa" stroke-width="8" fill="none" />
|
||||
</svg>
|
||||
</template>
|
||||
</van-field>
|
||||
/>
|
||||
|
||||
<van-field
|
||||
v-model="password"
|
||||
|
|
@ -38,33 +50,15 @@
|
|||
placeholder="请输入密码"
|
||||
:rules="[{ required: true, message: '请填写密码' }]"
|
||||
class="login-input"
|
||||
>
|
||||
<template #left-icon>
|
||||
<svg class="input-icon" viewBox="0 0 100 100">
|
||||
<rect x="20" y="40" width="60" height="40" rx="5" fill="none" stroke="#1989fa" stroke-width="8" />
|
||||
<circle cx="50" cy="25" r="10" fill="#1989fa" />
|
||||
</svg>
|
||||
</template>
|
||||
</van-field>
|
||||
/>
|
||||
</van-cell-group>
|
||||
|
||||
<div class="login-options">
|
||||
<van-checkbox v-model="rememberMe" name="rememberMe" checked-color="#1989fa">
|
||||
记住密码
|
||||
</van-checkbox>
|
||||
<a href="javascript:void(0)" class="forgot-password">忘记密码?</a>
|
||||
</div>
|
||||
|
||||
<div class="login-button-container">
|
||||
<van-button round block type="primary" native-type="submit" :loading="loading" class="login-button">
|
||||
登录
|
||||
</van-button>
|
||||
</div>
|
||||
</van-form>
|
||||
|
||||
<div class="login-footer">
|
||||
<p class="footer-text">© 2025 订单管理系统 - 安全可靠的订单管理平台</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
Loading…
Reference in New Issue