up
This commit is contained in:
@@ -35,4 +35,9 @@ export const purchaseApi = {
|
||||
deleteOrder(id) {
|
||||
return api.post('/purchase/deleteorder', { id })
|
||||
},
|
||||
|
||||
/** 删除状态记录 */
|
||||
deleteCommit(orderId, commitId) {
|
||||
return api.post('/purchase/delete_commit', { orderId, commitId })
|
||||
},
|
||||
}
|
||||
|
||||
@@ -40,4 +40,9 @@ export const workOrderApi = {
|
||||
searchPurchaseOrders(search = '', limit = 5) {
|
||||
return api.post('/work_order/search_purchase_orders', { search, limit })
|
||||
},
|
||||
|
||||
/** 删除进度 */
|
||||
deleteCommit(workOrderId, commitId) {
|
||||
return api.post('/work_order/delete_commit', { workOrderId, commitId })
|
||||
},
|
||||
}
|
||||
|
||||
@@ -108,7 +108,8 @@
|
||||
"upload_photos": "Upload Photos",
|
||||
"commit_create": "Order created",
|
||||
"edit_order": "Edit Order",
|
||||
"submit_changes":"Submit changes"
|
||||
"submit_changes":"Submit changes",
|
||||
"confirm_delete_commit": "Are you sure you want to delete this progress?"
|
||||
},
|
||||
"work_order": {
|
||||
"list_title": "Work Order List",
|
||||
@@ -146,6 +147,7 @@
|
||||
"back_to_list": "Back to List",
|
||||
"not_found": "Work order not found",
|
||||
"confirm_delete": "Are you sure you want to delete this work order? This action cannot be undone.",
|
||||
"confirm_delete_commit": "Are you sure you want to delete this progress?",
|
||||
"submit": "Submit",
|
||||
"save_changes": "Save Changes"
|
||||
},
|
||||
@@ -292,6 +294,7 @@
|
||||
"cancel": "Cancel",
|
||||
"save_success": "Saved successfully",
|
||||
"submit": "Submit",
|
||||
"submitting": "Submitting...",
|
||||
"loading": "Loading..."
|
||||
},
|
||||
"settings": {
|
||||
|
||||
@@ -108,7 +108,8 @@
|
||||
"upload_photos": "上传图片",
|
||||
"commit_create": "订单创建",
|
||||
"edit_order": "编辑订单",
|
||||
"submit_changes":"提交修改"
|
||||
"submit_changes":"提交修改",
|
||||
"confirm_delete_commit": "确定要删除此进度吗?"
|
||||
},
|
||||
"work_order": {
|
||||
"list_title": "工单列表",
|
||||
@@ -146,6 +147,7 @@
|
||||
"back_to_list": "返回列表",
|
||||
"not_found": "工单不存在",
|
||||
"confirm_delete": "确定要删除此工单吗?此操作不可撤销。",
|
||||
"confirm_delete_commit": "确定要删除此进度吗?",
|
||||
"submit": "提交",
|
||||
"save_changes": "保存修改"
|
||||
},
|
||||
@@ -292,6 +294,7 @@
|
||||
"delete_ok": "删除成功",
|
||||
"save_success": "保存成功",
|
||||
"submit": "提交",
|
||||
"submitting": "提交中...",
|
||||
"loading": "加载中..."
|
||||
},
|
||||
"settings": {
|
||||
|
||||
@@ -7,6 +7,7 @@ import { usePageTitle } from "@/composables/usePageTitle";
|
||||
import { purchaseApi } from "@/api/purchase";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
import { useUsersStore } from "@/stores/users";
|
||||
import ConfirmDialog from "@/components/ConfirmDialog.vue";
|
||||
import {
|
||||
IconChevronLeft,
|
||||
IconExternalLink,
|
||||
@@ -44,6 +45,47 @@ const pendingComment = ref("");
|
||||
const pendingPhotos = ref([]); // { hash, url, uploading, error }
|
||||
const photoInputRef = ref(null);
|
||||
|
||||
// 删除进度相关
|
||||
const showDeleteConfirm = ref(false);
|
||||
const pendingDeleteCommitId = ref(null);
|
||||
|
||||
// 判断是否可以删除进度
|
||||
function canDeleteCommit(commit, index) {
|
||||
// 最新状态(第0条)不显示删除按钮
|
||||
if (index === 0) return false;
|
||||
// 订单创建者
|
||||
if (order.value?.UserID === userStore.user?.ID) return true;
|
||||
// 进度创建者
|
||||
if (commit.userId === userStore.user?.ID) return true;
|
||||
// 管理员
|
||||
if (userStore.user?.Type === 'admin') return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function handleDeleteCommit(commitId) {
|
||||
pendingDeleteCommitId.value = commitId;
|
||||
showDeleteConfirm.value = true;
|
||||
}
|
||||
|
||||
async function confirmDeleteCommit() {
|
||||
if (!pendingDeleteCommitId.value) return;
|
||||
try {
|
||||
const { errCode } = await purchaseApi.deleteCommit(orderId.value, pendingDeleteCommitId.value);
|
||||
if (errCode === 0) {
|
||||
toast.success(t("message.delete_ok"));
|
||||
// 前端直接移除该 commit,保持滚动位置
|
||||
commits.value = commits.value.filter(c => c.id !== pendingDeleteCommitId.value);
|
||||
} else {
|
||||
toast.error(t("message.server_error"));
|
||||
}
|
||||
} catch {
|
||||
toast.error(t("message.server_error"));
|
||||
} finally {
|
||||
pendingDeleteCommitId.value = null;
|
||||
showDeleteConfirm.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 状态选项
|
||||
const statusOptions = [
|
||||
{ value: "pending", labelKey: "status_pending", color: "yellow" },
|
||||
@@ -644,9 +686,9 @@ onMounted(fetchOrder);
|
||||
class="divide-y divide-gray-50 px-6 py-2 dark:divide-dk-muted/50"
|
||||
>
|
||||
<div
|
||||
v-for="commit in commits"
|
||||
v-for="(commit, index) in commits"
|
||||
:key="commit.id"
|
||||
class="flex items-start gap-3 py-3"
|
||||
class="flex items-start gap-3 py-3 rounded-lg border border-gray-100 bg-gray-50/50 px-4 my-2 dark:border-dk-muted dark:bg-dk-base/30"
|
||||
>
|
||||
<!-- 左侧:头像 + 用户名 -->
|
||||
<div class="flex w-20 flex-shrink-0 flex-col items-center gap-1">
|
||||
@@ -697,6 +739,15 @@ onMounted(fetchOrder);
|
||||
<span class="ml-auto text-xs text-gray-400">{{
|
||||
formatDate(commit.createdAt)
|
||||
}}</span>
|
||||
<!-- 删除按钮 -->
|
||||
<button
|
||||
v-if="canDeleteCommit(commit, index)"
|
||||
class="ml-2 rounded-lg border border-red-200 bg-red-50 px-3 py-1 text-xs font-medium text-red-600 transition-colors hover:bg-red-100 hover:border-red-300 dark:border-red-900/50 dark:bg-red-900/30 dark:text-red-400 dark:hover:bg-red-900/50"
|
||||
@click="handleDeleteCommit(commit.id)"
|
||||
>
|
||||
<IconTrash :size="14" class="mr-1 inline align-middle" />
|
||||
删除
|
||||
</button>
|
||||
</div>
|
||||
<p
|
||||
v-if="commit.comment"
|
||||
@@ -899,6 +950,14 @@ onMounted(fetchOrder);
|
||||
</div>
|
||||
</Transition>
|
||||
</Teleport>
|
||||
|
||||
<!-- 删除进度确认弹窗 -->
|
||||
<ConfirmDialog
|
||||
v-model="showDeleteConfirm"
|
||||
:message="t('purchase.confirm_delete_commit')"
|
||||
danger
|
||||
@confirm="confirmDeleteCommit"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -259,9 +259,9 @@ async function handleSubmit() {
|
||||
|
||||
<!-- 删除确认弹窗 -->
|
||||
<ConfirmDialog
|
||||
v-if="showDeleteConfirm"
|
||||
v-model="showDeleteConfirm"
|
||||
:message="t('work_order.confirm_delete')"
|
||||
danger
|
||||
@confirm="doDelete"
|
||||
@cancel="showDeleteConfirm = false"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -8,6 +8,7 @@ import { useUserStore } from '@/stores/user'
|
||||
import { useUsersStore } from '@/stores/users'
|
||||
import { workOrderApi } from '@/api/work_order'
|
||||
import useDropzone from '@/components/useDropzone.vue'
|
||||
import ConfirmDialog from '@/components/ConfirmDialog.vue'
|
||||
import {
|
||||
IconChevronLeft,
|
||||
IconCheck,
|
||||
@@ -39,7 +40,7 @@ const notFound = ref(false)
|
||||
const submittingCommit = ref(false)
|
||||
const commitStatus = ref('pending')
|
||||
const commitComment = ref('')
|
||||
const commitPhotos = ref([])
|
||||
const commitDropzoneRef = ref(null)
|
||||
|
||||
// 采购订单关联相关
|
||||
const purchaseSearchQuery = ref('')
|
||||
@@ -54,7 +55,7 @@ const purchaseDropdownRef = ref(null)
|
||||
const canSubmit = computed(() => {
|
||||
const hasSelectedOrders = selectedPurchaseOrders.value.length > 0
|
||||
const hasComment = !!commitComment.value
|
||||
const hasPhotos = commitPhotos.value.length > 0
|
||||
const hasPhotos = commitDropzoneRef.value?.return_files().filter(f => f.is_upload).length > 0
|
||||
// 订单、备注、上传图片都为空时才禁止提交
|
||||
return hasSelectedOrders || hasComment || hasPhotos
|
||||
})
|
||||
@@ -138,18 +139,22 @@ async function handleCommit() {
|
||||
submittingCommit.value = true
|
||||
try {
|
||||
const purchaseOrderIds = selectedPurchaseOrders.value.map(p => p.id)
|
||||
// 从 dropzone 获取已上传的文件 hash
|
||||
const uploadedPhotos = commitDropzoneRef.value?.return_files()
|
||||
.filter(f => f.is_upload)
|
||||
.map(f => f.hash) ?? []
|
||||
const { errCode } = await workOrderApi.commit(
|
||||
orderId.value,
|
||||
commitStatus.value,
|
||||
commitComment.value,
|
||||
commitPhotos.value,
|
||||
uploadedPhotos,
|
||||
purchaseOrderIds,
|
||||
)
|
||||
if (errCode === 0) {
|
||||
toast.success(t('message.save_ok'))
|
||||
commitComment.value = ''
|
||||
commitPhotos.value = []
|
||||
selectedPurchaseOrders.value = []
|
||||
// 清空 dropzone(刷新组件即可)
|
||||
await fetchOrder()
|
||||
} else {
|
||||
toast.error(t('message.server_error'))
|
||||
@@ -161,6 +166,47 @@ async function handleCommit() {
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 删除进度 ====================
|
||||
const showDeleteCommitConfirm = ref(false)
|
||||
const pendingDeleteCommitId = ref(null)
|
||||
|
||||
function handleDeleteCommit(commitId) {
|
||||
pendingDeleteCommitId.value = commitId
|
||||
showDeleteCommitConfirm.value = true
|
||||
}
|
||||
|
||||
async function confirmDeleteCommit() {
|
||||
if (!pendingDeleteCommitId.value) return
|
||||
try {
|
||||
const { errCode } = await workOrderApi.deleteCommit(orderId.value, pendingDeleteCommitId.value)
|
||||
if (errCode === 0) {
|
||||
toast.success(t('message.delete_ok'))
|
||||
// 前端直接移除该 commit,保持滚动位置
|
||||
commits.value = commits.value.filter(c => c.ID !== pendingDeleteCommitId.value)
|
||||
} else {
|
||||
toast.error(t('message.server_error'))
|
||||
}
|
||||
} catch {
|
||||
toast.error(t('message.server_error'))
|
||||
} finally {
|
||||
pendingDeleteCommitId.value = null
|
||||
showDeleteCommitConfirm.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 判断是否可以删除进度
|
||||
function canDeleteCommit(commit, index) {
|
||||
// 最新状态(第0条)不显示删除按钮
|
||||
if (index === 0) return false
|
||||
// 订单创建者
|
||||
if (order.value?.UserID === userStore.user?.ID) return true
|
||||
// 进度创建者
|
||||
if (commit.UserID === userStore.user?.ID) return true
|
||||
// 管理员
|
||||
if (userStore.user?.Type === 'admin') return true
|
||||
return false
|
||||
}
|
||||
|
||||
// ==================== 快捷切换状态 ====================
|
||||
async function quickChangeStatus(newStatus) {
|
||||
if (newStatus === order.value?.CurrentStatus) return
|
||||
@@ -492,7 +538,7 @@ onUnmounted(() => {
|
||||
<div class="mb-3">
|
||||
<label class="mb-1 block text-xs font-medium text-gray-400">{{ t('work_order.commit_photos_label') }}</label>
|
||||
<useDropzone
|
||||
v-model="commitPhotos"
|
||||
ref="commitDropzoneRef"
|
||||
:maxFiles="10"
|
||||
:maxSize="10 * 1024 * 1024"
|
||||
accept="image/*"
|
||||
@@ -502,11 +548,11 @@ onUnmounted(() => {
|
||||
<!-- 第四行:提交 -->
|
||||
<div class="flex justify-end">
|
||||
<button
|
||||
:disabled="isCommitting || !canSubmit"
|
||||
:disabled="submittingCommit || !canSubmit"
|
||||
class="rounded-lg bg-blue-600 px-6 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-50"
|
||||
@click="handleCommit"
|
||||
>
|
||||
{{ isCommitting ? '提交中...' : t('work_order.commit_submit') }}
|
||||
{{ submittingCommit ? t('message.submitting') : t('work_order.commit_submit') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -516,9 +562,9 @@ onUnmounted(() => {
|
||||
<div v-if="commits.length === 0" class="py-4 text-sm text-gray-400">{{ t('work_order.no_commits') }}</div>
|
||||
<ol v-else class="relative border-l border-gray-200 dark:border-dk-muted">
|
||||
<li
|
||||
v-for="commit in [...commits].reverse()"
|
||||
v-for="(commit, index) in commits"
|
||||
:key="commit.ID"
|
||||
class="mb-6 ml-4"
|
||||
class="mb-6 ml-4 rounded-lg border border-gray-100 bg-gray-50/50 px-4 py-3 dark:border-dk-muted dark:bg-dk-base/30"
|
||||
>
|
||||
<!-- 时间线圆点 -->
|
||||
<div
|
||||
@@ -545,6 +591,15 @@ onUnmounted(() => {
|
||||
</span>
|
||||
<!-- 时间 -->
|
||||
<time class="text-xs text-gray-400">{{ formatDate(commit.CreatedAt) }}</time>
|
||||
<!-- 删除按钮 -->
|
||||
<button
|
||||
v-if="canDeleteCommit(commit, index)"
|
||||
class="ml-auto rounded-lg border border-red-200 bg-red-50 px-3 py-1.5 text-xs font-medium text-red-600 transition-colors hover:bg-red-100 hover:border-red-300 dark:border-red-900/50 dark:bg-red-900/30 dark:text-red-400 dark:hover:bg-red-900/50"
|
||||
@click="handleDeleteCommit(commit.ID)"
|
||||
>
|
||||
<IconTrash :size="14" class="mr-1 inline align-middle" />
|
||||
删除
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 备注文字 -->
|
||||
@@ -606,4 +661,12 @@ onUnmounted(() => {
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 删除进度确认弹窗 -->
|
||||
<ConfirmDialog
|
||||
v-model="showDeleteCommitConfirm"
|
||||
:message="t('work_order.confirm_delete_commit')"
|
||||
danger
|
||||
@confirm="confirmDeleteCommit"
|
||||
/>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user