全局重命名: 序列号→身份证 (product.serial_number)
This commit is contained in:
@ -20,7 +20,7 @@
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-grid">
|
||||
<view class="info-item"><text class="label">序列号</text><text class="value sn">{{ product.serial_number }}</text></view>
|
||||
<view class="info-item"><text class="label">身份证</text><text class="value sn">{{ product.serial_number }}</text></view>
|
||||
<view class="info-item"><text class="label">物料名称</text><text class="value">{{ product.material_name || product.material_id || '—' }}</text></view>
|
||||
<view class="info-item"><text class="label">规格型号</text><text class="value">{{ product.spec_model || '—' }}</text></view>
|
||||
<view class="info-item"><text class="label">订单编号</text><text class="value">{{ product.order_no || '—' }}</text></view>
|
||||
@ -62,8 +62,8 @@
|
||||
<text class="popup-title">编辑产品</text>
|
||||
<view class="field-label">订单编号</view>
|
||||
<input v-model="editForm.order_no" class="popup-input" placeholder="请输入订单编号" />
|
||||
<view class="field-label" style="margin-top:10px;">外部序列号</view>
|
||||
<input v-model="editForm.external_serial" class="popup-input" placeholder="请输入外部序列号" />
|
||||
<view class="field-label" style="margin-top:10px;">外部身份证</view>
|
||||
<input v-model="editForm.external_serial" class="popup-input" placeholder="请输入外部身份证" />
|
||||
<view class="popup-btns"><button class="btn-cancel" @tap="editProductVisible = false">取消</button><button class="btn-primary" :disabled="editSaving" @tap="doEditProduct">{{ editSaving ? '保存中...' : '保存' }}</button></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
<!-- 手动输入 -->
|
||||
<view class="manual-input">
|
||||
<input v-model="serialNumber" class="input" type="text" maxlength="16"
|
||||
placeholder="手动输入16位序列号" @confirm="handleSearch" />
|
||||
placeholder="手动输入16位身份证" @confirm="handleSearch" />
|
||||
<button class="search-btn" @tap="handleSearch" :disabled="loading">
|
||||
{{ loading ? '查询中' : '查询' }}
|
||||
</button>
|
||||
@ -24,7 +24,7 @@
|
||||
<!-- 空状态 -->
|
||||
<view v-if="!loading && !error" class="empty">
|
||||
<text class="empty-icon">📱</text>
|
||||
<text class="empty-text">扫码或手动输入序列号查询产品进度</text>
|
||||
<text class="empty-text">扫码或手动输入身份证查询产品进度</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@ -43,7 +43,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
async doQuery(sn) {
|
||||
if (!sn || sn.length < 8) { this.error = "序列号至少需要 8 位"; return; }
|
||||
if (!sn || sn.length < 8) { this.error = "身份证至少需要 8 位"; return; }
|
||||
this.serialNumber = sn;
|
||||
this.lastScanned = sn;
|
||||
this.loading = true;
|
||||
|
||||
@ -2,24 +2,145 @@
|
||||
<view class="page">
|
||||
<view class="header">
|
||||
<text class="title">我的任务</text>
|
||||
<text class="subtitle">待处理和进行中的任务</text>
|
||||
</view>
|
||||
<view class="empty">
|
||||
<text class="empty-icon">📋</text>
|
||||
<text class="empty-text">暂无待办任务</text>
|
||||
|
||||
<!-- Tab 栏 — 固定顶部 -->
|
||||
<view class="tabs">
|
||||
<view v-for="t in TABS" :key="t.key"
|
||||
:class="['tab', tab === t.key ? 'tab-active' : '']"
|
||||
@tap="tab = t.key">{{ t.label }} ({{ countBy(t.key) }})</view>
|
||||
</view>
|
||||
|
||||
<!-- 内容区 -->
|
||||
<view v-if="loading" class="center">加载中...</view>
|
||||
<template v-else>
|
||||
<view v-if="filtered.length === 0" class="empty">
|
||||
<text class="empty-icon">📋</text>
|
||||
<text class="empty-text">{{ tab === 'all' ? '暂无待办任务' : '无此状态任务' }}</text>
|
||||
</view>
|
||||
<view v-for="task in filtered" :key="task.id" class="card" @tap="goDetail(task)">
|
||||
<view class="card-row">
|
||||
<text class="card-name">{{ task.task_name }}</text>
|
||||
<text :class="['card-status', statusColor(task.status)]">{{ statusLabel(task.status) }}</text>
|
||||
</view>
|
||||
<view class="card-meta">
|
||||
<text>身份证: {{ task.product_sn || '—' }}</text>
|
||||
<text>物料: {{ task.product_material || '—' }}</text>
|
||||
</view>
|
||||
<view class="card-time">创建: {{ formatTime(task.created_at) }}</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script>
|
||||
import { get } from "../../utils/request";
|
||||
|
||||
const TABS = [
|
||||
{ key: "all", label: "全部" },
|
||||
{ key: "PENDING", label: "待接收" },
|
||||
{ key: "WIP", label: "进行中" },
|
||||
{ key: "COMPLETED", label: "已完成" },
|
||||
];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
TABS,
|
||||
tab: "PENDING",
|
||||
tasks: [],
|
||||
loading: true,
|
||||
currentUser: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
filtered() {
|
||||
if (this.tab === "all") return this.tasks;
|
||||
return this.tasks.filter(t => t.status === this.tab);
|
||||
},
|
||||
},
|
||||
onShow() {
|
||||
this.loadCurrentUser();
|
||||
this.fetchTasks();
|
||||
},
|
||||
methods: {
|
||||
statusLabel(s) {
|
||||
const map = { PENDING: "待接收", WIP: "进行中", COMPLETED: "已完成", REJECTED: "已驳回", ARCHIVED: "已入库" };
|
||||
return map[s] || s;
|
||||
},
|
||||
statusColor(s) {
|
||||
switch (s) {
|
||||
case "PENDING": return "s-yellow";
|
||||
case "WIP": return "s-blue";
|
||||
case "COMPLETED": return "s-green";
|
||||
default: return "s-gray";
|
||||
}
|
||||
},
|
||||
countBy(key) {
|
||||
if (key === "all") return this.tasks.length;
|
||||
return this.tasks.filter(t => t.status === key).length;
|
||||
},
|
||||
formatTime(t) {
|
||||
if (!t) return "";
|
||||
const d = new Date(t);
|
||||
const pad = (n) => String(n).padStart(2, "0");
|
||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
||||
},
|
||||
loadCurrentUser() {
|
||||
try {
|
||||
const u = uni.getStorageSync("user");
|
||||
if (u) this.currentUser = typeof u === "string" ? JSON.parse(u) : u;
|
||||
} catch {}
|
||||
},
|
||||
async fetchTasks() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const username = this.currentUser?.username || "";
|
||||
const res = await get("/tasks/", { assignee_id: username, limit: 100 });
|
||||
this.tasks = res.tasks || [];
|
||||
} catch { this.tasks = []; }
|
||||
finally { this.loading = false; }
|
||||
},
|
||||
goDetail(task) {
|
||||
const sn = task.product_sn || task.product_id;
|
||||
if (sn) uni.navigateTo({ url: `/pages/scan/detail?serial=${sn}` });
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.page { min-height: 100vh; padding: 16px; padding-bottom: 80px; }
|
||||
.header { margin-bottom: 24px; }
|
||||
.title { font-size: 20px; font-weight: 700; color: #1f2937; display: block; }
|
||||
.subtitle { font-size: 13px; color: #9ca3af; margin-top: 4px; display: block; }
|
||||
.page { min-height: 100vh; padding: 16px; padding-bottom: 100px; }
|
||||
.header { margin-bottom: 12px; }
|
||||
.title { font-size: 20px; font-weight: 700; color: #1f2937; }
|
||||
.center { text-align: center; padding: 48px 0; color: #9ca3af; }
|
||||
.empty { display: flex; flex-direction: column; align-items: center; padding-top: 80px; }
|
||||
.empty-icon { font-size: 64px; margin-bottom: 12px; }
|
||||
.empty-text { font-size: 14px; color: #9ca3af; }
|
||||
|
||||
/* tabs — sticky 不换行,溢出滚动 */
|
||||
.tabs {
|
||||
display: flex; gap: 8px; margin-bottom: 14px;
|
||||
white-space: nowrap; overflow-x: auto;
|
||||
position: sticky; top: 0; z-index: 999;
|
||||
background: #f3f4f6; padding: 12px 0 8px;
|
||||
}
|
||||
.tab {
|
||||
padding: 8px 16px; border-radius: 20px; font-size: 13px; font-weight: 600;
|
||||
background: #fff; color: #6b7280; flex-shrink: 0;
|
||||
}
|
||||
.tab-active { background: #2563eb; color: #fff; }
|
||||
|
||||
/* card */
|
||||
.card { background: #fff; border-radius: 12px; padding: 14px; margin-bottom: 10px;
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.06); }
|
||||
.card-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
|
||||
.card-name { font-size: 15px; font-weight: 700; color: #1f2937; }
|
||||
.card-status { font-size: 11px; padding: 2px 10px; border-radius: 20px; font-weight: 600; }
|
||||
.s-yellow { background: #fef3c7; color: #b45309; }
|
||||
.s-blue { background: #dbeafe; color: #1d4ed8; }
|
||||
.s-green { background: #dcfce7; color: #15803d; }
|
||||
.s-gray { background: #f3f4f6; color: #6b7280; }
|
||||
.card-meta { font-size: 12px; color: #6b7280; display: flex; gap: 12px; }
|
||||
.card-time { font-size: 11px; color: #9ca3af; margin-top: 4px; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user