|
@@ -0,0 +1,303 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import { ElMessage, dayjs, ElForm } from "element-plus";
|
|
|
+import { computed, reactive, ref, watchEffect } from "vue";
|
|
|
+import { input_type_list } from "../status";
|
|
|
+import { xs_inv_type_list } from "/@/utils/status";
|
|
|
+import { httpBack } from "/@/api/InvoiceSales/invoiceApply";
|
|
|
+import { isnumber } from "/@/utils/validate";
|
|
|
+
|
|
|
+const map = {
|
|
|
+ "10": "electronic", //电子普通发票
|
|
|
+ "20": "special_electronic", //电子专用发票
|
|
|
+ "01": "special", //普通专用发票
|
|
|
+ "04": "normal" //普通发票
|
|
|
+};
|
|
|
+
|
|
|
+const invType = ref("");
|
|
|
+const invNo = ref("");
|
|
|
+const visible = ref(false);
|
|
|
+
|
|
|
+const formRef = ref<InstanceType<typeof ElForm>>(null);
|
|
|
+const emit = defineEmits(["refresh"]);
|
|
|
+
|
|
|
+const rules = reactive({
|
|
|
+ inv_code: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: "发票代码格式不正确",
|
|
|
+ trigger: "blur",
|
|
|
+ validator(_, value) {
|
|
|
+ if (!value) {
|
|
|
+ return new Error("发票代码不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ return isnumber(value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ inv_number: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: "发票号码格式不正确",
|
|
|
+ trigger: "blur",
|
|
|
+ validator(_, value) {
|
|
|
+ if (!value) {
|
|
|
+ return new Error("发票号码不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ return isnumber(value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ open_date: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: "请选择开票日期",
|
|
|
+ trigger: "change"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ inv_total: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: "请输入税后金额",
|
|
|
+ trigger: "blur"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+
|
|
|
+ inv_subtotal: [
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: "请输入税前金额",
|
|
|
+ trigger: "blur"
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ check_code: [
|
|
|
+ {
|
|
|
+ required: false,
|
|
|
+ message: "请输入校验码",
|
|
|
+ trigger: "change"
|
|
|
+ }
|
|
|
+ ]
|
|
|
+});
|
|
|
+
|
|
|
+const scanInvType = ref("");
|
|
|
+const disabled = computed(() => formData.input_type === "1");
|
|
|
+const loading = ref(false);
|
|
|
+const scanInputValue = ref("");
|
|
|
+const formData = reactive({
|
|
|
+ input_type: "1",
|
|
|
+ remark: "",
|
|
|
+ inv_code: "",
|
|
|
+ inv_number: "",
|
|
|
+ open_date: null,
|
|
|
+ inv_subtotal: 0,
|
|
|
+ check_code: ""
|
|
|
+});
|
|
|
+
|
|
|
+function handleSaveStatus() {
|
|
|
+ formRef.value.validate(async isValid => {
|
|
|
+ if (!isValid) return;
|
|
|
+ const {
|
|
|
+ input_type: _,
|
|
|
+ inv_subtotal,
|
|
|
+ check_code,
|
|
|
+ ...otherParams
|
|
|
+ } = formData;
|
|
|
+ let params: Record<string, string> | null = null;
|
|
|
+
|
|
|
+ const type = map[scanInvType.value];
|
|
|
+
|
|
|
+ if (scanInvType.value && String(invType.value) !== String(type)) {
|
|
|
+ return ElMessage.error("扫描识别的发票类型与开票类型不一致");
|
|
|
+ }
|
|
|
+
|
|
|
+ //线下开票
|
|
|
+ params = {
|
|
|
+ invNo: invNo.value,
|
|
|
+ inv_subtotal: inv_subtotal.toFixed(2),
|
|
|
+ ...(check_code ? { check_code } : {}),
|
|
|
+ ...otherParams
|
|
|
+ };
|
|
|
+
|
|
|
+ loading.value = true;
|
|
|
+ const { code, message } = await httpBack(params);
|
|
|
+ loading.value = false;
|
|
|
+
|
|
|
+ switch (code) {
|
|
|
+ case 0:
|
|
|
+ visible.value = false;
|
|
|
+ emit("refresh");
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ ElMessage.warning(message);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function handleScanKeydown(evt: KeyboardEvent) {
|
|
|
+ const { keyCode } = evt;
|
|
|
+ if (keyCode !== 13) return;
|
|
|
+
|
|
|
+ //校验扫描枪值是否含有中文逗号
|
|
|
+ if (scanInputValue.value.indexOf(",") >= 0) {
|
|
|
+ ElMessage.error("不能包含中文逗号");
|
|
|
+ return (scanInputValue.value = "");
|
|
|
+ }
|
|
|
+
|
|
|
+ const result = scanInputValue.value.split(",");
|
|
|
+
|
|
|
+ if (result.length !== 9) {
|
|
|
+ ElMessage.error("扫码枪识别数据格式不正确,请重新扫描。");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const [_1, invoiceType, ...chunks] = result;
|
|
|
+ const [inv_code, inv_number, subtotal_amount, open_time, check_code] = chunks;
|
|
|
+
|
|
|
+ scanInvType.value = invoiceType;
|
|
|
+ const year = open_time.slice(0, 4);
|
|
|
+ const month = open_time.slice(4, 6);
|
|
|
+ const day = open_time.slice(6);
|
|
|
+
|
|
|
+ formData.inv_code = inv_code;
|
|
|
+ formData.check_code = check_code;
|
|
|
+ formData.inv_number = inv_number;
|
|
|
+ formData.inv_subtotal = Number(subtotal_amount);
|
|
|
+ formData.open_date = dayjs(`${year}-${month}-${day}`).format(
|
|
|
+ "YYYY-MM-DD HH:mm:ss"
|
|
|
+ );
|
|
|
+
|
|
|
+ scanInputValue.value = "";
|
|
|
+}
|
|
|
+
|
|
|
+watchEffect(() => {
|
|
|
+ rules.check_code[0].required =
|
|
|
+ invType.value === "normal" || invType.value === "electronic";
|
|
|
+});
|
|
|
+
|
|
|
+watchEffect(() => {
|
|
|
+ const { input_type } = formData;
|
|
|
+
|
|
|
+ if (input_type === "2") {
|
|
|
+ const source = xs_inv_type_list.find(
|
|
|
+ ({ value }) => value === invType.value
|
|
|
+ );
|
|
|
+ if (source) {
|
|
|
+ scanInvType.value = source.scanValue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+defineExpose({
|
|
|
+ onDisplay: (_invType, _invNo) => {
|
|
|
+ visible.value = true;
|
|
|
+ invType.value = _invType;
|
|
|
+ invNo.value = _invNo;
|
|
|
+ }
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <el-dialog v-model="visible">
|
|
|
+ <el-form
|
|
|
+ ref="formRef"
|
|
|
+ :model="formData"
|
|
|
+ :rules="rules"
|
|
|
+ label-width="90px"
|
|
|
+ class="demo-ruleForm"
|
|
|
+ size="small"
|
|
|
+ status-icon
|
|
|
+ >
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="输入类型" prop="input_type">
|
|
|
+ <el-select
|
|
|
+ v-model="formData.input_type"
|
|
|
+ style="width: 100%"
|
|
|
+ placeholder="菜单类型"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="(si, sii) in input_type_list"
|
|
|
+ :key="'type' + si.value + sii"
|
|
|
+ :label="si.label"
|
|
|
+ :value="si.value"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <el-col
|
|
|
+ :span="24"
|
|
|
+ style="padding: 12px 12px 12px 16px"
|
|
|
+ v-if="formData.input_type === '1'"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ clearable
|
|
|
+ v-model="scanInputValue"
|
|
|
+ :rows="3"
|
|
|
+ type="textarea"
|
|
|
+ placeholder="扫码枪输入处"
|
|
|
+ @keydown="handleScanKeydown"
|
|
|
+ />
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-form-item label="发票类型">
|
|
|
+ <el-select style="width: 100%" v-model="scanInvType" disabled>
|
|
|
+ <el-option
|
|
|
+ v-for="inv in xs_inv_type_list"
|
|
|
+ :key="inv.scanValue"
|
|
|
+ :value="inv.scanValue"
|
|
|
+ :label="inv.label"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="发票号码" prop="inv_number">
|
|
|
+ <el-input
|
|
|
+ v-model="formData.inv_number"
|
|
|
+ placeholder="发票号码"
|
|
|
+ :disabled="disabled"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="发票代码" prop="inv_code">
|
|
|
+ <el-input
|
|
|
+ v-model="formData.inv_code"
|
|
|
+ placeholder="发票代码"
|
|
|
+ :disabled="disabled"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="开票日期" prop="open_date">
|
|
|
+ <el-date-picker
|
|
|
+ style="width: 100%"
|
|
|
+ value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
+ v-model="formData.open_date"
|
|
|
+ :disabled="disabled"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="税前金额" prop="inv_subtotal">
|
|
|
+ <el-input-number
|
|
|
+ v-model="formData.inv_subtotal"
|
|
|
+ :precision="2"
|
|
|
+ style="width: 100%"
|
|
|
+ :min="0"
|
|
|
+ :max="999999"
|
|
|
+ :disabled="disabled"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="校验码" prop="check_code">
|
|
|
+ <el-input
|
|
|
+ placeholde="请输入校验码"
|
|
|
+ v-model="formData.check_code"
|
|
|
+ :disabled="disabled"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <div class="flex justify-end">
|
|
|
+ <el-button type="primary" :loading="loading" @click="handleSaveStatus"
|
|
|
+ >保存</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ </el-dialog>
|
|
|
+</template>
|