From ea6ad9ddc3d5b33897e93276282245f7023836ff Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期四, 28 八月 2025 17:45:28 +0800
Subject: [PATCH] 大数据市场分析

---
 src/views/invoiceCollaboration/components/InvoiceDialog.vue |  484 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 484 insertions(+), 0 deletions(-)

diff --git a/src/views/invoiceCollaboration/components/InvoiceDialog.vue b/src/views/invoiceCollaboration/components/InvoiceDialog.vue
new file mode 100644
index 0000000..3b8f2a6
--- /dev/null
+++ b/src/views/invoiceCollaboration/components/InvoiceDialog.vue
@@ -0,0 +1,484 @@
+<template>
+  <el-dialog
+    :model-value="dialogFormVisible"
+    @update:model-value="$emit('update:dialogFormVisible', $event)"
+    :title="title"
+    width="1200px"
+    :close-on-click-modal="false"
+    @close="handleClose"
+  >
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="rules"
+      label-width="120px"
+      class="invoice-form"
+    >
+      <!-- 璐拱鏂逛俊鎭� -->
+      <el-card class="buyer-card" shadow="never">
+        <template #header>
+          <div class="card-header">
+            <span>璐拱鏂逛俊鎭�</span>
+          </div>
+        </template>
+        
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="璐拱鏂瑰悕绉�" prop="buyerName">
+              <el-input
+                v-model="formData.buyerName"
+                placeholder="璇疯緭鍏ヨ喘涔版柟鍚嶇О"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="绾崇◣浜鸿瘑鍒彿" prop="buyerTaxNo">
+              <el-input
+                v-model="formData.buyerTaxNo"
+                placeholder="璇疯緭鍏ョ撼绋庝汉璇嗗埆鍙�"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鍦板潃鐢佃瘽" prop="buyerAddress">
+              <el-input
+                v-model="formData.buyerAddress"
+                placeholder="璇疯緭鍏ュ湴鍧�鐢佃瘽"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="寮�鎴疯鍙婅处鍙�" prop="buyerBankAccount">
+              <el-input
+                v-model="formData.buyerBankAccount"
+                placeholder="璇疯緭鍏ュ紑鎴疯鍙婅处鍙�"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-card>
+
+      <!-- 閿�鍞柟淇℃伅 -->
+      <el-card class="seller-card" shadow="never">
+        <template #header>
+          <div class="card-header">
+            <span>閿�鍞柟淇℃伅</span>
+          </div>
+        </template>
+        
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="閿�鍞柟鍚嶇О" prop="sellerName">
+              <el-input
+                v-model="formData.sellerName"
+                placeholder="璇疯緭鍏ラ攢鍞柟鍚嶇О"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="绾崇◣浜鸿瘑鍒彿" prop="sellerTaxNo">
+              <el-input
+                v-model="formData.sellerTaxNo"
+                placeholder="璇疯緭鍏ョ撼绋庝汉璇嗗埆鍙�"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鍦板潃鐢佃瘽" prop="sellerAddress">
+              <el-input
+                v-model="formData.sellerAddress"
+                placeholder="璇疯緭鍏ュ湴鍧�鐢佃瘽"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="寮�鎴疯鍙婅处鍙�" prop="sellerBankAccount">
+              <el-input
+                v-model="formData.sellerBankAccount"
+                placeholder="璇疯緭鍏ュ紑鎴疯鍙婅处鍙�"
+                style="width: 100%"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-card>
+
+      <!-- 鍟嗗搧鏄庣粏 -->
+      <el-card class="items-card" shadow="never">
+        <template #header>
+          <div class="card-header">
+            <span>鍟嗗搧鏄庣粏</span>
+            <el-button type="primary" size="small" @click="addItem">
+              娣诲姞鍟嗗搧
+            </el-button>
+          </div>
+        </template>
+        
+        <el-table :data="formData.items" border style="width: 100%">
+          <el-table-column label="鍟嗗搧鍚嶇О" width="200">
+            <template #default="scope">
+              <el-input
+                v-model="scope.row.name"
+                placeholder="鍟嗗搧鍚嶇О"
+                style="width: 100%"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="瑙勬牸鍨嬪彿" width="150">
+            <template #default="scope">
+              <el-input
+                v-model="scope.row.specification"
+                placeholder="瑙勬牸鍨嬪彿"
+                style="width: 100%"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="鍗曚綅" width="100">
+            <template #default="scope">
+              <el-input
+                v-model="scope.row.unit"
+                placeholder="鍗曚綅"
+                style="width: 100%"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="鏁伴噺" width="120">
+            <template #default="scope">
+              <el-input
+                v-model.number="scope.row.quantity"
+                placeholder="鏁伴噺"
+                type="number"
+                @input="calculateItemAmount(scope.$index)"
+                style="width: 100%"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="鍗曚环" width="120">
+            <template #default="scope">
+              <el-input
+                v-model.number="scope.row.unitPrice"
+                placeholder="鍗曚环"
+                type="number"
+                @input="calculateItemAmount(scope.$index)"
+                style="width: 100%"
+              >
+                <template v-slot:suffix>
+                  <span>鍏�</span>
+                </template>
+              </el-input>
+            </template>
+          </el-table-column>
+          <el-table-column label="閲戦" width="120">
+            <template #default="scope">
+              <span>{{ (scope.row.amount || 0).toFixed(2) }} 鍏�</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="绋庣巼" width="120">
+            <template #default="scope">
+              <el-select
+                v-model="scope.row.taxRate"
+                placeholder="閫夋嫨绋庣巼"
+                @change="calculateItemAmount(scope.$index)"
+                style="width: 100%"
+              >
+                <el-option label="0%" value="0" />
+                <el-option label="1%" value="0.01" />
+                <el-option label="3%" value="0.03" />
+                <el-option label="6%" value="0.06" />
+                <el-option label="9%" value="0.09" />
+                <el-option label="13%" value="0.13" />
+              </el-select>
+            </template>
+          </el-table-column>
+          <el-table-column label="绋庨" width="120">
+            <template #default="scope">
+              <span>{{ (scope.row.taxAmount || 0).toFixed(2) }} 鍏�</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="浠风◣鍚堣" width="120">
+            <template #default="scope">
+              <span>{{ (scope.row.totalAmount || 0).toFixed(2) }} 鍏�</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="鎿嶄綔" width="80">
+            <template #default="scope">
+              <el-button
+                type="danger"
+                size="small"
+                @click="removeItem(scope.$index)"
+              >
+                鍒犻櫎
+              </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+        
+        <!-- 鍚堣淇℃伅 -->
+        <div class="summary-info">
+          <el-row :gutter="20">
+            <el-col :span="6">
+              <span class="summary-label">閲戦鍚堣锛�</span>
+              <span class="summary-value">{{ totalAmount.toFixed(2) }} 鍏�</span>
+            </el-col>
+            <el-col :span="6">
+              <span class="summary-label">绋庨鍚堣锛�</span>
+              <span class="summary-value">{{ totalTaxAmount.toFixed(2) }} 鍏�</span>
+            </el-col>
+            <el-col :span="6">
+              <span class="summary-label">浠风◣鍚堣锛�</span>
+              <span class="summary-value">{{ totalTotalAmount.toFixed(2) }} 鍏�</span>
+            </el-col>
+          </el-row>
+        </div>
+      </el-card>
+
+      <!-- 澶囨敞淇℃伅 -->
+      <el-form-item label="澶囨敞" prop="remark">
+        <el-input
+          v-model="formData.remark"
+          type="textarea"
+          :rows="3"
+          placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�"
+        />
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="handleClose">鍙栨秷</el-button>
+        <el-button type="primary" @click="handleSubmit" :loading="submitLoading">
+          鎻愪氦
+        </el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup>
+import { ref, reactive, watch, computed } from "vue";
+import { ElMessage } from "element-plus";
+
+// Props
+const props = defineProps({
+  dialogFormVisible: {
+    type: Boolean,
+    default: false
+  },
+  form: {
+    type: Object,
+    default: () => ({})
+  },
+  title: {
+    type: String,
+    default: ""
+  },
+  isEdit: {
+    type: Boolean,
+    default: false
+  }
+});
+
+// Emits
+const emit = defineEmits(['update:dialogFormVisible', 'update:form', 'submit', 'success']);
+
+// 鍝嶅簲寮忔暟鎹�
+const formRef = ref(null);
+const submitLoading = ref(false);
+
+// 琛ㄥ崟鏁版嵁
+const formData = reactive({
+  buyerName: "",
+  buyerTaxNo: "",
+  buyerAddress: "",
+  buyerBankAccount: "",
+  sellerName: "鏈叕鍙�",
+  sellerTaxNo: "123456789012345678",
+  sellerAddress: "鍏徃鍦板潃",
+  sellerBankAccount: "閾惰璐︽埛",
+  items: [],
+  remark: ""
+});
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const rules = {
+  buyerName: [
+    { required: true, message: "璇疯緭鍏ヨ喘涔版柟鍚嶇О", trigger: "blur" }
+  ],
+  buyerTaxNo: [
+    { required: true, message: "璇疯緭鍏ョ撼绋庝汉璇嗗埆鍙�", trigger: "blur" }
+  ],
+  items: [
+    { 
+      type: "array", 
+      required: true, 
+      message: "璇疯嚦灏戞坊鍔犱竴涓晢鍝�", 
+      trigger: "change",
+      validator: (rule, value, callback) => {
+        if (!value || value.length === 0) {
+          callback(new Error("璇疯嚦灏戞坊鍔犱竴涓晢鍝�"));
+        } else {
+          callback();
+        }
+      }
+    }
+  ]
+};
+
+// 璁$畻灞炴��
+const totalAmount = computed(() => {
+  return formData.items.reduce((sum, item) => sum + (item.amount || 0), 0);
+});
+
+const totalTaxAmount = computed(() => {
+  return formData.items.reduce((sum, item) => sum + (item.taxAmount || 0), 0);
+});
+
+const totalTotalAmount = computed(() => {
+  return formData.items.reduce((sum, item) => sum + (item.totalAmount || 0), 0);
+});
+
+// 鐩戝惉琛ㄥ崟鏁版嵁鍙樺寲
+watch(() => props.form, (newVal) => {
+  Object.assign(formData, newVal);
+  if (!formData.items || formData.items.length === 0) {
+    formData.items = [];
+  }
+}, { deep: true, immediate: true });
+
+// 娣诲姞鍟嗗搧
+const addItem = () => {
+  formData.items.push({
+    name: "",
+    specification: "",
+    unit: "",
+    quantity: 0,
+    unitPrice: 0,
+    amount: 0,
+    taxRate: "0.13",
+    taxAmount: 0,
+    totalAmount: 0
+  });
+};
+
+// 鍒犻櫎鍟嗗搧
+const removeItem = (index) => {
+  formData.items.splice(index, 1);
+};
+
+// 璁$畻鍟嗗搧閲戦
+const calculateItemAmount = (index) => {
+  const item = formData.items[index];
+  if (item.quantity && item.unitPrice) {
+    item.amount = item.quantity * item.unitPrice;
+    item.taxAmount = item.amount * parseFloat(item.taxRate);
+    item.totalAmount = item.amount + item.taxAmount;
+  }
+};
+
+// 鍏抽棴瀵硅瘽妗�
+const handleClose = () => {
+  emit('update:dialogFormVisible', false);
+  formRef.value?.resetFields();
+};
+
+// 鎻愪氦琛ㄥ崟
+const handleSubmit = async () => {
+  if (!formRef.value) return;
+  
+  try {
+    await formRef.value.validate();
+    
+    // 楠岃瘉鍟嗗搧淇℃伅
+    if (formData.items.length === 0) {
+      ElMessage.warning("璇疯嚦灏戞坊鍔犱竴涓晢鍝�");
+      return;
+    }
+    
+    for (let item of formData.items) {
+      if (!item.name) {
+        ElMessage.warning("璇疯緭鍏ュ晢鍝佸悕绉�");
+        return;
+      }
+      if (!item.quantity || item.quantity <= 0) {
+        ElMessage.warning("璇疯緭鍏ユ湁鏁堢殑鍟嗗搧鏁伴噺");
+        return;
+      }
+      if (!item.unitPrice || item.unitPrice <= 0) {
+        ElMessage.warning("璇疯緭鍏ユ湁鏁堢殑鍟嗗搧鍗曚环");
+        return;
+      }
+    }
+    
+    submitLoading.value = true;
+    
+    // 妯℃嫙鎻愪氦
+    setTimeout(() => {
+      submitLoading.value = false;
+      ElMessage.success("鎻愪氦鎴愬姛");
+      emit('submit', { ...formData });
+      handleClose();
+    }, 1000);
+    
+  } catch (error) {
+    console.error('琛ㄥ崟楠岃瘉澶辫触:', error);
+  }
+};
+</script>
+
+<style scoped>
+.invoice-form {
+  padding: 20px 0;
+}
+
+.buyer-card,
+.seller-card,
+.items-card {
+  margin-bottom: 20px;
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  font-weight: bold;
+}
+
+.summary-info {
+  margin-top: 15px;
+  padding: 15px;
+  background-color: #f5f7fa;
+  border-radius: 4px;
+}
+
+.summary-label {
+  font-weight: bold;
+  margin-right: 10px;
+}
+
+.summary-value {
+  color: #409eff;
+  font-size: 16px;
+  font-weight: bold;
+}
+
+.dialog-footer {
+  text-align: right;
+}
+
+.el-table {
+  margin-top: 10px;
+}
+</style>
\ No newline at end of file

--
Gitblit v1.9.3