父子组件之间数据交互和监听解决方案,和解决ant-design-vue复选框翻页后数据丢失的问题

父子组件之间数据交互和监听解决方案,和解决ant-design-vue复选框翻页后数据丢失的问题
以下是父组件代码

<template>
  <AvicModal :visible="true" title="添加" width="960px" height="520px" :centered="true" @cancel="closeModal">
    <a-spin :spinning="loading">
      <h2 :style="{ 'font-weight': 'bold', 'text-align': 'center', 'margin-top': '0px', 'font-size': '34px' }">{{ addTypeText }}</h2>
      <a-form ref="formRef" :model="form" :rules="rules" v-bind="layout" class="form-excel-style">
        <a-row>
          <a-col v-bind="colLayout.cols">
            <a-form-item name="applyNo" label="申请单编码" has-feedback>
              <AvicAutoCode
                ref="autoCode"
                v-model:value="form.applyNo"
                code-type="ASSET_TRANSFER_CODE"
                code-param="ASSET_TRANSFER"
                :allow-clear="true"
                :disabled="false"
                placeholder="请输入编码"
              />
            </a-form-item>
          </a-col>
          <a-col v-bind="colLayout.cols">
            <a-form-item name="title" label="标题">
              <a-input v-model:value="form.title" :maxlength="256" placeholder="请输入标题" />
            </a-form-item>
          </a-col>
          <a-col v-bind="colLayout.cols">
            <a-form-item name="manageDeptId" label="主管部门名称">
              <AvicCommonSelect
                v-model:value="form.manageDeptId"
                type="deptSelect"
                placeholder="请选择需求部门"
                @callback="
                  (result) => {
                    form.manageDeptName = result.names;
                    form.manageDeptCode = result.deptNamePath;
                  }
                "
              />
            </a-form-item>
          </a-col>
          <a-col v-bind="colLayout.cols">
            <a-form-item name="inDeptId" label="调入部门">
              <AvicCommonSelect
                v-model:value="form.inDeptId"
                type="deptSelect"
                placeholder="请选择调入部门"
                @callback="
                  (result) => {
                    form.inDeptName = result.names;
                    form.inDeptCode = result.deptNamePath;
                  }
                "
              />
            </a-form-item>
          </a-col>
          <a-col v-bind="colLayout.cols">
            <a-form-item name="outDeptId" label="调出部门">
              <AvicCommonSelect
                v-model:value="form.outDeptId"
                type="deptSelect"
                placeholder="请选择调出部门"
                @callback="
                  (result) => {
                    form.outDeptName = result.names;
                    form.outDeptCode = result.deptNamePath;
                  }
                "
              />
              <!-- <a-input v-model:value="form.outDeptId" :maxlength="50" placeholder="请输入调出部门" /> -->
            </a-form-item>
          </a-col>
          <a-col v-bind="colLayout.cols">
            <a-form-item name="operatorId" label="经办人" has-feedback>
              <AvicCommonSelect
                v-model:value="form.operatorId"
                type="userSelect"
                placeholder="请选择经办人"
                @callback="
                  (result) => {
                    form.operatorName = result.names;
                    form.operatorCode = result.deptNamePath;
                  }
                "
              />
            </a-form-item>
            <!-- 
            <a-form-item name="operatorId" label="经办人">
              <a-input v-model:value="form.operatorId" :maxlength="50" placeholder="请输入经办人" />
            </a-form-item> -->
          </a-col>
          <a-col v-bind="colLayout.cols">
            <a-form-item name="applyDate" label="申请时间">
              <a-date-picker v-model:value="form.applyDate" format="YYYY-MM-DD" value-format="YYYY-MM-DD" placeholder="请选择申请时间" />
            </a-form-item>
          </a-col>
          <a-col v-bind="colLayout.cols">
            <a-form-item name="secretLevel" label="单据密级" has-feedback>
              <a-select
                v-model:value="form.secretLevel"
                :get-popup-container="(triggerNode) => triggerNode.parentNode"
                :allow-clear="true"
                placeholder="请选择单据密级"
              >
                <a-select-option v-for="item in secretLevelList" :key="item.sysLookupTlId" :value="item.lookupCode">
                  {{ item.lookupName }}
                </a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :span="24">
            <a-form-item name="transferReason" label="调入原因">
              <a-input v-model:value="form.transferReason" :maxlength="4000" placeholder="请输入调入原因" />
            </a-form-item>
          </a-col>
          <a-col v-bind="colLayout.cols2">
            <a-form-item label="附件">
              <AvicUploader
                ref="uploadFile"
                element-id="1"
                form-type="add"
                table-name="AMS_ASSET_TRANSFER_MAIN"
                :form-id="form.id"
                :allow-download="true"
                :allow-preview="true"
                :allow-delete="true"
                :allow-update-secret-level="true"
                :form-secret-level="form.secretLevel"
                @afterUpload="afterUploadEvent"
              />
            </a-form-item>
          </a-col>
        </a-row>
        <div style="margin-top: 10px">
          <a-button title="批量添加" type="primary" @click="showModal">
            <template #icon>
              <plus-outlined />
            </template>
            批量添加
          </a-button>
          <a-button title="删除" danger @click="handleDelete" :style="{ 'margin-left': '10px' }">
            <template #icon>
              <plus-outlined />
            </template>
            删除
          </a-button>
          <a-modal
            v-model:visible="visible"
            title=""
            :okButtonProps="{ hidden: false }"
            :cancelButtonProps="{ hidden: true }"
            @ok="handleOk"
            width="100%"
            wrapClassName="full-modal"
          >
            <amsTeansferAssetDetailSelect
              @select="selectFor"
              v-if="props.addType === 'ASSET'"
              :existsArr="selectList"
            ></amsTeansferAssetDetailSelect>
            <amsTransferFurnitureDetailSelect
              @select="selectFor"
              v-if="props.addType === 'FURNITURE'"
              :existsArr="selectList"
            ></amsTransferFurnitureDetailSelect>
          </a-modal>
        </div>
        <div>
          <a-table
            v-if="props.addType === 'ASSET'"
            :columns="assetColumns"
            :data-source="selectList"
            :row-selection="rowSelection"
            row-key="id"
          ></a-table>
          <a-table
            v-if="props.addType === 'FURNITURE'"
            :columns="furnitureColumns"
            :data-source="selectList"
            :row-selection="rowSelection"
            row-key="id"
          ></a-table>
        </div>
      </a-form>
    </a-spin>
    <template #footer>
      <a-button title="保存并启动流程" type="primary" :loading="loading" @click="saveAndStartProcess">保存并启动流程</a-button>
      <a-button title="返回" type="primary" ghost @click="closeModal">返回</a-button>
    </template>
  </AvicModal>
</template>
<script lang="ts" setup>
import { useAmsAssetTransferMainForm, emits } from './ts/AmsAssetTransferMainForm'; // 引入表单ts
import amsTeansferAssetDetailSelect from './AmsTransferAssetDetailSelect.vue';
import amsTransferFurnitureDetailSelect from './AmsTransferFurnitureDetailSelect.vue';

const props = defineProps({
  formId: {
    type: String,
    default: ''
  },
  bpmInstanceObject: {
    type: Object,
    default: null
  },
  params: {
    type: Object,
    required: false,
    default: null
  },
  bpmOperatorRefresh: {
    type: Function,
    default: null
  },
  addType: {
    type: String,
    default: ''
  }
});
const emit = defineEmits(emits);
const { form, formRef, rules, layout, colLayout, loading, secretLevelList, uploadFile, afterUploadEvent, saveAndStartProcess, closeModal } =
  useAmsAssetTransferMainForm({
    props,
    emit
  });

const visible = ref<boolean>(false);

const handleOk = (e: MouseEvent) => {
  visible.value = false;
};

const showModal = () => {
  visible.value = true;
};

const selectList = ref([]);

const selectedRowKeys = ref<string[]>([]); // 新增选中行key存储
// 行选择配置
const rowSelection = computed(() => ({
  selectedRowKeys: selectedRowKeys.value,
  onChange: (newSelectedRowKeys: string[]) => {
    selectedRowKeys.value = newSelectedRowKeys;
  },
  // 可选:自定义选择列宽度
  columnWidth: 60
}));
// 删除选中行
const handleDelete = () => {
  console.log('handleDelete', selectedRowKeys.value);
  selectList.value = selectList.value.filter((item) => !selectedRowKeys.value.includes(item.id));
  selectedRowKeys.value = []; // 清空选中状态
  if (props.addType === 'ASSET') {
    form.value.amsTransferAssetDetailDto = selectList.value;
  } else {
    form.value.amsTransferFurnitureDetailDto = selectList.value;
  }
};

const addTypeText = computed(() => (props.addType === 'ASSET' ? '资产调拨申请' : '办公家具调拨申请'));
form.value.transferType = props.addType;

const selectFor = (value) => {
  console.log('selectFor', value);
  selectList.value = value.value;
  if (props.addType === 'ASSET') {
    form.value.amsTransferAssetDetailDto = selectList.value;
  } else {
    form.value.amsTransferFurnitureDetailDto = selectList.value;
  }
};

const assetColumns = [
  {
    title: '资产编码',
    dataIndex: 'assetCode',
    key: 'assetCode'
  },
  {
    title: '资产名称',
    dataIndex: 'assetName',
    key: 'assetName'
  },
  {
    title: '资产密级',
    dataIndex: 'secretLevelName',
    key: 'secretLevelName'
  },
  {
    title: '责任人',
    dataIndex: 'responsibleUserName',
    key: 'responsibleUserName'
  },
  {
    title: '资产型号',
    dataIndex: 'assetModel',
    key: 'assetModel'
  },
  {
    title: '资产是否完好',
    dataIndex: 'ifIntact',
    key: 'ifIntact'
  },
  {
    title: '资产原值(元)',
    dataIndex: 'originalValue',
    key: 'originalValue'
  },
  {
    title: '出厂序列号',
    dataIndex: 'serialNumber',
    key: 'serialNumber'
  },
  {
    title: '资产规格',
    dataIndex: 'assetSpec',
    key: 'assetSpec'
  }
];

const furnitureColumns = [
  {
    title: '办公用品编号',
    dataIndex: 'furnitureCode',
    key: 'furnitureCode'
  },
  {
    title: '办公用品类别',
    dataIndex: 'category',
    key: 'category'
  },
  {
    title: '上架情况',
    dataIndex: 'shelfStatus',
    key: 'shelfStatus'
  },
  {
    title: '办公用品名称',
    dataIndex: 'furnitureName',
    key: 'furnitureName'
  },
  {
    title: '牌号',
    dataIndex: 'brand',
    key: 'brand'
  },
  {
    title: '规格',
    dataIndex: 'specification',
    key: 'specification'
  },
  {
    title: '计量单位',
    dataIndex: 'unitName',
    key: 'unitName'
  },
  {
    title: '单价',
    dataIndex: 'unitPrice',
    key: 'unitPrice'
  },
  {
    title: '库存数量',
    dataIndex: 'stockQty',
    key: 'stockQty'
  }
];
</script>

点击批量添加,如果父组件有数据,子组件直接变成勾选状态,弹出子组件后,如果点击数据,就把数据传给父组件(鸡贼的把取消按钮去掉了),删除只能通过父组件删除(这样解决了翻页后数据丢失的问题)
以下是子组件代码

<template>
  <div class="content-wrapper">
    <div class="top-search-box">
      <!-- 高级查询 -->
      <a-form v-bind="layout" ref="formRef" :model="queryForm">
        <a-row :gutter="16">
          <a-col v-bind="colLayout.cols">
            <a-form-item label="资产调拨主表ID">
              <a-input
                v-model:value="queryForm.amsAssetTransferMainId"
                placeholder="请输入资产调拨主表ID"
                :allow-clear="true"
                @pressEnter="handleQuery"
              />
            </a-form-item>
          </a-col>
          <a-col v-bind="colLayout.cols">
            <a-form-item label="资产编码">
              <a-input v-model:value="queryForm.assetCode" placeholder="请输入资产编码" :allow-clear="true" @pressEnter="handleQuery" />
            </a-form-item>
          </a-col>
          <a-col v-bind="colLayout.cols">
            <a-form-item label="资产名称">
              <a-input v-model:value="queryForm.assetName" placeholder="请输入资产名称" :allow-clear="true" @pressEnter="handleQuery" />
            </a-form-item>
          </a-col>
          <a-col v-show="advanced" v-bind="colLayout.cols">
            <a-form-item label="责任人">
              <a-input
                v-model:value="queryForm.responsibleUserId"
                placeholder="请输入责任人"
                :allow-clear="true"
                @pressEnter="handleQuery"
              />
            </a-form-item>
          </a-col>
          <a-col v-show="advanced" v-bind="colLayout.cols">
            <a-form-item label="责任人">
              <a-input
                v-model:value="queryForm.responsibleUserCode"
                placeholder="请输入责任人"
                :allow-clear="true"
                @pressEnter="handleQuery"
              />
            </a-form-item>
          </a-col>
          <a-col v-show="advanced" v-bind="colLayout.cols">
            <a-form-item label="责任人">
              <a-input
                v-model:value="queryForm.responsibleUserName"
                placeholder="请输入责任人"
                :allow-clear="true"
                @pressEnter="handleQuery"
              />
            </a-form-item>
          </a-col>
          <a-col v-show="advanced" v-bind="colLayout.cols">
            <a-form-item label="资产型号">
              <a-input v-model:value="queryForm.assetModel" placeholder="请输入资产型号" :allow-clear="true" @pressEnter="handleQuery" />
            </a-form-item>
          </a-col>
          <a-col v-show="advanced" v-bind="colLayout.cols">
            <a-form-item label="资产是否完好">
              <a-input v-model:value="queryForm.ifIntact" placeholder="请输入资产是否完好" :allow-clear="true" @pressEnter="handleQuery" />
            </a-form-item>
          </a-col>
          <a-col v-show="advanced" v-bind="colLayout.cols">
            <a-form-item label="出厂序列号">
              <a-input
                v-model:value="queryForm.serialNumber"
                placeholder="请输入出厂序列号"
                :allow-clear="true"
                @pressEnter="handleQuery"
              />
            </a-form-item>
          </a-col>
          <a-col v-show="advanced" v-bind="colLayout.cols">
            <a-form-item label="资产规格">
              <a-input v-model:value="queryForm.assetSpec" placeholder="请输入资产规格" :allow-clear="true" @pressEnter="handleQuery" />
            </a-form-item>
          </a-col>
          <a-col v-show="advanced" v-bind="colLayout.cols">
            <a-form-item label="存放地点">
              <a-input
                v-model:value="queryForm.storageLocation"
                placeholder="请输入存放地点"
                :allow-clear="true"
                @pressEnter="handleQuery"
              />
            </a-form-item>
          </a-col>
          <a-col v-show="advanced" v-bind="colLayout.cols">
            <a-form-item label="SECRET_LEVEL">
              <a-select
                v-model:value="queryForm.secretLevel"
                :get-popup-container="(triggerNode) => triggerNode.parentNode"
                :allow-clear="true"
                placeholder="请选择SECRET_LEVEL"
              >
                <a-select-option v-for="item in secretLevelList" :key="item.sysLookupTlId" :value="item.lookupCode">
                  {{ item.lookupName }}
                </a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col v-bind="colLayout.cols" style="margin-left: auto">
            <div class="table-page-search-submitButtons">
              <a-space>
                <AvicAdvancedQueryButton
                  table-key="amsTransferAssetDetail"
                  :query-form="queryForm"
                  :advanced="advanced"
                  @select="
                    (value, advancedFlag) => {
                      queryForm = value;
                      advanced = !advanced ? advancedFlag : advanced;
                    }
                  "
                  @search="handleQuery"
                />
                <a-button type="primary" ghost @click="resetQuery">
                  <redo-outlined />
                  重置
                </a-button>
                <a-button type="link" style="margin: 0" @click="toggleAdvanced">
                  {{ advanced ? '收起' : '展开' }}
                  <up-outlined v-if="advanced" />
                  <down-outlined v-else />
                </a-button>
              </a-space>
            </div>
          </a-col>
        </a-row>
      </a-form>
    </div>
    <!-- 表格组件 -->
    <div class="table-wrapper">
      <AvicTable
        ref="amsTransferAssetDetailSelect"
        table-key="amsTransferAssetDetailSelect"
        :columns="columns"
        :row-key="(record) => record.id"
        :data-source="list"
        :loading="loading"
        :show-table-setting="false"
        :row-selection="{
          selectedRowKeys: selectedRowKeys,
          onChange: onSelectChange,
          columnWidth: 40,
          fixed: true
        }"
        :page-parameter="queryParam.pageParameter"
        :total="totalPage"
        :custom-row="customRow"
        @change="handleTableChange"
        @refresh="getList"
      >
        <template #toolBarRight>
          <a-input-search
            class="opt-btn-commonsearch"
            style="width: 200px"
            placeholder="请输入"
            title="请输入"
            :allow-clear="true"
            @search="handleKeyWordQuery"
          />
        </template>
        <template #bodyCell="{ column, text, record, index }">
          <template v-if="column.dataIndex === 'id'">
            {{ index + 1 + queryParam.pageParameter.rows * (queryParam.pageParameter.page - 1) }}
          </template>
        </template>
      </AvicTable>
    </div>
  </div>
</template>
<script lang="ts" setup>
import type { AmsTransferAssetDetailDto } from '@/api/avic/mms/ams/amsassettransfermain/AmsTransferAssetDetailApi'; // 引入模块DTO
import { listAmsTransferAssetDetailByPage } from '@/api/avic/mms/ams/amsassettransfermain/AmsTransferAssetDetailApi'; // 引入模块API
const $emit = defineEmits(['select', 'handleRowDblClick']);
const props = defineProps({
  existsArr: {
    type: Array,
    default: () => []
  }
});
watch(
  () => props.existsArr,
  (newValue) => {
    if (newValue) {
      console.log('existsArr', newValue);
      selectedRowKeys.value = newValue.map((item) => item.id);
      selectedRows.value = newValue;
    } else {
      selectedRowKeys.value = [];
      selectedRows.value = [];
    }
  },
  { deep: true, immediate: false } // 如果需要初始执行可以加 immediate: true
);
const amsTransferAssetDetailSelect = ref();
const { proxy } = getCurrentInstance();
const layout = {
  labelCol: { flex: '0 0 120px' },
  wrapperCol: { flex: '1 1 0' }
};
const colLayout = proxy.$colLayout4; // 页面表单响应式布局对象
const columns = [
  {
    title: '资产编码',
    dataIndex: 'assetCode',
    ellipsis: true,
    sorter: true,
    minWidth: 120,
    resizable: true,
    align: 'left'
  },
  {
    title: '资产名称',
    dataIndex: 'assetName',
    ellipsis: true,
    sorter: true,
    minWidth: 120,
    resizable: true,
    align: 'left'
  },
  {
    title: '责任人',
    dataIndex: 'responsibleUserName',
    ellipsis: true,
    sorter: true,
    minWidth: 120,
    resizable: true,
    align: 'left'
  },
  {
    title: '资产型号',
    dataIndex: 'assetModel',
    ellipsis: true,
    sorter: true,
    minWidth: 120,
    resizable: true,
    align: 'left'
  },
  {
    title: '资产是否完好',
    dataIndex: 'ifIntact',
    ellipsis: true,
    sorter: true,
    minWidth: 120,
    resizable: true,
    align: 'left'
  },
  {
    title: '资产原值(元)',
    dataIndex: 'originalValue',
    ellipsis: true,
    minWidth: 120,
    resizable: true,
    customRender: (text) => proxy.$formatZero(text.value, 7),
    align: 'right'
  },
  {
    title: '出厂序列号',
    dataIndex: 'serialNumber',
    ellipsis: true,
    sorter: true,
    minWidth: 120,
    resizable: true,
    align: 'left'
  },
  {
    title: '资产规格',
    dataIndex: 'assetSpec',
    ellipsis: true,
    sorter: true,
    minWidth: 120,
    resizable: true,
    align: 'left'
  },
  {
    title: '存放地点',
    dataIndex: 'storageLocation',
    ellipsis: true,
    sorter: true,
    minWidth: 120,
    resizable: true,
    align: 'left'
  },
  {
    title: 'SECRET_LEVEL',
    dataIndex: 'secretLevelName',
    ellipsis: true,
    minWidth: 120,
    resizable: true,
    customHeaderCell() {
      return {
        ['class']: 'required-table-title'
      };
    },
    align: 'center'
  },
  {
    title: '操作',
    dataIndex: 'action',
    ellipsis: true,
    visible: false,
    width: 120,
    fixed: 'right'
  }
];
const queryForm = ref<AmsTransferAssetDetailDto>({});
const queryParam = reactive({
  // 请求表格数据参数
  pageParameter: {
    page: 1, // 页数
    rows: proxy.$settings.table.pageSize || 20 // 每页条数
  },
  searchParams: {
    ...queryForm.value
  },
  keyWord: ref(''), // 快速查询数据
  sidx: null, // 排序字段
  sord: null // 排序方式: desc降序 asc升序
});
const advanced = ref(false); // 高级搜索 展开/关闭
const list = ref([]); // 表格数据集合
const selectedRowKeys = ref([]); // 选中数据主键集合
const selectedRows = ref([]); // 选中行集合
const loading = ref(false);
const totalPage = ref(0);
const secretLevelList = ref([]); // SECRET_LEVEL通用代码

onMounted(() => {
  // 加载表格数据
  getList();
  // 获取当前用户对应的文档密级
  getUserFileSecretList();
});
/** 查询数据  */
function getList() {
  // selectedRowKeys.value = []; // 清空选中
  // selectedRows.value = []; // 清空选中
  loading.value = true;
  listAmsTransferAssetDetailByPage(queryParam)
    .then((response) => {
      list.value = response.data.result;
      totalPage.value = response.data.pageParameter.totalCount;
      loading.value = false;
    })
    .catch(() => {
      list.value = [];
      totalPage.value = 0;
      loading.value = false;
    });
}
/** 获取当前用户对应的文档密级 */
function getUserFileSecretList() {
  proxy.$getUserFileSecretLevelList((result) => {
    secretLevelList.value = result;
  });
}
/** 高级查询 查询按钮操作 */
function handleQuery() {
  queryParam.searchParams = queryForm.value;
  queryParam.keyWord = '';
  queryParam.pageParameter.page = 1;
  getList();
}
/** 高级查询 重置按钮操作 */
function resetQuery() {
  queryForm.value = {};
  handleQuery();
}
/** 高级查询 展开/收起 */
function toggleAdvanced() {
  advanced.value = !advanced.value;
}
/** 快速查询逻辑 */
function handleKeyWordQuery(value) {
  queryParam.keyWord = value;
  queryParam.pageParameter.page = 1;
  getList();
}

/** 勾选复选框时触发 */
function onSelectChange(rowKeys, rows) {
  nextTick(() => {
    // 1. 获取旧值(避免直接修改原数组)
    const oldRowKeys = [...selectedRowKeys.value];
    const oldRows = [...selectedRows.value];
    // 2. 合并新值和旧值(根据需求选择是否去重)
    // 方案一:直接追加(允许重复选择)
    const mergedRowKeys = [...oldRowKeys, ...rowKeys];
    const mergedRows = [...oldRows, ...rows];
    const uniqueRowKeys = [...new Set(mergedRowKeys)]; // 对 rowKeys 去重
    const uniqueRows = mergedRows.filter((item, index, self) => index === self.findIndex((t) => t.id === item.id)); // 对 rows 根据 id 去重
    selectedRowKeys.value = uniqueRowKeys;
    selectedRows.value = uniqueRows;
    // 传出选中项
    $emit('select', selectedRows);
  });
}
// function onSelectChange(rowKeys, rows) {
//   selectedRowKeys.value = rowKeys;
//   selectedRows.value = rows;
//   // 传出选中项
//   $emit('select', selectedRows);
// }
/** 表格排序 */
function handleTableChange(pagination, _filters, sorter) {
  queryParam.pageParameter.page = pagination.current;
  queryParam.pageParameter.rows = pagination.pageSize;
  if (proxy.$objIsNotBlank(sorter.field)) {
    queryParam.sidx = sorter.field;
    queryParam.sord = sorter.order === 'ascend' ? 'asc' : 'desc'; // 排序方式: desc降序 asc升序
  }
  getList();
}
/** 行双击事件 */
function customRow() {
  return {
    on: {
      dblclick: (event, record) => {
        $emit('handleRowDblClick', [record]);
      }
    }
  };
}

onMounted(() => {
  if (props.existsArr) {
    selectedRowKeys.value = props.existsArr.map((item) => item.id);
    selectedRows.value = props.existsArr;
  }
});
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值