<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '型号管理' }" :custom-row="(record: any) => ({ onClick: () => showChangeLog(record), style: { cursor: 'pointer' } })">
      <template #toolbar-actions>
        <a-button v-permission="'base:model:add'" type="primary" @click="handleAdd"><PlusOutlined /> 新增型号</a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'operations'">
          <a-space :size="4" @click.stop>
            <a-button v-permission="'base:model:edit'" type="link" size="small" @click.stop="handleEdit(record)"><EditOutlined /> 编辑</a-button>
            <a-popconfirm v-permission="'base:model:delete'" title="确认删除？" @confirm="handleDelete(record.id)">
              <a-button type="link" size="small" danger @click.stop><DeleteOutlined /> 删除</a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </ProTable>

    <a-modal v-model:open="visible" :title="isEdit ? '编辑型号' : '新增型号'" @ok="handleSubmit" width="600px">
      <a-form :model="form" :label-col="{ span: 6 }">
        <a-form-item label="型号名称" required><a-input v-model:value="form.name" /></a-form-item>
        <a-form-item label="型号编号"><a-input v-model:value="form.model_number" /></a-form-item>
        <a-form-item label="制造商ID"><a-input v-model:value="form.manufacturer_id" /></a-form-item>
        <a-form-item label="分类ID"><a-input v-model:value="form.category_id" /></a-form-item>
      </a-form>
    </a-modal>

    <a-modal v-model:open="logVisible" title="变更记录" width="800px" :footer="null">
      <a-table :columns="logColumns" :data-source="logData" :pagination="false" size="small" row-key="id">
        <template #bodyCell="{ column, record: row }">
          <template v-if="column.key === 'change_type'">
            <a-tag :color="row.change_type === 'create' ? 'green' : row.change_type === 'delete' ? 'red' : 'blue'">{{ row.change_type === 'create' ? '新增' : row.change_type === 'delete' ? '删除' : '修改' }}</a-tag>
          </template>
        </template>
      </a-table>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message } from "antdv-next";
import { ref } from "vue";
import { modelApi, changeRecordApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const tableRef = ref();
const visible = ref(false); const isEdit = ref(false);
const form = ref<Record<string, unknown>>({});

const logVisible = ref(false);
const logData = ref<Record<string, unknown>[]>([]);
const logColumns = [
  { title: "时间", dataIndex: "create_time", key: "create_time", width: 170 },
  { title: "变更类型", dataIndex: "change_type", key: "change_type", width: 80 },
  { title: "变更字段", dataIndex: "field_name", key: "field_name", width: 120 },
  { title: "旧值", dataIndex: "old_value", key: "old_value", ellipsis: true },
  { title: "新值", dataIndex: "new_value", key: "new_value", ellipsis: true },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name", width: 100 },
];

const columns: ProTableColumn[] = [
  { title: "型号名称", dataIndex: "name", key: "name", search: true, searchType: "input" },
  { title: "型号编号", dataIndex: "model_number", key: "model_number" },
  { title: "制造商", dataIndex: "manufacturer_name", key: "manufacturer_name" },
  { title: "分类", dataIndex: "category_name", key: "category_name" },
  { title: "操作", dataIndex: "operations", key: "operations", width: 200, fixed: "right" as const },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await modelApi.page({ page: params.current, pageSize: params.pageSize, keyword: params.keyword });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};

const showChangeLog = async (record: Record<string, unknown>) => {
  try {
    const res: any = await changeRecordApi.page({ asset_type: "model", asset_id: record.id, page: 1, pageSize: 200 });
    logData.value = (res.data || res).list || [];
    logVisible.value = true;
  } catch { message.error("获取变更记录失败"); }
};

const handleAdd = () => { isEdit.value = false; form.value = {}; visible.value = true; };
const handleEdit = (r: Record<string, unknown>) => { isEdit.value = true; form.value = { ...r }; visible.value = true; };
const handleDelete = async (id: string) => {
  await modelApi.del(id);
  message.success("删除成功");
  tableRef.value?.reload();
};
const handleSubmit = async () => {
  await modelApi.save(form.value);
  message.success(isEdit.value ? "更新成功" : "创建成功");
  visible.value = false;
  tableRef.value?.reload();
};
</script>


Write

<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '供应商' }" :custom-row="(record: any) => ({ onClick: () => showChangeLog(record), style: { cursor: 'pointer' } })">
      <template #toolbar-actions>
        <a-button v-permission="'base:supplier:add'" type="primary" @click="handleAdd"><PlusOutlined /> 新增供应商</a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'operations'">
          <a-space :size="4" @click.stop>
            <a-button v-permission="'base:supplier:edit'" type="link" size="small" @click.stop="handleEdit(record)"><EditOutlined /> 编辑</a-button>
            <a-popconfirm v-permission="'base:supplier:delete'" title="确认删除？" @confirm="handleDelete(record.id)">
              <a-button type="link" size="small" danger @click.stop><DeleteOutlined /> 删除</a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </ProTable>

    <a-modal v-model:open="visible" :title="isEdit ? '编辑供应商' : '新增供应商'" @ok="handleSubmit" width="600px">
      <a-form :model="form" :label-col="{ span: 6 }">
        <a-form-item label="名称" required><a-input v-model:value="form.name" /></a-form-item>
        <a-form-item label="联系人"><a-input v-model:value="form.contact_name" /></a-form-item>
        <a-form-item label="电话"><a-input v-model:value="form.phone" /></a-form-item>
        <a-form-item label="备注"><a-textarea v-model:value="form.remark" :rows="2" /></a-form-item>
      </a-form>
    </a-modal>

    <a-modal v-model:open="logVisible" title="变更记录" width="800px" :footer="null">
      <a-table :columns="logColumns" :data-source="logData" :pagination="false" size="small" row-key="id">
        <template #bodyCell="{ column, record: row }">
          <template v-if="column.key === 'change_type'">
            <a-tag :color="row.change_type === 'create' ? 'green' : row.change_type === 'delete' ? 'red' : 'blue'">{{ row.change_type === 'create' ? '新增' : row.change_type === 'delete' ? '删除' : '修改' }}</a-tag>
          </template>
        </template>
      </a-table>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message } from "antdv-next";
import { ref } from "vue";
import { supplierApi, changeRecordApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const tableRef = ref();
const visible = ref(false); const isEdit = ref(false);
const form = ref<Record<string, unknown>>({});

const logVisible = ref(false);
const logData = ref<Record<string, unknown>[]>([]);
const logColumns = [
  { title: "时间", dataIndex: "create_time", key: "create_time", width: 170 },
  { title: "变更类型", dataIndex: "change_type", key: "change_type", width: 80 },
  { title: "变更字段", dataIndex: "field_name", key: "field_name", width: 120 },
  { title: "旧值", dataIndex: "old_value", key: "old_value", ellipsis: true },
  { title: "新值", dataIndex: "new_value", key: "new_value", ellipsis: true },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name", width: 100 },
];

const columns: ProTableColumn[] = [
  { title: "名称", dataIndex: "name", key: "name", search: true, searchType: "input" },
  { title: "联系人", dataIndex: "contact_name", key: "contact_name" },
  { title: "电话", dataIndex: "phone", key: "phone" },
  { title: "备注", dataIndex: "remark", key: "remark", ellipsis: true },
  { title: "操作", dataIndex: "operations", key: "operations", width: 200, fixed: "right" as const },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await supplierApi.page({ page: params.current, pageSize: params.pageSize, keyword: params.keyword });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};

const showChangeLog = async (record: Record<string, unknown>) => {
  try {
    const res: any = await changeRecordApi.page({ asset_type: "supplier", asset_id: record.id, page: 1, pageSize: 200 });
    logData.value = (res.data || res).list || [];
    logVisible.value = true;
  } catch { message.error("获取变更记录失败"); }
};

const handleAdd = () => { isEdit.value = false; form.value = {}; visible.value = true; };
const handleEdit = (r: Record<string, unknown>) => { isEdit.value = true; form.value = { ...r }; visible.value = true; };
const handleDelete = async (id: string) => {
  await supplierApi.del(id);
  message.success("删除成功");
  tableRef.value?.reload();
};
const handleSubmit = async () => {
  await supplierApi.save(form.value);
  message.success(isEdit.value ? "更新成功" : "创建成功");
  visible.value = false;
  tableRef.value?.reload();
};
</script>


File created successfully at: c:\Workspace\Project\tansci\antdv-next-admin\src\views\asset\base\category\index.vue (file state is current in your context — no need to Read it back)

<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '资产分类' }" :custom-row="(record: any) => ({ onClick: () => showChangeLog(record), style: { cursor: 'pointer' } })">
      <template #toolbar-actions>
        <a-button v-permission="'base:category:add'" type="primary" @click="handleAdd"><PlusOutlined /> 新增分类</a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'category_type'">
          <a-tag>{{ record.category_type }}</a-tag>
        </template>
        <template v-if="column.key === 'operations'">
          <a-space :size="4" @click.stop>
            <a-button v-permission="'base:category:edit'" type="link" size="small" @click.stop="handleEdit(record)"><EditOutlined /> 编辑</a-button>
            <a-popconfirm v-permission="'base:category:delete'" title="确认删除？" @confirm="handleDelete(record.id)">
              <a-button type="link" size="small" danger @click.stop><DeleteOutlined /> 删除</a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </ProTable>

    <a-modal v-model:open="visible" :title="isEdit ? '编辑分类' : '新增分类'" @ok="handleSubmit" width="600px">
      <a-form :model="form" :label-col="{ span: 6 }">
        <a-form-item label="分类名称" required><a-input v-model:value="form.name" /></a-form-item>
        <a-form-item label="分类编码" required><a-input v-model:value="form.code" /></a-form-item>
        <a-form-item label="分类大类" required>
          <a-select v-model:value="form.category_type">
            <a-select-option value="device">设备</a-select-option>
            <a-select-option value="license">许可证</a-select-option>
            <a-select-option value="accessory">配件</a-select-option>
            <a-select-option value="consumable">耗材</a-select-option>
            <a-select-option value="service">服务</a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item label="父级分类"><a-input v-model:value="form.parent_id" placeholder="留空为顶级分类" /></a-form-item>
      </a-form>
    </a-modal>

    <a-modal v-model:open="logVisible" title="变更记录" width="800px" :footer="null">
      <a-table :columns="logColumns" :data-source="logData" :pagination="false" size="small" row-key="id">
        <template #bodyCell="{ column, record: row }">
          <template v-if="column.key === 'change_type'">
            <a-tag :color="row.change_type === 'create' ? 'green' : row.change_type === 'delete' ? 'red' : 'blue'">{{ row.change_type === 'create' ? '新增' : row.change_type === 'delete' ? '删除' : '修改' }}</a-tag>
          </template>
        </template>
      </a-table>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message } from "antdv-next";
import { ref } from "vue";
import { categoryApi, changeRecordApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const tableRef = ref();
const visible = ref(false); const isEdit = ref(false);
const form = ref<Record<string, unknown>>({});

const logVisible = ref(false);
const logData = ref<Record<string, unknown>[]>([]);
const logColumns = [
  { title: "时间", dataIndex: "create_time", key: "create_time", width: 170 },
  { title: "变更类型", dataIndex: "change_type", key: "change_type", width: 80 },
  { title: "变更字段", dataIndex: "field_name", key: "field_name", width: 120 },
  { title: "旧值", dataIndex: "old_value", key: "old_value", ellipsis: true },
  { title: "新值", dataIndex: "new_value", key: "new_value", ellipsis: true },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name", width: 100 },
];

const columns: ProTableColumn[] = [
  { title: "分类名称", dataIndex: "name", key: "name", search: true, searchType: "input" },
  { title: "分类编码", dataIndex: "code", key: "code" },
  { title: "分类大类", dataIndex: "category_type", key: "category_type" },
  { title: "父级ID", dataIndex: "parent_id", key: "parent_id", ellipsis: true },
  { title: "操作", dataIndex: "operations", key: "operations", width: 200, fixed: "right" as const },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await categoryApi.page({ page: params.current, pageSize: params.pageSize, keyword: params.keyword });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};

const showChangeLog = async (record: Record<string, unknown>) => {
  try {
    const res: any = await changeRecordApi.page({ asset_type: "category", asset_id: record.id, page: 1, pageSize: 200 });
    logData.value = (res.data || res).list || [];
    logVisible.value = true;
  } catch { message.error("获取变更记录失败"); }
};

const handleAdd = () => { isEdit.value = false; form.value = {}; visible.value = true; };
const handleEdit = (r: Record<string, unknown>) => { isEdit.value = true; form.value = { ...r }; visible.value = true; };
const handleDelete = async (id: string) => {
  await categoryApi.del(id);
  message.success("删除成功");
  tableRef.value?.reload();
};
const handleSubmit = async () => {
  await categoryApi.save(form.value);
  message.success(isEdit.value ? "更新成功" : "创建成功");
  visible.value = false;
  tableRef.value?.reload();
};
</script>


File created successfully at: c:\Workspace\Project\tansci\antdv-next-admin\src\views\asset\base\location\index.vue (file state is current in your context — no need to Read it back)

<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '存放位置' }" :custom-row="(record: any) => ({ onClick: () => showChangeLog(record), style: { cursor: 'pointer' } })">
      <template #toolbar-actions>
        <a-button v-permission="'base:location:add'" type="primary" @click="handleAdd"><PlusOutlined /> 新增位置</a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'operations'">
          <a-space :size="4" @click.stop>
            <a-button v-permission="'base:location:edit'" type="link" size="small" @click.stop="handleEdit(record)"><EditOutlined /> 编辑</a-button>
            <a-popconfirm v-permission="'base:location:delete'" title="确认删除？" @confirm="handleDelete(record.id)">
              <a-button type="link" size="small" danger @click.stop><DeleteOutlined /> 删除</a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </ProTable>

    <a-modal v-model:open="visible" :title="isEdit ? '编辑位置' : '新增位置'" @ok="handleSubmit" width="700px">
      <a-form :model="form" :label-col="{ span: 6 }">
        <a-row :gutter="16">
          <a-col :span="12"><a-form-item label="位置名称" required><a-input v-model:value="form.name" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="建筑"><a-input v-model:value="form.building" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="房间"><a-input v-model:value="form.room" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="城市"><a-input v-model:value="form.city" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="省/州"><a-input v-model:value="form.state" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="国家"><a-input v-model:value="form.country" /></a-form-item></a-col>
          <a-col :span="24"><a-form-item label="详细地址" :label-col="{ span: 3 }"><a-textarea v-model:value="form.address" :rows="2" /></a-form-item></a-col>
        </a-row>
      </a-form>
    </a-modal>

    <a-modal v-model:open="logVisible" title="变更记录" width="800px" :footer="null">
      <a-table :columns="logColumns" :data-source="logData" :pagination="false" size="small" row-key="id">
        <template #bodyCell="{ column, record: row }">
          <template v-if="column.key === 'change_type'">
            <a-tag :color="row.change_type === 'create' ? 'green' : row.change_type === 'delete' ? 'red' : 'blue'">{{ row.change_type === 'create' ? '新增' : row.change_type === 'delete' ? '删除' : '修改' }}</a-tag>
          </template>
        </template>
      </a-table>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message } from "antdv-next";
import { ref } from "vue";
import { locationApi, changeRecordApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const tableRef = ref();
const visible = ref(false); const isEdit = ref(false);
const form = ref<Record<string, unknown>>({});

const logVisible = ref(false);
const logData = ref<Record<string, unknown>[]>([]);
const logColumns = [
  { title: "时间", dataIndex: "create_time", key: "create_time", width: 170 },
  { title: "变更类型", dataIndex: "change_type", key: "change_type", width: 80 },
  { title: "变更字段", dataIndex: "field_name", key: "field_name", width: 120 },
  { title: "旧值", dataIndex: "old_value", key: "old_value", ellipsis: true },
  { title: "新值", dataIndex: "new_value", key: "new_value", ellipsis: true },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name", width: 100 },
];

const columns: ProTableColumn[] = [
  { title: "位置名称", dataIndex: "name", key: "name", search: true, searchType: "input" },
  { title: "建筑", dataIndex: "building", key: "building" },
  { title: "房间", dataIndex: "room", key: "room" },
  { title: "城市", dataIndex: "city", key: "city" },
  { title: "省/州", dataIndex: "state", key: "state" },
  { title: "国家", dataIndex: "country", key: "country" },
  { title: "操作", dataIndex: "operations", key: "operations", width: 200, fixed: "right" as const },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await locationApi.page({ page: params.current, pageSize: params.pageSize, keyword: params.keyword });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};

const showChangeLog = async (record: Record<string, unknown>) => {
  try {
    const res: any = await changeRecordApi.page({ asset_type: "location", asset_id: record.id, page: 1, pageSize: 200 });
    logData.value = (res.data || res).list || [];
    logVisible.value = true;
  } catch { message.error("获取变更记录失败"); }
};

const handleAdd = () => { isEdit.value = false; form.value = {}; visible.value = true; };
const handleEdit = (r: Record<string, unknown>) => { isEdit.value = true; form.value = { ...r }; visible.value = true; };
const handleDelete = async (id: string) => {
  await locationApi.del(id);
  message.success("删除成功");
  tableRef.value?.reload();
};
const handleSubmit = async () => {
  await locationApi.save(form.value);
  message.success(isEdit.value ? "更新成功" : "创建成功");
  visible.value = false;
  tableRef.value?.reload();
};
</script>


File created successfully at: c:\Workspace\Project\tansci\antdv-next-admin\src\views\asset\base\manufacturer\index.vue (file state is current in your context — no need to Read it back)

<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '制造商' }" :custom-row="(record: any) => ({ onClick: () => showChangeLog(record), style: { cursor: 'pointer' } })">
      <template #toolbar-actions>
        <a-button v-permission="'base:manufacturer:add'" type="primary" @click="handleAdd"><PlusOutlined /> 新增制造商</a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'operations'">
          <a-space :size="4" @click.stop>
            <a-button v-permission="'base:manufacturer:edit'" type="link" size="small" @click.stop="handleEdit(record)"><EditOutlined /> 编辑</a-button>
            <a-popconfirm v-permission="'base:manufacturer:delete'" title="确认删除？" @confirm="handleDelete(record.id)">
              <a-button type="link" size="small" danger @click.stop><DeleteOutlined /> 删除</a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </ProTable>

    <a-modal v-model:open="visible" :title="isEdit ? '编辑制造商' : '新增制造商'" @ok="handleSubmit" width="700px">
      <a-form :model="form" :label-col="{ span: 6 }">
        <a-row :gutter="16">
          <a-col :span="12"><a-form-item label="名称" required><a-input v-model:value="form.name" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="官网"><a-input v-model:value="form.url" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="支持URL"><a-input v-model:value="form.support_url" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="保修URL"><a-input v-model:value="form.warranty_url" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="支持电话"><a-input v-model:value="form.support_phone" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="支持邮箱"><a-input v-model:value="form.support_email" /></a-form-item></a-col>
        </a-row>
      </a-form>
    </a-modal>

    <a-modal v-model:open="logVisible" title="变更记录" width="800px" :footer="null">
      <a-table :columns="logColumns" :data-source="logData" :pagination="false" size="small" row-key="id">
        <template #bodyCell="{ column, record: row }">
          <template v-if="column.key === 'change_type'">
            <a-tag :color="row.change_type === 'create' ? 'green' : row.change_type === 'delete' ? 'red' : 'blue'">{{ row.change_type === 'create' ? '新增' : row.change_type === 'delete' ? '删除' : '修改' }}</a-tag>
          </template>
        </template>
      </a-table>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message } from "antdv-next";
import { ref } from "vue";
import { manufacturerApi, changeRecordApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const tableRef = ref();
const visible = ref(false); const isEdit = ref(false);
const form = ref<Record<string, unknown>>({});

const logVisible = ref(false);
const logData = ref<Record<string, unknown>[]>([]);
const logColumns = [
  { title: "时间", dataIndex: "create_time", key: "create_time", width: 170 },
  { title: "变更类型", dataIndex: "change_type", key: "change_type", width: 80 },
  { title: "变更字段", dataIndex: "field_name", key: "field_name", width: 120 },
  { title: "旧值", dataIndex: "old_value", key: "old_value", ellipsis: true },
  { title: "新值", dataIndex: "new_value", key: "new_value", ellipsis: true },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name", width: 100 },
];

const columns: ProTableColumn[] = [
  { title: "名称", dataIndex: "name", key: "name", search: true, searchType: "input" },
  { title: "支持电话", dataIndex: "support_phone", key: "support_phone" },
  { title: "支持邮箱", dataIndex: "support_email", key: "support_email" },
  { title: "操作", dataIndex: "operations", key: "operations", width: 200, fixed: "right" as const },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await manufacturerApi.page({ page: params.current, pageSize: params.pageSize, keyword: params.keyword });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};

const showChangeLog = async (record: Record<string, unknown>) => {
  try {
    const res: any = await changeRecordApi.page({ asset_type: "manufacturer", asset_id: record.id, page: 1, pageSize: 200 });
    logData.value = (res.data || res).list || [];
    logVisible.value = true;
  } catch { message.error("获取变更记录失败"); }
};

const handleAdd = () => { isEdit.value = false; form.value = {}; visible.value = true; };
const handleEdit = (r: Record<string, unknown>) => { isEdit.value = true; form.value = { ...r }; visible.value = true; };
const handleDelete = async (id: string) => {
  await manufacturerApi.del(id);
  message.success("删除成功");
  tableRef.value?.reload();
};
const handleSubmit = async () => {
  await manufacturerApi.save(form.value);
  message.success(isEdit.value ? "更新成功" : "创建成功");
  visible.value = false;
  tableRef.value?.reload();
};
</script>


File created successfully at: c:\Workspace\Project\tansci\antdv-next-admin\src\views\asset\base\model\index.vue (file state is current in your context — no need to Read it back)

<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '型号管理' }" :custom-row="(record: any) => ({ onClick: () => showChangeLog(record), style: { cursor: 'pointer' } })">
      <template #toolbar-actions>
        <a-button v-permission="'base:model:add'" type="primary" @click="handleAdd"><PlusOutlined /> 新增型号</a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'operations'">
          <a-space :size="4" @click.stop>
            <a-button v-permission="'base:model:edit'" type="link" size="small" @click.stop="handleEdit(record)"><EditOutlined /> 编辑</a-button>
            <a-popconfirm v-permission="'base:model:delete'" title="确认删除？" @confirm="handleDelete(record.id)">
              <a-button type="link" size="small" danger @click.stop><DeleteOutlined /> 删除</a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </ProTable>

    <a-modal v-model:open="visible" :title="isEdit ? '编辑型号' : '新增型号'" @ok="handleSubmit" width="600px">
      <a-form :model="form" :label-col="{ span: 6 }">
        <a-form-item label="型号名称" required><a-input v-model:value="form.name" /></a-form-item>
        <a-form-item label="型号编号"><a-input v-model:value="form.model_number" /></a-form-item>
        <a-form-item label="制造商ID"><a-input v-model:value="form.manufacturer_id" /></a-form-item>
        <a-form-item label="分类ID"><a-input v-model:value="form.category_id" /></a-form-item>
      </a-form>
    </a-modal>

    <a-modal v-model:open="logVisible" title="变更记录" width="800px" :footer="null">
      <a-table :columns="logColumns" :data-source="logData" :pagination="false" size="small" row-key="id">
        <template #bodyCell="{ column, record: row }">
          <template v-if="column.key === 'change_type'">
            <a-tag :color="row.change_type === 'create' ? 'green' : row.change_type === 'delete' ? 'red' : 'blue'">{{ row.change_type === 'create' ? '新增' : row.change_type === 'delete' ? '删除' : '修改' }}</a-tag>
          </template>
        </template>
      </a-table>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message } from "antdv-next";
import { ref } from "vue";
import { modelApi, changeRecordApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const tableRef = ref();
const visible = ref(false); const isEdit = ref(false);
const form = ref<Record<string, unknown>>({});

const logVisible = ref(false);
const logData = ref<Record<string, unknown>[]>([]);
const logColumns = [
  { title: "时间", dataIndex: "create_time", key: "create_time", width: 170 },
  { title: "变更类型", dataIndex: "change_type", key: "change_type", width: 80 },
  { title: "变更字段", dataIndex: "field_name", key: "field_name", width: 120 },
  { title: "旧值", dataIndex: "old_value", key: "old_value", ellipsis: true },
  { title: "新值", dataIndex: "new_value", key: "new_value", ellipsis: true },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name", width: 100 },
];

const columns: ProTableColumn[] = [
  { title: "型号名称", dataIndex: "name", key: "name", search: true, searchType: "input" },
  { title: "型号编号", dataIndex: "model_number", key: "model_number" },
  { title: "制造商", dataIndex: "manufacturer_name", key: "manufacturer_name" },
  { title: "分类", dataIndex: "category_name", key: "category_name" },
  { title: "操作", dataIndex: "operations", key: "operations", width: 200, fixed: "right" as const },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await modelApi.page({ page: params.current, pageSize: params.pageSize, keyword: params.keyword });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};

const showChangeLog = async (record: Record<string, unknown>) => {
  try {
    const res: any = await changeRecordApi.page({ asset_type: "model", asset_id: record.id, page: 1, pageSize: 200 });
    logData.value = (res.data || res).list || [];
    logVisible.value = true;
  } catch { message.error("获取变更记录失败"); }
};

const handleAdd = () => { isEdit.value = false; form.value = {}; visible.value = true; };
const handleEdit = (r: Record<string, unknown>) => { isEdit.value = true; form.value = { ...r }; visible.value = true; };
const handleDelete = async (id: string) => {
  await modelApi.del(id);
  message.success("删除成功");
  tableRef.value?.reload();
};
const handleSubmit = async () => {
  await modelApi.save(form.value);
  message.success(isEdit.value ? "更新成功" : "创建成功");
  visible.value = false;
  tableRef.value?.reload();
};
</script>


File created successfully at: c:\Workspace\Project\tansci\antdv-next-admin\src\views\asset\base\supplier\index.vue (file state is current in your context — no need to Read it back)

<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '供应商' }" :custom-row="(record: any) => ({ onClick: () => showChangeLog(record), style: { cursor: 'pointer' } })">
      <template #toolbar-actions>
        <a-button v-permission="'base:supplier:add'" type="primary" @click="handleAdd"><PlusOutlined /> 新增供应商</a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'operations'">
          <a-space :size="4" @click.stop>
            <a-button v-permission="'base:supplier:edit'" type="link" size="small" @click.stop="handleEdit(record)"><EditOutlined /> 编辑</a-button>
            <a-popconfirm v-permission="'base:supplier:delete'" title="确认删除？" @confirm="handleDelete(record.id)">
              <a-button type="link" size="small" danger @click.stop><DeleteOutlined /> 删除</a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </ProTable>

    <a-modal v-model:open="visible" :title="isEdit ? '编辑供应商' : '新增供应商'" @ok="handleSubmit" width="600px">
      <a-form :model="form" :label-col="{ span: 6 }">
        <a-form-item label="名称" required><a-input v-model:value="form.name" /></a-form-item>
        <a-form-item label="联系人"><a-input v-model:value="form.contact_name" /></a-form-item>
        <a-form-item label="电话"><a-input v-model:value="form.phone" /></a-form-item>
        <a-form-item label="备注"><a-textarea v-model:value="form.remark" :rows="2" /></a-form-item>
      </a-form>
    </a-modal>

    <a-modal v-model:open="logVisible" title="变更记录" width="800px" :footer="null">
      <a-table :columns="logColumns" :data-source="logData" :pagination="false" size="small" row-key="id">
        <template #bodyCell="{ column, record: row }">
          <template v-if="column.key === 'change_type'">
            <a-tag :color="row.change_type === 'create' ? 'green' : row.change_type === 'delete' ? 'red' : 'blue'">{{ row.change_type === 'create' ? '新增' : row.change_type === 'delete' ? '删除' : '修改' }}</a-tag>
          </template>
        </template>
      </a-table>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message } from "antdv-next";
import { ref } from "vue";
import { supplierApi, changeRecordApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const tableRef = ref();
const visible = ref(false); const isEdit = ref(false);
const form = ref<Record<string, unknown>>({});

const logVisible = ref(false);
const logData = ref<Record<string, unknown>[]>([]);
const logColumns = [
  { title: "时间", dataIndex: "create_time", key: "create_time", width: 170 },
  { title: "变更类型", dataIndex: "change_type", key: "change_type", width: 80 },
  { title: "变更字段", dataIndex: "field_name", key: "field_name", width: 120 },
  { title: "旧值", dataIndex: "old_value", key: "old_value", ellipsis: true },
  { title: "新值", dataIndex: "new_value", key: "new_value", ellipsis: true },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name", width: 100 },
];

const columns: ProTableColumn[] = [
  { title: "名称", dataIndex: "name", key: "name", search: true, searchType: "input" },
  { title: "联系人", dataIndex: "contact_name", key: "contact_name" },
  { title: "电话", dataIndex: "phone", key: "phone" },
  { title: "备注", dataIndex: "remark", key: "remark", ellipsis: true },
  { title: "操作", dataIndex: "operations", key: "operations", width: 200, fixed: "right" as const },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await supplierApi.page({ page: params.current, pageSize: params.pageSize, keyword: params.keyword });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};

const showChangeLog = async (record: Record<string, unknown>) => {
  try {
    const res: any = await changeRecordApi.page({ asset_type: "supplier", asset_id: record.id, page: 1, pageSize: 200 });
    logData.value = (res.data || res).list || [];
    logVisible.value = true;
  } catch { message.error("获取变更记录失败"); }
};

const handleAdd = () => { isEdit.value = false; form.value = {}; visible.value = true; };
const handleEdit = (r: Record<string, unknown>) => { isEdit.value = true; form.value = { ...r }; visible.value = true; };
const handleDelete = async (id: string) => {
  await supplierApi.del(id);
  message.success("删除成功");
  tableRef.value?.reload();
};
const handleSubmit = async () => {
  await supplierApi.save(form.value);
  message.success(isEdit.value ? "更新成功" : "创建成功");
  visible.value = false;
  tableRef.value?.reload();
};
</script>


创建基础数据页面 (category, location, manufacturer, model, supplier)

创建业务管理页面 (failure, stocktake, transaction, allocation, request)


5 base module pages created. Now let me create the 5 biz module pages and update the routes.


基础数据 5 个页面完成。现在创建业务管理 5 个页面。


<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '故障报修' }" :custom-row="(record: any) => ({ onClick: () => showChangeLog(record), style: { cursor: 'pointer' } })">
      <template #toolbar-actions>
        <a-button v-permission="'biz:failure:add'" type="primary" @click="handleAdd"><PlusOutlined /> 新增故障</a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'status'">
          <a-tag :color="record.status === 'open' ? 'red' : record.status === 'in_progress' ? 'orange' : record.status === 'resolved' ? 'blue' : 'green'">{{ record.status === 'open' ? '待处理' : record.status === 'in_progress' ? '处理中' : record.status === 'resolved' ? '已修复' : '已关闭' }}</a-tag>
        </template>
        <template v-if="column.key === 'operations'">
          <a-space :size="4" @click.stop>
            <a-button v-permission="'biz:failure:edit'" type="link" size="small" @click.stop="handleEdit(record)"><EditOutlined /> 编辑</a-button>
            <a-popconfirm v-permission="'biz:failure:delete'" title="确认删除？" @confirm="handleDelete(record.id)">
              <a-button type="link" size="small" danger @click.stop><DeleteOutlined /> 删除</a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </ProTable>

    <a-modal v-model:open="visible" :title="isEdit ? '编辑故障' : '新增故障'" @ok="handleSubmit" width="700px">
      <a-form :model="form" :label-col="{ span: 6 }">
        <a-row :gutter="16">
          <a-col :span="12"><a-form-item label="故障名称" required><a-input v-model:value="form.failure_name" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="关联类型"><a-input v-model:value="form.target_type" placeholder="device/license/accessory" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="关联资产ID"><a-input v-model:value="form.target_id" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="故障日期" required><a-input v-model:value="form.failure_date" type="date" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="状态">
            <a-select v-model:value="form.status">
              <a-select-option value="open">待处理</a-select-option>
              <a-select-option value="in_progress">处理中</a-select-option>
              <a-select-option value="resolved">已修复</a-select-option>
              <a-select-option value="closed">已关闭</a-select-option>
            </a-select>
          </a-form-item></a-col>
          <a-col :span="12"><a-form-item label="报告人ID"><a-input v-model:value="form.reported_by" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="解决人ID"><a-input v-model:value="form.resolved_by" /></a-form-item></a-col>
          <a-col :span="24"><a-form-item label="故障描述" :label-col="{ span: 3 }"><a-textarea v-model:value="form.failure_description" :rows="3" /></a-form-item></a-col>
          <a-col :span="24"><a-form-item label="备注" :label-col="{ span: 3 }"><a-textarea v-model:value="form.notes" :rows="2" /></a-form-item></a-col>
        </a-row>
      </a-form>
    </a-modal>

    <a-modal v-model:open="logVisible" title="变更记录" width="800px" :footer="null">
      <a-table :columns="logColumns" :data-source="logData" :pagination="false" size="small" row-key="id">
        <template #bodyCell="{ column, record: row }">
          <template v-if="column.key === 'change_type'">
            <a-tag :color="row.change_type === 'create' ? 'green' : row.change_type === 'delete' ? 'red' : 'blue'">{{ row.change_type === 'create' ? '新增' : row.change_type === 'delete' ? '删除' : '修改' }}</a-tag>
          </template>
        </template>
      </a-table>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message } from "antdv-next";
import { ref } from "vue";
import { failureApi, changeRecordApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const tableRef = ref();
const visible = ref(false); const isEdit = ref(false);
const form = ref<Record<string, unknown>>({});

const logVisible = ref(false);
const logData = ref<Record<string, unknown>[]>([]);
const logColumns = [
  { title: "时间", dataIndex: "create_time", key: "create_time", width: 170 },
  { title: "变更类型", dataIndex: "change_type", key: "change_type", width: 80 },
  { title: "变更字段", dataIndex: "field_name", key: "field_name", width: 120 },
  { title: "旧值", dataIndex: "old_value", key: "old_value", ellipsis: true },
  { title: "新值", dataIndex: "new_value", key: "new_value", ellipsis: true },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name", width: 100 },
];

const columns: ProTableColumn[] = [
  { title: "故障名称", dataIndex: "failure_name", key: "failure_name", search: true, searchType: "input" },
  { title: "关联类型", dataIndex: "target_type", key: "target_type" },
  { title: "状态", dataIndex: "status", key: "status" },
  { title: "报告人", dataIndex: "reported_user_name", key: "reported_user_name" },
  { title: "解决人", dataIndex: "resolved_user_name", key: "resolved_user_name" },
  { title: "故障日期", dataIndex: "failure_date", key: "failure_date" },
  { title: "操作", dataIndex: "operations", key: "operations", width: 200, fixed: "right" as const },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await failureApi.page({ page: params.current, pageSize: params.pageSize, keyword: params.keyword });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};

const showChangeLog = async (record: Record<string, unknown>) => {
  try {
    const res: any = await changeRecordApi.page({ asset_type: "failure", asset_id: record.id, page: 1, pageSize: 200 });
    logData.value = (res.data || res).list || [];
    logVisible.value = true;
  } catch { message.error("获取变更记录失败"); }
};

const handleAdd = () => { isEdit.value = false; form.value = { status: 'open' }; visible.value = true; };
const handleEdit = (r: Record<string, unknown>) => { isEdit.value = true; form.value = { ...r }; visible.value = true; };
const handleDelete = async (id: string) => {
  await failureApi.del(id);
  message.success("删除成功");
  tableRef.value?.reload();
};
const handleSubmit = async () => {
  await failureApi.save(form.value);
  message.success(isEdit.value ? "更新成功" : "创建成功");
  visible.value = false;
  tableRef.value?.reload();
};
</script>


<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '盘点管理' }" :custom-row="(record: any) => ({ onClick: () => showChangeLog(record), style: { cursor: 'pointer' } })">
      <template #toolbar-actions>
        <a-button v-permission="'biz:stocktake:add'" type="primary" @click="handleAdd"><PlusOutlined /> 新增盘点</a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'status'">
          <a-tag :color="record.status === 'planning' ? 'blue' : record.status === 'in_progress' ? 'orange' : 'green'">{{ record.status === 'planning' ? '计划中' : record.status === 'in_progress' ? '执行中' : '已完成' }}</a-tag>
        </template>
        <template v-if="column.key === 'operations'">
          <a-space :size="4" @click.stop>
            <a-button v-permission="'biz:stocktake:edit'" type="link" size="small" @click.stop="handleEdit(record)"><EditOutlined /> 编辑</a-button>
            <a-popconfirm v-permission="'biz:stocktake:delete'" title="确认删除？" @confirm="handleDelete(record.id)">
              <a-button type="link" size="small" danger @click.stop><DeleteOutlined /> 删除</a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </ProTable>

    <a-modal v-model:open="visible" :title="isEdit ? '编辑盘点' : '新增盘点'" @ok="handleSubmit" width="600px">
      <a-form :model="form" :label-col="{ span: 6 }">
        <a-form-item label="盘点名称" required><a-input v-model:value="form.name" /></a-form-item>
        <a-form-item label="状态">
          <a-select v-model:value="form.status">
            <a-select-option value="planning">计划中</a-select-option>
            <a-select-option value="in_progress">执行中</a-select-option>
            <a-select-option value="completed">已完成</a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item label="负责人ID"><a-input v-model:value="form.manager_id" /></a-form-item>
        <a-form-item label="位置ID"><a-input v-model:value="form.location_id" /></a-form-item>
        <a-form-item label="分类ID"><a-input v-model:value="form.category_id" /></a-form-item>
        <a-form-item label="开始日期"><a-input v-model:value="form.start_date" type="date" /></a-form-item>
        <a-form-item label="结束日期"><a-input v-model:value="form.end_date" type="date" /></a-form-item>
        <a-form-item label="备注"><a-textarea v-model:value="form.note" :rows="2" /></a-form-item>
      </a-form>
    </a-modal>

    <a-modal v-model:open="logVisible" title="变更记录" width="800px" :footer="null">
      <a-table :columns="logColumns" :data-source="logData" :pagination="false" size="small" row-key="id">
        <template #bodyCell="{ column, record: row }">
          <template v-if="column.key === 'change_type'">
            <a-tag :color="row.change_type === 'create' ? 'green' : row.change_type === 'delete' ? 'red' : 'blue'">{{ row.change_type === 'create' ? '新增' : row.change_type === 'delete' ? '删除' : '修改' }}</a-tag>
          </template>
        </template>
      </a-table>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message } from "antdv-next";
import { ref } from "vue";
import { stocktakeApi, changeRecordApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const tableRef = ref();
const visible = ref(false); const isEdit = ref(false);
const form = ref<Record<string, unknown>>({});

const logVisible = ref(false);
const logData = ref<Record<string, unknown>[]>([]);
const logColumns = [
  { title: "时间", dataIndex: "create_time", key: "create_time", width: 170 },
  { title: "变更类型", dataIndex: "change_type", key: "change_type", width: 80 },
  { title: "变更字段", dataIndex: "field_name", key: "field_name", width: 120 },
  { title: "旧值", dataIndex: "old_value", key: "old_value", ellipsis: true },
  { title: "新值", dataIndex: "new_value", key: "new_value", ellipsis: true },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name", width: 100 },
];

const columns: ProTableColumn[] = [
  { title: "盘点名称", dataIndex: "name", key: "name", search: true, searchType: "input" },
  { title: "状态", dataIndex: "status", key: "status" },
  { title: "负责人", dataIndex: "manager_name", key: "manager_name" },
  { title: "开始日期", dataIndex: "start_date", key: "start_date" },
  { title: "结束日期", dataIndex: "end_date", key: "end_date" },
  { title: "操作", dataIndex: "operations", key: "operations", width: 200, fixed: "right" as const },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await stocktakeApi.page({ page: params.current, pageSize: params.pageSize, keyword: params.keyword });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};

const showChangeLog = async (record: Record<string, unknown>) => {
  try {
    const res: any = await changeRecordApi.page({ asset_type: "stocktake", asset_id: record.id, page: 1, pageSize: 200 });
    logData.value = (res.data || res).list || [];
    logVisible.value = true;
  } catch { message.error("获取变更记录失败"); }
};

const handleAdd = () => { isEdit.value = false; form.value = { status: 'planning' }; visible.value = true; };
const handleEdit = (r: Record<string, unknown>) => { isEdit.value = true; form.value = { ...r }; visible.value = true; };
const handleDelete = async (id: string) => {
  await stocktakeApi.del(id);
  message.success("删除成功");
  tableRef.value?.reload();
};
const handleSubmit = async () => {
  await stocktakeApi.save(form.value);
  message.success(isEdit.value ? "更新成功" : "创建成功");
  visible.value = false;
  tableRef.value?.reload();
};
</script>


<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '出入库记录' }">
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'action_type'">
          <a-tag :color="record.action_type === 'STOCK_IN' ? 'green' : record.action_type === 'STOCK_OUT' ? 'red' : 'blue'">{{ record.action_type === 'STOCK_IN' ? '入库' : record.action_type === 'STOCK_OUT' ? '出库' : '调整' }}</a-tag>
        </template>
      </template>
    </ProTable>
  </div>
</template>

<script setup lang="ts">
import { message } from "antdv-next";
import { transactionApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const columns: ProTableColumn[] = [
  { title: "操作类型", dataIndex: "action_type", key: "action_type" },
  { title: "数量", dataIndex: "quantity", key: "quantity" },
  { title: "剩余库存", dataIndex: "remaining_quantity", key: "remaining_quantity" },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name" },
  { title: "备注", dataIndex: "note", key: "note", ellipsis: true },
  { title: "时间", dataIndex: "create_time", key: "create_time" },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await transactionApi.page({ consumable_id: params.consumable_id || '', page: params.current, pageSize: params.pageSize });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};
</script>


<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '资产分配' }" :custom-row="(record: any) => ({ onClick: () => showChangeLog(record), style: { cursor: 'pointer' } })">
      <template #toolbar-actions>
        <a-button v-permission="'biz:allocation:add'" type="primary" @click="handleAdd"><PlusOutlined /> 新增分配</a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'status'">
          <a-tag :color="record.status === 'active' ? 'green' : record.status === 'returned' ? 'blue' : 'default'">{{ record.status === 'active' ? '使用中' : record.status === 'returned' ? '已归还' : record.status }}</a-tag>
        </template>
        <template v-if="column.key === 'operations'">
          <a-space :size="4" @click.stop>
            <a-button v-permission="'biz:allocation:edit'" type="link" size="small" @click.stop="handleEdit(record)"><EditOutlined /> 编辑</a-button>
            <a-popconfirm v-permission="'biz:allocation:delete'" title="确认删除？" @confirm="handleDelete(record.id)">
              <a-button type="link" size="small" danger @click.stop><DeleteOutlined /> 删除</a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </ProTable>

    <a-modal v-model:open="visible" :title="isEdit ? '编辑分配' : '新增分配'" @ok="handleSubmit" width="600px">
      <a-form :model="form" :label-col="{ span: 6 }">
        <a-form-item label="资产类型" required><a-input v-model:value="form.item_type" /></a-form-item>
        <a-form-item label="资产ID" required><a-input v-model:value="form.item_id" /></a-form-item>
        <a-form-item label="持有人类型"><a-input v-model:value="form.owner_type" placeholder="user/location" /></a-form-item>
        <a-form-item label="持有人ID"><a-input v-model:value="form.owner_id" /></a-form-item>
        <a-form-item label="数量"><a-input-number v-model:value="form.quantity" :min="1" style="width:100%" /></a-form-item>
        <a-form-item label="分配日期" required><a-input v-model:value="form.assign_date" type="date" /></a-form-item>
        <a-form-item label="预计归还"><a-input v-model:value="form.expected_return_date" type="date" /></a-form-item>
        <a-form-item label="备注"><a-textarea v-model:value="form.note" :rows="2" /></a-form-item>
      </a-form>
    </a-modal>

    <a-modal v-model:open="logVisible" title="变更记录" width="800px" :footer="null">
      <a-table :columns="logColumns" :data-source="logData" :pagination="false" size="small" row-key="id">
        <template #bodyCell="{ column, record: row }">
          <template v-if="column.key === 'change_type'">
            <a-tag :color="row.change_type === 'create' ? 'green' : row.change_type === 'delete' ? 'red' : 'blue'">{{ row.change_type === 'create' ? '新增' : row.change_type === 'delete' ? '删除' : '修改' }}</a-tag>
          </template>
        </template>
      </a-table>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message } from "antdv-next";
import { ref } from "vue";
import { allocationApi, changeRecordApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const tableRef = ref();
const visible = ref(false); const isEdit = ref(false);
const form = ref<Record<string, unknown>>({});

const logVisible = ref(false);
const logData = ref<Record<string, unknown>[]>([]);
const logColumns = [
  { title: "时间", dataIndex: "create_time", key: "create_time", width: 170 },
  { title: "变更类型", dataIndex: "change_type", key: "change_type", width: 80 },
  { title: "变更字段", dataIndex: "field_name", key: "field_name", width: 120 },
  { title: "旧值", dataIndex: "old_value", key: "old_value", ellipsis: true },
  { title: "新值", dataIndex: "new_value", key: "new_value", ellipsis: true },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name", width: 100 },
];

const columns: ProTableColumn[] = [
  { title: "资产类型", dataIndex: "item_type", key: "item_type" },
  { title: "持有人", dataIndex: "assignee_name", key: "assignee_name" },
  { title: "位置", dataIndex: "location_name", key: "location_name" },
  { title: "数量", dataIndex: "quantity", key: "quantity" },
  { title: "状态", dataIndex: "status", key: "status" },
  { title: "分配日期", dataIndex: "assign_date", key: "assign_date" },
  { title: "操作", dataIndex: "operations", key: "operations", width: 200, fixed: "right" as const },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await allocationApi.page({ page: params.current, pageSize: params.pageSize, keyword: params.keyword });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};

const showChangeLog = async (record: Record<string, unknown>) => {
  try {
    const res: any = await changeRecordApi.page({ asset_type: "allocation", asset_id: record.id, page: 1, pageSize: 200 });
    logData.value = (res.data || res).list || [];
    logVisible.value = true;
  } catch { message.error("获取变更记录失败"); }
};

const handleAdd = () => { isEdit.value = false; form.value = { quantity: 1, status: 'active' }; visible.value = true; };
const handleEdit = (r: Record<string, unknown>) => { isEdit.value = true; form.value = { ...r }; visible.value = true; };
const handleDelete = async (id: string) => {
  await allocationApi.del(id);
  message.success("删除成功");
  tableRef.value?.reload();
};
const handleSubmit = async () => {
  await allocationApi.save(form.value);
  message.success(isEdit.value ? "更新成功" : "创建成功");
  visible.value = false;
  tableRef.value?.reload();
};
</script>


<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '资产申请' }" :custom-row="(record: any) => ({ onClick: () => showChangeLog(record), style: { cursor: 'pointer' } })">
      <template #toolbar-actions>
        <a-button v-permission="'biz:request:add'" type="primary" @click="handleAdd"><PlusOutlined /> 新增申请</a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'status'">
          <a-tag :color="record.status === 'pending' ? 'orange' : record.status === 'approved' ? 'green' : record.status === 'rejected' ? 'red' : 'default'">{{ record.status === 'pending' ? '待审批' : record.status === 'approved' ? '已批准' : record.status === 'rejected' ? '已拒绝' : '已取消' }}</a-tag>
        </template>
        <template v-if="column.key === 'operations'">
          <a-space :size="4" @click.stop>
            <a-button v-permission="'biz:request:edit'" type="link" size="small" @click.stop="handleEdit(record)"><EditOutlined /> 编辑</a-button>
            <a-popconfirm v-permission="'biz:request:delete'" title="确认删除？" @confirm="handleDelete(record.id)">
              <a-button type="link" size="small" danger @click.stop><DeleteOutlined /> 删除</a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </ProTable>

    <a-modal v-model:open="visible" :title="isEdit ? '编辑申请' : '新增申请'" @ok="handleSubmit" width="600px">
      <a-form :model="form" :label-col="{ span: 6 }">
        <a-form-item label="申请单号"><a-input v-model:value="form.request_no" disabled /></a-form-item>
        <a-form-item label="申请人ID"><a-input v-model:value="form.user_id" /></a-form-item>
        <a-form-item label="资产类型"><a-input v-model:value="form.item_type" /></a-form-item>
        <a-form-item label="分类ID"><a-input v-model:value="form.category_id" /></a-form-item>
        <a-form-item label="数量"><a-input-number v-model:value="form.quantity" :min="1" style="width:100%" /></a-form-item>
        <a-form-item label="申请原因"><a-textarea v-model:value="form.reason" :rows="2" /></a-form-item>
        <a-form-item label="状态">
          <a-select v-model:value="form.status">
            <a-select-option value="pending">待审批</a-select-option>
            <a-select-option value="approved">已批准</a-select-option>
            <a-select-option value="rejected">已拒绝</a-select-option>
            <a-select-option value="cancelled">已取消</a-select-option>
          </a-select>
        </a-form-item>
      </a-form>
    </a-modal>

    <a-modal v-model:open="logVisible" title="变更记录" width="800px" :footer="null">
      <a-table :columns="logColumns" :data-source="logData" :pagination="false" size="small" row-key="id">
        <template #bodyCell="{ column, record: row }">
          <template v-if="column.key === 'change_type'">
            <a-tag :color="row.change_type === 'create' ? 'green' : row.change_type === 'delete' ? 'red' : 'blue'">{{ row.change_type === 'create' ? '新增' : row.change_type === 'delete' ? '删除' : '修改' }}</a-tag>
          </template>
        </template>
      </a-table>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message } from "antdv-next";
import { ref } from "vue";
import { requestApi, changeRecordApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const tableRef = ref();
const visible = ref(false); const isEdit = ref(false);
const form = ref<Record<string, unknown>>({});

const logVisible = ref(false);
const logData = ref<Record<string, unknown>[]>([]);
const logColumns = [
  { title: "时间", dataIndex: "create_time", key: "create_time", width: 170 },
  { title: "变更类型", dataIndex: "change_type", key: "change_type", width: 80 },
  { title: "变更字段", dataIndex: "field_name", key: "field_name", width: 120 },
  { title: "旧值", dataIndex: "old_value", key: "old_value", ellipsis: true },
  { title: "新值", dataIndex: "new_value", key: "new_value", ellipsis: true },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name", width: 100 },
];

const columns: ProTableColumn[] = [
  { title: "申请单号", dataIndex: "request_no", key: "request_no", search: true, searchType: "input" },
  { title: "申请人", dataIndex: "user_name", key: "user_name" },
  { title: "资产类型", dataIndex: "item_type", key: "item_type" },
  { title: "分类", dataIndex: "category_name", key: "category_name" },
  { title: "数量", dataIndex: "quantity", key: "quantity" },
  { title: "状态", dataIndex: "status", key: "status" },
  { title: "审批人", dataIndex: "approver_name", key: "approver_name" },
  { title: "操作", dataIndex: "operations", key: "operations", width: 200, fixed: "right" as const },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await requestApi.page({ page: params.current, pageSize: params.pageSize, keyword: params.keyword });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};

const showChangeLog = async (record: Record<string, unknown>) => {
  try {
    const res: any = await changeRecordApi.page({ asset_type: "asset_request", asset_id: record.id, page: 1, pageSize: 200 });
    logData.value = (res.data || res).list || [];
    logVisible.value = true;
  } catch { message.error("获取变更记录失败"); }
};

const handleAdd = () => { isEdit.value = false; form.value = { quantity: 1, status: 'pending' }; visible.value = true; };
const handleEdit = (r: Record<string, unknown>) => { isEdit.value = true; form.value = { ...r }; visible.value = true; };
const handleDelete = async (id: string) => {
  await requestApi.del(id);
  message.success("删除成功");
  tableRef.value?.reload();
};
const handleSubmit = async () => {
  await requestApi.save(form.value);
  message.success(isEdit.value ? "更新成功" : "创建成功");
  visible.value = false;
  tableRef.value?.reload();
};
</script>


File created successfully at: c:\Workspace\Project\tansci\antdv-next-admin\src\views\asset\biz\failure\index.vue (file state is current in your context — no need to Read it back)

<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '故障报修' }" :custom-row="(record: any) => ({ onClick: () => showChangeLog(record), style: { cursor: 'pointer' } })">
      <template #toolbar-actions>
        <a-button v-permission="'biz:failure:add'" type="primary" @click="handleAdd"><PlusOutlined /> 新增故障</a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'status'">
          <a-tag :color="record.status === 'open' ? 'red' : record.status === 'in_progress' ? 'orange' : record.status === 'resolved' ? 'blue' : 'green'">{{ record.status === 'open' ? '待处理' : record.status === 'in_progress' ? '处理中' : record.status === 'resolved' ? '已修复' : '已关闭' }}</a-tag>
        </template>
        <template v-if="column.key === 'operations'">
          <a-space :size="4" @click.stop>
            <a-button v-permission="'biz:failure:edit'" type="link" size="small" @click.stop="handleEdit(record)"><EditOutlined /> 编辑</a-button>
            <a-popconfirm v-permission="'biz:failure:delete'" title="确认删除？" @confirm="handleDelete(record.id)">
              <a-button type="link" size="small" danger @click.stop><DeleteOutlined /> 删除</a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </ProTable>

    <a-modal v-model:open="visible" :title="isEdit ? '编辑故障' : '新增故障'" @ok="handleSubmit" width="700px">
      <a-form :model="form" :label-col="{ span: 6 }">
        <a-row :gutter="16">
          <a-col :span="12"><a-form-item label="故障名称" required><a-input v-model:value="form.failure_name" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="关联类型"><a-input v-model:value="form.target_type" placeholder="device/license/accessory" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="关联资产ID"><a-input v-model:value="form.target_id" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="故障日期" required><a-input v-model:value="form.failure_date" type="date" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="状态">
            <a-select v-model:value="form.status">
              <a-select-option value="open">待处理</a-select-option>
              <a-select-option value="in_progress">处理中</a-select-option>
              <a-select-option value="resolved">已修复</a-select-option>
              <a-select-option value="closed">已关闭</a-select-option>
            </a-select>
          </a-form-item></a-col>
          <a-col :span="12"><a-form-item label="报告人ID"><a-input v-model:value="form.reported_by" /></a-form-item></a-col>
          <a-col :span="12"><a-form-item label="解决人ID"><a-input v-model:value="form.resolved_by" /></a-form-item></a-col>
          <a-col :span="24"><a-form-item label="故障描述" :label-col="{ span: 3 }"><a-textarea v-model:value="form.failure_description" :rows="3" /></a-form-item></a-col>
          <a-col :span="24"><a-form-item label="备注" :label-col="{ span: 3 }"><a-textarea v-model:value="form.notes" :rows="2" /></a-form-item></a-col>
        </a-row>
      </a-form>
    </a-modal>

    <a-modal v-model:open="logVisible" title="变更记录" width="800px" :footer="null">
      <a-table :columns="logColumns" :data-source="logData" :pagination="false" size="small" row-key="id">
        <template #bodyCell="{ column, record: row }">
          <template v-if="column.key === 'change_type'">
            <a-tag :color="row.change_type === 'create' ? 'green' : row.change_type === 'delete' ? 'red' : 'blue'">{{ row.change_type === 'create' ? '新增' : row.change_type === 'delete' ? '删除' : '修改' }}</a-tag>
          </template>
        </template>
      </a-table>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message } from "antdv-next";
import { ref } from "vue";
import { failureApi, changeRecordApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const tableRef = ref();
const visible = ref(false); const isEdit = ref(false);
const form = ref<Record<string, unknown>>({});

const logVisible = ref(false);
const logData = ref<Record<string, unknown>[]>([]);
const logColumns = [
  { title: "时间", dataIndex: "create_time", key: "create_time", width: 170 },
  { title: "变更类型", dataIndex: "change_type", key: "change_type", width: 80 },
  { title: "变更字段", dataIndex: "field_name", key: "field_name", width: 120 },
  { title: "旧值", dataIndex: "old_value", key: "old_value", ellipsis: true },
  { title: "新值", dataIndex: "new_value", key: "new_value", ellipsis: true },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name", width: 100 },
];

const columns: ProTableColumn[] = [
  { title: "故障名称", dataIndex: "failure_name", key: "failure_name", search: true, searchType: "input" },
  { title: "关联类型", dataIndex: "target_type", key: "target_type" },
  { title: "状态", dataIndex: "status", key: "status" },
  { title: "报告人", dataIndex: "reported_user_name", key: "reported_user_name" },
  { title: "解决人", dataIndex: "resolved_user_name", key: "resolved_user_name" },
  { title: "故障日期", dataIndex: "failure_date", key: "failure_date" },
  { title: "操作", dataIndex: "operations", key: "operations", width: 200, fixed: "right" as const },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await failureApi.page({ page: params.current, pageSize: params.pageSize, keyword: params.keyword });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};

const showChangeLog = async (record: Record<string, unknown>) => {
  try {
    const res: any = await changeRecordApi.page({ asset_type: "failure", asset_id: record.id, page: 1, pageSize: 200 });
    logData.value = (res.data || res).list || [];
    logVisible.value = true;
  } catch { message.error("获取变更记录失败"); }
};

const handleAdd = () => { isEdit.value = false; form.value = { status: 'open' }; visible.value = true; };
const handleEdit = (r: Record<string, unknown>) => { isEdit.value = true; form.value = { ...r }; visible.value = true; };
const handleDelete = async (id: string) => {
  await failureApi.del(id);
  message.success("删除成功");
  tableRef.value?.reload();
};
const handleSubmit = async () => {
  await failureApi.save(form.value);
  message.success(isEdit.value ? "更新成功" : "创建成功");
  visible.value = false;
  tableRef.value?.reload();
};
</script>


File created successfully at: c:\Workspace\Project\tansci\antdv-next-admin\src\views\asset\biz\stocktake\index.vue (file state is current in your context — no need to Read it back)

<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '盘点管理' }" :custom-row="(record: any) => ({ onClick: () => showChangeLog(record), style: { cursor: 'pointer' } })">
      <template #toolbar-actions>
        <a-button v-permission="'biz:stocktake:add'" type="primary" @click="handleAdd"><PlusOutlined /> 新增盘点</a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'status'">
          <a-tag :color="record.status === 'planning' ? 'blue' : record.status === 'in_progress' ? 'orange' : 'green'">{{ record.status === 'planning' ? '计划中' : record.status === 'in_progress' ? '执行中' : '已完成' }}</a-tag>
        </template>
        <template v-if="column.key === 'operations'">
          <a-space :size="4" @click.stop>
            <a-button v-permission="'biz:stocktake:edit'" type="link" size="small" @click.stop="handleEdit(record)"><EditOutlined /> 编辑</a-button>
            <a-popconfirm v-permission="'biz:stocktake:delete'" title="确认删除？" @confirm="handleDelete(record.id)">
              <a-button type="link" size="small" danger @click.stop><DeleteOutlined /> 删除</a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </ProTable>

    <a-modal v-model:open="visible" :title="isEdit ? '编辑盘点' : '新增盘点'" @ok="handleSubmit" width="600px">
      <a-form :model="form" :label-col="{ span: 6 }">
        <a-form-item label="盘点名称" required><a-input v-model:value="form.name" /></a-form-item>
        <a-form-item label="状态">
          <a-select v-model:value="form.status">
            <a-select-option value="planning">计划中</a-select-option>
            <a-select-option value="in_progress">执行中</a-select-option>
            <a-select-option value="completed">已完成</a-select-option>
          </a-select>
        </a-form-item>
        <a-form-item label="负责人ID"><a-input v-model:value="form.manager_id" /></a-form-item>
        <a-form-item label="位置ID"><a-input v-model:value="form.location_id" /></a-form-item>
        <a-form-item label="分类ID"><a-input v-model:value="form.category_id" /></a-form-item>
        <a-form-item label="开始日期"><a-input v-model:value="form.start_date" type="date" /></a-form-item>
        <a-form-item label="结束日期"><a-input v-model:value="form.end_date" type="date" /></a-form-item>
        <a-form-item label="备注"><a-textarea v-model:value="form.note" :rows="2" /></a-form-item>
      </a-form>
    </a-modal>

    <a-modal v-model:open="logVisible" title="变更记录" width="800px" :footer="null">
      <a-table :columns="logColumns" :data-source="logData" :pagination="false" size="small" row-key="id">
        <template #bodyCell="{ column, record: row }">
          <template v-if="column.key === 'change_type'">
            <a-tag :color="row.change_type === 'create' ? 'green' : row.change_type === 'delete' ? 'red' : 'blue'">{{ row.change_type === 'create' ? '新增' : row.change_type === 'delete' ? '删除' : '修改' }}</a-tag>
          </template>
        </template>
      </a-table>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message } from "antdv-next";
import { ref } from "vue";
import { stocktakeApi, changeRecordApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const tableRef = ref();
const visible = ref(false); const isEdit = ref(false);
const form = ref<Record<string, unknown>>({});

const logVisible = ref(false);
const logData = ref<Record<string, unknown>[]>([]);
const logColumns = [
  { title: "时间", dataIndex: "create_time", key: "create_time", width: 170 },
  { title: "变更类型", dataIndex: "change_type", key: "change_type", width: 80 },
  { title: "变更字段", dataIndex: "field_name", key: "field_name", width: 120 },
  { title: "旧值", dataIndex: "old_value", key: "old_value", ellipsis: true },
  { title: "新值", dataIndex: "new_value", key: "new_value", ellipsis: true },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name", width: 100 },
];

const columns: ProTableColumn[] = [
  { title: "盘点名称", dataIndex: "name", key: "name", search: true, searchType: "input" },
  { title: "状态", dataIndex: "status", key: "status" },
  { title: "负责人", dataIndex: "manager_name", key: "manager_name" },
  { title: "开始日期", dataIndex: "start_date", key: "start_date" },
  { title: "结束日期", dataIndex: "end_date", key: "end_date" },
  { title: "操作", dataIndex: "operations", key: "operations", width: 200, fixed: "right" as const },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await stocktakeApi.page({ page: params.current, pageSize: params.pageSize, keyword: params.keyword });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};

const showChangeLog = async (record: Record<string, unknown>) => {
  try {
    const res: any = await changeRecordApi.page({ asset_type: "stocktake", asset_id: record.id, page: 1, pageSize: 200 });
    logData.value = (res.data || res).list || [];
    logVisible.value = true;
  } catch { message.error("获取变更记录失败"); }
};

const handleAdd = () => { isEdit.value = false; form.value = { status: 'planning' }; visible.value = true; };
const handleEdit = (r: Record<string, unknown>) => { isEdit.value = true; form.value = { ...r }; visible.value = true; };
const handleDelete = async (id: string) => {
  await stocktakeApi.del(id);
  message.success("删除成功");
  tableRef.value?.reload();
};
const handleSubmit = async () => {
  await stocktakeApi.save(form.value);
  message.success(isEdit.value ? "更新成功" : "创建成功");
  visible.value = false;
  tableRef.value?.reload();
};
</script>


File created successfully at: c:\Workspace\Project\tansci\antdv-next-admin\src\views\asset\biz\transaction\index.vue (file state is current in your context — no need to Read it back)

<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '出入库记录' }">
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'action_type'">
          <a-tag :color="record.action_type === 'STOCK_IN' ? 'green' : record.action_type === 'STOCK_OUT' ? 'red' : 'blue'">{{ record.action_type === 'STOCK_IN' ? '入库' : record.action_type === 'STOCK_OUT' ? '出库' : '调整' }}</a-tag>
        </template>
      </template>
    </ProTable>
  </div>
</template>

<script setup lang="ts">
import { message } from "antdv-next";
import { transactionApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const columns: ProTableColumn[] = [
  { title: "操作类型", dataIndex: "action_type", key: "action_type" },
  { title: "数量", dataIndex: "quantity", key: "quantity" },
  { title: "剩余库存", dataIndex: "remaining_quantity", key: "remaining_quantity" },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name" },
  { title: "备注", dataIndex: "note", key: "note", ellipsis: true },
  { title: "时间", dataIndex: "create_time", key: "create_time" },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await transactionApi.page({ consumable_id: params.consumable_id || '', page: params.current, pageSize: params.pageSize });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};
</script>


File created successfully at: c:\Workspace\Project\tansci\antdv-next-admin\src\views\asset\biz\allocation\index.vue (file state is current in your context — no need to Read it back)

<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '资产分配' }" :custom-row="(record: any) => ({ onClick: () => showChangeLog(record), style: { cursor: 'pointer' } })">
      <template #toolbar-actions>
        <a-button v-permission="'biz:allocation:add'" type="primary" @click="handleAdd"><PlusOutlined /> 新增分配</a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'status'">
          <a-tag :color="record.status === 'active' ? 'green' : record.status === 'returned' ? 'blue' : 'default'">{{ record.status === 'active' ? '使用中' : record.status === 'returned' ? '已归还' : record.status }}</a-tag>
        </template>
        <template v-if="column.key === 'operations'">
          <a-space :size="4" @click.stop>
            <a-button v-permission="'biz:allocation:edit'" type="link" size="small" @click.stop="handleEdit(record)"><EditOutlined /> 编辑</a-button>
            <a-popconfirm v-permission="'biz:allocation:delete'" title="确认删除？" @confirm="handleDelete(record.id)">
              <a-button type="link" size="small" danger @click.stop><DeleteOutlined /> 删除</a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </ProTable>

    <a-modal v-model:open="visible" :title="isEdit ? '编辑分配' : '新增分配'" @ok="handleSubmit" width="600px">
      <a-form :model="form" :label-col="{ span: 6 }">
        <a-form-item label="资产类型" required><a-input v-model:value="form.item_type" /></a-form-item>
        <a-form-item label="资产ID" required><a-input v-model:value="form.item_id" /></a-form-item>
        <a-form-item label="持有人类型"><a-input v-model:value="form.owner_type" placeholder="user/location" /></a-form-item>
        <a-form-item label="持有人ID"><a-input v-model:value="form.owner_id" /></a-form-item>
        <a-form-item label="数量"><a-input-number v-model:value="form.quantity" :min="1" style="width:100%" /></a-form-item>
        <a-form-item label="分配日期" required><a-input v-model:value="form.assign_date" type="date" /></a-form-item>
        <a-form-item label="预计归还"><a-input v-model:value="form.expected_return_date" type="date" /></a-form-item>
        <a-form-item label="备注"><a-textarea v-model:value="form.note" :rows="2" /></a-form-item>
      </a-form>
    </a-modal>

    <a-modal v-model:open="logVisible" title="变更记录" width="800px" :footer="null">
      <a-table :columns="logColumns" :data-source="logData" :pagination="false" size="small" row-key="id">
        <template #bodyCell="{ column, record: row }">
          <template v-if="column.key === 'change_type'">
            <a-tag :color="row.change_type === 'create' ? 'green' : row.change_type === 'delete' ? 'red' : 'blue'">{{ row.change_type === 'create' ? '新增' : row.change_type === 'delete' ? '删除' : '修改' }}</a-tag>
          </template>
        </template>
      </a-table>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message } from "antdv-next";
import { ref } from "vue";
import { allocationApi, changeRecordApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const tableRef = ref();
const visible = ref(false); const isEdit = ref(false);
const form = ref<Record<string, unknown>>({});

const logVisible = ref(false);
const logData = ref<Record<string, unknown>[]>([]);
const logColumns = [
  { title: "时间", dataIndex: "create_time", key: "create_time", width: 170 },
  { title: "变更类型", dataIndex: "change_type", key: "change_type", width: 80 },
  { title: "变更字段", dataIndex: "field_name", key: "field_name", width: 120 },
  { title: "旧值", dataIndex: "old_value", key: "old_value", ellipsis: true },
  { title: "新值", dataIndex: "new_value", key: "new_value", ellipsis: true },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name", width: 100 },
];

const columns: ProTableColumn[] = [
  { title: "资产类型", dataIndex: "item_type", key: "item_type" },
  { title: "持有人", dataIndex: "assignee_name", key: "assignee_name" },
  { title: "位置", dataIndex: "location_name", key: "location_name" },
  { title: "数量", dataIndex: "quantity", key: "quantity" },
  { title: "状态", dataIndex: "status", key: "status" },
  { title: "分配日期", dataIndex: "assign_date", key: "assign_date" },
  { title: "操作", dataIndex: "operations", key: "operations", width: 200, fixed: "right" as const },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await allocationApi.page({ page: params.current, pageSize: params.pageSize, keyword: params.keyword });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};

const showChangeLog = async (record: Record<string, unknown>) => {
  try {
    const res: any = await changeRecordApi.page({ asset_type: "allocation", asset_id: record.id, page: 1, pageSize: 200 });
    logData.value = (res.data || res).list || [];
    logVisible.value = true;
  } catch { message.error("获取变更记录失败"); }
};

const handleAdd = () => { isEdit.value = false; form.value = { quantity: 1, status: 'active' }; visible.value = true; };
const handleEdit = (r: Record<string, unknown>) => { isEdit.value = true; form.value = { ...r }; visible.value = true; };
const handleDelete = async (id: string) => {
  await allocationApi.del(id);
  message.success("删除成功");
  tableRef.value?.reload();
};
const handleSubmit = async () => {
  await allocationApi.save(form.value);
  message.success(isEdit.value ? "更新成功" : "创建成功");
  visible.value = false;
  tableRef.value?.reload();
};
</script>


File created successfully at: c:\Workspace\Project\tansci\antdv-next-admin\src\views\asset\biz\request\index.vue (file state is current in your context — no need to Read it back)

<template>
  <div class="page-container">
    <ProTable ref="tableRef" :columns="columns" :request="loadData" :toolbar="{ title: '资产申请' }" :custom-row="(record: any) => ({ onClick: () => showChangeLog(record), style: { cursor: 'pointer' } })">
      <template #toolbar-actions>
        <a-button v-permission="'biz:request:add'" type="primary" @click="handleAdd"><PlusOutlined /> 新增申请</a-button>
      </template>
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'status'">
          <a-tag :color="record.status === 'pending' ? 'orange' : record.status === 'approved' ? 'green' : record.status === 'rejected' ? 'red' : 'default'">{{ record.status === 'pending' ? '待审批' : record.status === 'approved' ? '已批准' : record.status === 'rejected' ? '已拒绝' : '已取消' }}</a-tag>
        </template>
        <template v-if="column.key === 'operations'">
          <a-space :size="4" @click.stop>
            <a-button v-permission="'biz:request:edit'" type="link" size="small" @click.stop="handleEdit(record)"><EditOutlined /> 编辑</a-button>
            <a-popconfirm v-permission="'biz:request:delete'" title="确认删除？" @confirm="handleDelete(record.id)">
              <a-button type="link" size="small" danger @click.stop><DeleteOutlined /> 删除</a-button>
            </a-popconfirm>
          </a-space>
        </template>
      </template>
    </ProTable>

    <a-modal v-model:open="visible" :title="isEdit ? '编辑申请' : '新增申请'" @ok="handleSubmit" width="600px">
      <a-form :model="form" :label-col="{ span: 6 }">
        <a-form-item label="申请单号"><a-input v-model:value="form.request_no" disabled /></a-form-item>
        <a-form-item label="申请人ID"><a-input v-model:value="form.user_id" /></a-form-item>
        <a-form-item label="资产类型"><a-input v-model:value="form.item_type" /></a-form-item>
        <a-form-item label="分类ID"><a-input v-model:value="form.category_id" /></a-form-item>
        <a-form-item label="数量"><a-input-number v-model:value="form.quantity" :min="1" style="width:100%" /></a-form-item>
        <a-form-item label="申请原因"><a-textarea v-model:value="form.reason" :rows="2" /></a-form-item>
        <a-form-item label="状态">
          <a-select v-model:value="form.status">
            <a-select-option value="pending">待审批</a-select-option>
            <a-select-option value="approved">已批准</a-select-option>
            <a-select-option value="rejected">已拒绝</a-select-option>
            <a-select-option value="cancelled">已取消</a-select-option>
          </a-select>
        </a-form-item>
      </a-form>
    </a-modal>

    <a-modal v-model:open="logVisible" title="变更记录" width="800px" :footer="null">
      <a-table :columns="logColumns" :data-source="logData" :pagination="false" size="small" row-key="id">
        <template #bodyCell="{ column, record: row }">
          <template v-if="column.key === 'change_type'">
            <a-tag :color="row.change_type === 'create' ? 'green' : row.change_type === 'delete' ? 'red' : 'blue'">{{ row.change_type === 'create' ? '新增' : row.change_type === 'delete' ? '删除' : '修改' }}</a-tag>
          </template>
        </template>
      </a-table>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from "@antdv-next/icons";
import { message } from "antdv-next";
import { ref } from "vue";
import { requestApi, changeRecordApi } from "@/api/asset";
import ProTable from "@/components/Pro/ProTable/index.vue";
import type { ProTableColumn } from "@/types/pro";

const tableRef = ref();
const visible = ref(false); const isEdit = ref(false);
const form = ref<Record<string, unknown>>({});

const logVisible = ref(false);
const logData = ref<Record<string, unknown>[]>([]);
const logColumns = [
  { title: "时间", dataIndex: "create_time", key: "create_time", width: 170 },
  { title: "变更类型", dataIndex: "change_type", key: "change_type", width: 80 },
  { title: "变更字段", dataIndex: "field_name", key: "field_name", width: 120 },
  { title: "旧值", dataIndex: "old_value", key: "old_value", ellipsis: true },
  { title: "新值", dataIndex: "new_value", key: "new_value", ellipsis: true },
  { title: "操作人", dataIndex: "operator_name", key: "operator_name", width: 100 },
];

const columns: ProTableColumn[] = [
  { title: "申请单号", dataIndex: "request_no", key: "request_no", search: true, searchType: "input" },
  { title: "申请人", dataIndex: "user_name", key: "user_name" },
  { title: "资产类型", dataIndex: "item_type", key: "item_type" },
  { title: "分类", dataIndex: "category_name", key: "category_name" },
  { title: "数量", dataIndex: "quantity", key: "quantity" },
  { title: "状态", dataIndex: "status", key: "status" },
  { title: "审批人", dataIndex: "approver_name", key: "approver_name" },
  { title: "操作", dataIndex: "operations", key: "operations", width: 200, fixed: "right" as const },
];

const loadData = async (params: Record<string, unknown>) => {
  try {
    const res: any = await requestApi.page({ page: params.current, pageSize: params.pageSize, keyword: params.keyword });
    const pageData = res.data || res;
    return { data: pageData.list || [], total: pageData.total || 0, success: true };
  } catch { return { data: [], total: 0, success: false }; }
};

const showChangeLog = async (record: Record<string, unknown>) => {
  try {
    const res: any = await changeRecordApi.page({ asset_type: "asset_request", asset_id: record.id, page: 1, pageSize: 200 });
    logData.value = (res.data || res).list || [];
    logVisible.value = true;
  } catch { message.error("获取变更记录失败"); }
};

const handleAdd = () => { isEdit.value = false; form.value = { quantity: 1, status: 'pending' }; visible.value = true; };
const handleEdit = (r: Record<string, unknown>) => { isEdit.value = true; form.value = { ...r }; visible.value = true; };
const handleDelete = async (id: string) => {
  await requestApi.del(id);
  message.success("删除成功");
  tableRef.value?.reload();
};
const handleSubmit = async () => {
  await requestApi.save(form.value);
  message.success(isEdit.value ? "更新成功" : "创建成功");
  visible.value = false;
  tableRef.value?.reload();
};
</script>


All 10 pages created. Now I need to add the routes to routes.ts. I need to add /base and /biz route groups after the /asset group.

Let me also update the en-US.ts i18n file to add the English translations for the menu items (zh-CN already has them).

But first, let me add the routes. I need to add after line 248 (end of /asset route group), but before /examples.

Let me also check the en-US.ts to see if the base/biz translations exist.


10 个页面全部创建。现在更新路由和英文国际化。


Edit

    ],
  },
  {
    path: "/base",
    name: "Base",
    redirect: "/base/category",
    component: () => import("@/components/Layout/AdminLayout.vue"),
    meta: {
      title: "menu.base",
      icon: "DatabaseOutlined",
      requiresAuth: true,
      order: 4,
    },
    children: [
      {
        path: "category",
        name: "BaseCategory",
        component: () => import("@/views/asset/base/category/index.vue"),
        meta: { title: "menu.baseCategory", icon: "TagOutlined", requiresAuth: true },
      },
      {
        path: "location",
        name: "BaseLocation",
        component: () => import("@/views/asset/base/location/index.vue"),
        meta: { title: "menu.baseLocation", icon: "EnvironmentOutlined", requiresAuth: true },
      },
      {
        path: "manufacturer",
        name: "BaseManufacturer",
        component: () => import("@/views/asset/base/manufacturer/index.vue"),
        meta: { title: "menu.baseManufacturer", icon: "BuildOutlined", requiresAuth: true },
      },
      {
        path: "model",
        name: "BaseModel",
        component: () => import("@/views/asset/base/model/index.vue"),
        meta: { title: "menu.baseModel", icon: "BarcodeOutlined", requiresAuth: true },
      },
      {
        path: "supplier",
        name: "BaseSupplier",
        component: () => import("@/views/asset/base/supplier/index.vue"),
        meta: { title: "menu.baseSupplier", icon: "ShopOutlined", requiresAuth: true },
      },
    ],
  },
  {
    path: "/biz",
    name: "Biz",
    redirect: "/biz/failure",
    component: () => import("@/components/Layout/AdminLayout.vue"),
    meta: {
      title: "menu.biz",
      icon: "ProfileOutlined",
      requiresAuth: true,
      order: 5,
    },
    children: [
      {
        path: "failure",
        name: "BizFailure",
        component: () => import("@/views/asset/biz/failure/index.vue"),
        meta: { title: "menu.bizFailure", icon: "WarningOutlined", requiresAuth: true },
      },
      {
        path: "stocktake",
        name: "BizStocktake",
        component: () => import("@/views/asset/biz/stocktake/index.vue"),
        meta: { title: "menu.bizStocktake", icon: "CheckSquareOutlined", requiresAuth: true },
      },
      {
        path: "transaction",
        name: "BizTransaction",
        component: () => import("@/views/asset/biz/transaction/index.vue"),
        meta: { title: "menu.bizTransaction", icon: "SwapOutlined", requiresAuth: true },
      },
      {
        path: "allocation",
        name: "BizAllocation",
        component: () => import("@/views/asset/biz/allocation/index.vue"),
        meta: { title: "menu.bizAllocation", icon: "SendOutlined", requiresAuth: true },
      },
      {
        path: "request",
        name: "BizRequest",
        component: () => import("@/views/asset/biz/request/index.vue"),
        meta: { title: "menu.bizRequest", icon: "FileAddOutlined", requiresAuth: true },
      },
    ],
  },
  {
    path: "/examples",


The file c:\Workspace\Project\tansci\antdv-next-admin\src\router\routes.ts has been updated successfully. (file state is current in your context — no need to Read it back)

    ],
  },
  {
    path: "/base",
    name: "Base",
    redirect: "/base/category",
    component: () => import("@/components/Layout/AdminLayout.vue"),
    meta: {
      title: "menu.base",
      icon: "DatabaseOutlined",
      requiresAuth: true,
      order: 4,
    },
    children: [
      {
        path: "category",
        name: "BaseCategory",
        component: () => import("@/views/asset/base/category/index.vue"),
        meta: { title: "menu.baseCategory", icon: "TagOutlined", requiresAuth: true },
      },
      {
        path: "location",
        name: "BaseLocation",
        component: () => import("@/views/asset/base/location/index.vue"),
        meta: { title: "menu.baseLocation", icon: "EnvironmentOutlined", requiresAuth: true },
      },
      {
        path: "manufacturer",
        name: "BaseManufacturer",
        component: () => import("@/views/asset/base/manufacturer/index.vue"),
        meta: { title: "menu.baseManufacturer", icon: "BuildOutlined", requiresAuth: true },
      },
      {
        path: "model",
        name: "BaseModel",
        component: () => import("@/views/asset/base/model/index.vue"),
        meta: { title: "menu.baseModel", icon: "BarcodeOutlined", requiresAuth: true },
      },
      {
        path: "supplier",
        name: "BaseSupplier",
        component: () => import("@/views/asset/base/supplier/index.vue"),
        meta: { title: "menu.baseSupplier", icon: "ShopOutlined", requiresAuth: true },
      },
    ],
  },
  {
    path: "/biz",
    name: "Biz",
    redirect: "/biz/failure",
    component: () => import("@/components/Layout/AdminLayout.vue"),
    meta: {
      title: "menu.biz",
      icon: "ProfileOutlined",
      requiresAuth: true,
      order: 5,
    },
    children: [
      {
        path: "failure",
        name: "BizFailure",
        component: () => import("@/views/asset/biz/failure/index.vue"),
        meta: { title: "menu.bizFailure", icon: "WarningOutlined", requiresAuth: true },
      },
      {
        path: "stocktake",
        name: "BizStocktake",
        component: () => import("@/views/asset/biz/stocktake/index.vue"),
        meta: { title: "menu.bizStocktake", icon: "CheckSquareOutlined", requiresAuth: true },
      },
      {
        path: "transaction",
        name: "BizTransaction",
        component: () => import("@/views/asset/biz/transaction/index.vue"),
        meta: { title: "menu.bizTransaction", icon: "SwapOutlined", requiresAuth: true },
      },
      {
        path: "allocation",
        name: "BizAllocation",
        component: () => import("@/views/asset/biz/allocation/index.vue"),
        meta: { title: "menu.bizAllocation", icon: "SendOutlined", requiresAuth: true },
      },
      {
        path: "request",
        name: "BizRequest",
        component: () => import("@/views/asset/biz/request/index.vue"),
        meta: { title: "menu.bizRequest", icon: "FileAddOutlined", requiresAuth: true },
      },
    ],
  },
  {
    path: "/examples",

+    component: () => import("@/components/Layout/AdminLayout.vue"),

+        component: () => import("@/views/asset/base/category/index.vue"),

+        meta: { title: "menu.baseCategory", icon: "TagOutlined", requiresAuth: true },

+        component: () => import("@/views/asset/base/location/index.vue"),

+        meta: { title: "menu.baseLocation", icon: "EnvironmentOutlined", requiresAuth: true },

+        component: () => import("@/views/asset/base/manufacturer/index.vue"),

+        meta: { title: "menu.baseManufacturer", icon: "BuildOutlined", requiresAuth: true },

+        component: () => import("@/views/asset/base/model/index.vue"),

+        meta: { title: "menu.baseModel", icon: "BarcodeOutlined", requiresAuth: true },

+        component: () => import("@/views/asset/base/supplier/index.vue"),

+        meta: { title: "menu.baseSupplier", icon: "ShopOutlined", requiresAuth: true },

+        component: () => import("@/views/asset/biz/failure/index.vue"),

+        meta: { title: "menu.bizFailure", icon: "WarningOutlined", requiresAuth: true },

+        component: () => import("@/views/asset/biz/stocktake/index.vue"),

+        meta: { title: "menu.bizStocktake", icon: "CheckSquareOutlined", requiresAuth: true },

+        component: () => import("@/views/asset/biz/transaction/index.vue"),

+        meta: { title: "menu.bizTransaction", icon: "SwapOutlined", requiresAuth: true },

+        component: () => import("@/views/asset/biz/allocation/index.vue"),

+        meta: { title: "menu.bizAllocation", icon: "SendOutlined", requiresAuth: true },

+        component: () => import("@/views/asset/biz/request/index.vue"),

+        meta: { title: "menu.bizRequest", icon: "FileAddOutlined", requiresAuth: true },


Routes added. Now let me check and update the English i18n file too.


路由已添加。现在更新英文国际化。


104:    baseCategory: "Category",
105:    baseLocation: "Location",
106:    baseManufacturer: "Manufacturer",
107:    baseModel: "Model",
108:    baseSupplier: "Supplier",
110:    bizFailure: "Failure",
111:    bizStocktake: "Stocktake",
112:    bizTransaction: "Transaction",
113:    bizAllocation: "Allocation",
114:    bizRequest: "Request",


The English i18n already has the translations too. Everything is in place.

Now let me check if the frontend is still running and verify the TypeScript compilation works.


英文 i18n 也已有。让我验证 TypeScript 编译是否通过。


Bash

cd /c/Workspace/Project/tansci/antdv-next-admin && npx vue-tsc --noEmit 2>&1 | head -30

Run TypeScript type check