From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目

---
 src/views/erp/sale/order/components/SaleOrderItemForm.vue |  271 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 271 insertions(+), 0 deletions(-)

diff --git a/src/views/erp/sale/order/components/SaleOrderItemForm.vue b/src/views/erp/sale/order/components/SaleOrderItemForm.vue
new file mode 100644
index 0000000..817775f
--- /dev/null
+++ b/src/views/erp/sale/order/components/SaleOrderItemForm.vue
@@ -0,0 +1,271 @@
+<template>
+  <el-form
+    ref="formRef"
+    :model="formData"
+    :rules="formRules"
+    v-loading="formLoading"
+    label-width="0px"
+    :inline-message="true"
+    :disabled="disabled"
+  >
+    <el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
+      <el-table-column label="搴忓彿" type="index" align="center" width="60" />
+      <el-table-column label="浜у搧鍚嶇О" min-width="180">
+        <template #default="{ row, $index }">
+          <el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!">
+            <el-select
+              v-model="row.productId"
+              clearable
+              filterable
+              @change="onChangeProduct($event, row)"
+              placeholder="璇烽�夋嫨浜у搧"
+            >
+              <el-option
+                v-for="item in productList"
+                :key="item.id"
+                :label="item.name"
+                :value="item.id"
+              />
+            </el-select>
+          </el-form-item>
+        </template>
+      </el-table-column>
+      <el-table-column label="搴撳瓨" min-width="100">
+        <template #default="{ row }">
+          <el-form-item class="mb-0px!">
+            <el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" />
+          </el-form-item>
+        </template>
+      </el-table-column>
+      <el-table-column label="鏉$爜" min-width="150">
+        <template #default="{ row }">
+          <el-form-item class="mb-0px!">
+            <el-input disabled v-model="row.productBarCode" />
+          </el-form-item>
+        </template>
+      </el-table-column>
+      <el-table-column label="鍗曚綅" min-width="80">
+        <template #default="{ row }">
+          <el-form-item class="mb-0px!">
+            <el-input disabled v-model="row.productUnitName" />
+          </el-form-item>
+        </template>
+      </el-table-column>
+      <el-table-column label="鏁伴噺" prop="count" fixed="right" min-width="140">
+        <template #default="{ row, $index }">
+          <el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!">
+            <el-input-number
+              v-model="row.count"
+              controls-position="right"
+              :min="0.001"
+              :precision="3"
+              class="!w-100%"
+            />
+          </el-form-item>
+        </template>
+      </el-table-column>
+      <el-table-column label="浜у搧鍗曚环" fixed="right" min-width="120">
+        <template #default="{ row, $index }">
+          <el-form-item :prop="`${$index}.productPrice`" class="mb-0px!">
+            <el-input-number
+              v-model="row.productPrice"
+              controls-position="right"
+              :min="0.01"
+              :precision="2"
+              class="!w-100%"
+            />
+          </el-form-item>
+        </template>
+      </el-table-column>
+      <el-table-column label="閲戦" prop="totalProductPrice" fixed="right" min-width="100">
+        <template #default="{ row, $index }">
+          <el-form-item :prop="`${$index}.totalProductPrice`" class="mb-0px!">
+            <el-input
+              disabled
+              v-model="row.totalProductPrice"
+              :formatter="erpPriceInputFormatter"
+            />
+          </el-form-item>
+        </template>
+      </el-table-column>
+      <el-table-column label="绋庣巼锛�%锛�" fixed="right" min-width="115">
+        <template #default="{ row, $index }">
+          <el-form-item :prop="`${$index}.taxPercent`" class="mb-0px!">
+            <el-input-number
+              v-model="row.taxPercent"
+              controls-position="right"
+              :min="0"
+              :precision="2"
+              class="!w-100%"
+            />
+          </el-form-item>
+        </template>
+      </el-table-column>
+      <el-table-column label="绋庨" prop="taxPrice" fixed="right" min-width="120">
+        <template #default="{ row, $index }">
+          <el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!">
+            <el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!">
+              <el-input disabled v-model="row.taxPrice" :formatter="erpPriceInputFormatter" />
+            </el-form-item>
+          </el-form-item>
+        </template>
+      </el-table-column>
+      <el-table-column label="绋庨鍚堣" prop="totalPrice" fixed="right" min-width="100">
+        <template #default="{ row, $index }">
+          <el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!">
+            <el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" />
+          </el-form-item>
+        </template>
+      </el-table-column>
+      <el-table-column label="澶囨敞" min-width="150">
+        <template #default="{ row, $index }">
+          <el-form-item :prop="`${$index}.remark`" class="mb-0px!">
+            <el-input v-model="row.remark" placeholder="璇疯緭鍏ュ娉�" />
+          </el-form-item>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" fixed="right" label="鎿嶄綔" width="60">
+        <template #default="{ $index }">
+          <el-button @click="handleDelete($index)" link>鈥�</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+  </el-form>
+  <el-row justify="center" class="mt-3" v-if="!disabled">
+    <el-button @click="handleAdd" round>+ 娣诲姞閿�鍞骇鍝�</el-button>
+  </el-row>
+</template>
+<script setup lang="ts">
+import { ProductApi, ProductVO } from '@/api/erp/product/product'
+import { StockApi } from '@/api/erp/stock/stock'
+import {
+  erpCountInputFormatter,
+  erpPriceInputFormatter,
+  erpPriceMultiply,
+  getSumValue
+} from '@/utils'
+
+const props = defineProps<{
+  items: undefined
+  disabled: false
+}>()
+const formLoading = ref(false) // 琛ㄥ崟鐨勫姞杞戒腑
+const formData = ref([])
+const formRules = reactive({
+  productId: [{ required: true, message: '浜у搧涓嶈兘涓虹┖', trigger: 'blur' }],
+  count: [{ required: true, message: '浜у搧鏁伴噺涓嶈兘涓虹┖', trigger: 'blur' }]
+})
+const formRef = ref([]) // 琛ㄥ崟 Ref
+const productList = ref<ProductVO[]>([]) // 浜у搧鍒楄〃
+
+/** 鍒濆鍖栬缃嚭搴撻」 */
+watch(
+  () => props.items,
+  async (val) => {
+    formData.value = val
+  },
+  { immediate: true }
+)
+
+/** 鐩戝惉鍚堝悓浜у搧鍙樺寲锛岃绠楀悎鍚屼骇鍝佹�讳环 */
+watch(
+  () => formData.value,
+  (val) => {
+    if (!val || val.length === 0) {
+      return
+    }
+    // 寰幆澶勭悊
+    val.forEach((item) => {
+      item.totalProductPrice = erpPriceMultiply(item.productPrice, item.count)
+      item.taxPrice = erpPriceMultiply(item.totalProductPrice, item.taxPercent / 100.0)
+      if (item.totalProductPrice != null) {
+        item.totalPrice = item.totalProductPrice + (item.taxPrice || 0)
+      } else {
+        item.totalPrice = undefined
+      }
+    })
+  },
+  { deep: true }
+)
+
+/** 鍚堣 */
+const getSummaries = (param: SummaryMethodProps) => {
+  const { columns, data } = param
+  const sums: string[] = []
+  columns.forEach((column, index: number) => {
+    if (index === 0) {
+      sums[index] = '鍚堣'
+      return
+    }
+    if (['count', 'totalProductPrice', 'taxPrice', 'totalPrice'].includes(column.property)) {
+      const sum = getSumValue(data.map((item) => Number(item[column.property])))
+      sums[index] =
+        column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
+    } else {
+      sums[index] = ''
+    }
+  })
+
+  return sums
+}
+
+/** 鏂板鎸夐挳鎿嶄綔 */
+const handleAdd = () => {
+  const row = {
+    id: undefined,
+    productId: undefined,
+    productUnitName: undefined, // 浜у搧鍗曚綅
+    productBarCode: undefined, // 浜у搧鏉$爜
+    productPrice: undefined,
+    stockCount: undefined,
+    count: 1,
+    totalProductPrice: undefined,
+    taxPercent: undefined,
+    taxPrice: undefined,
+    totalPrice: undefined,
+    remark: undefined
+  }
+  formData.value.push(row)
+}
+
+/** 鍒犻櫎鎸夐挳鎿嶄綔 */
+const handleDelete = (index: number) => {
+  formData.value.splice(index, 1)
+}
+
+/** 澶勭悊浜у搧鍙樻洿 */
+const onChangeProduct = (productId, row) => {
+  const product = productList.value.find((item) => item.id === productId)
+  if (product) {
+    row.productUnitName = product.unitName
+    row.productBarCode = product.barCode
+    row.productPrice = product.salePrice
+  }
+  // 鍔犺浇搴撳瓨
+  setStockCount(row)
+}
+
+/** 鍔犺浇搴撳瓨 */
+const setStockCount = async (row: any) => {
+  if (!row.productId) {
+    return
+  }
+  const count = await StockApi.getStockCount(row.productId)
+  row.stockCount = count || 0
+}
+
+/** 琛ㄥ崟鏍¢獙 */
+const validate = () => {
+  return formRef.value.validate()
+}
+defineExpose({ validate })
+
+/** 鍒濆鍖� */
+onMounted(async () => {
+  productList.value = await ProductApi.getProductSimpleList()
+  // 榛樿娣诲姞涓�涓�
+  if (formData.value.length === 0) {
+    handleAdd()
+  }
+})
+</script>

--
Gitblit v1.8.0