更新
This commit is contained in:
@@ -87,3 +87,42 @@ export function editObj(obj: any) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载导入模板
|
||||||
|
*/
|
||||||
|
export function downloadTemplate() {
|
||||||
|
return request({
|
||||||
|
url: '/purchase/purchasingcategory/import/template',
|
||||||
|
method: 'get',
|
||||||
|
responseType: 'blob'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入数据
|
||||||
|
* @param file 文件对象
|
||||||
|
*/
|
||||||
|
export function importData(file: File) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', file);
|
||||||
|
return request({
|
||||||
|
url: '/purchase/purchasingcategory/import',
|
||||||
|
method: 'post',
|
||||||
|
data: formData,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出数据
|
||||||
|
*/
|
||||||
|
export function exportData() {
|
||||||
|
return request({
|
||||||
|
url: '/purchase/purchasingcategory/export',
|
||||||
|
method: 'get',
|
||||||
|
responseType: 'blob'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export function usePurchaseRules() {
|
|||||||
const thresholds: Record<string, number> = {
|
const thresholds: Record<string, number> = {
|
||||||
deptPurchase: 50000,
|
deptPurchase: 50000,
|
||||||
feasibility: 300000,
|
feasibility: 300000,
|
||||||
publicSelect: 400000,
|
publicSelect: 300000,
|
||||||
govPurchase: 1000000
|
govPurchase: 1000000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
|
<el-alert type="warning" :closable="false">既定规则请不要随意修改,否则会出错</el-alert>
|
||||||
<el-table
|
<el-table
|
||||||
:data="state.dataList"
|
:data="state.dataList"
|
||||||
v-loading="state.loading"
|
v-loading="state.loading"
|
||||||
|
|||||||
@@ -17,6 +17,31 @@
|
|||||||
@click="formDialogRef.openDialog('add')">
|
@click="formDialogRef.openDialog('add')">
|
||||||
新增
|
新增
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="Download"
|
||||||
|
type="success"
|
||||||
|
v-auth="'purchase_purchasingcategory_import'"
|
||||||
|
@click="handleDownloadTemplate">
|
||||||
|
下载模板
|
||||||
|
</el-button>
|
||||||
|
<el-upload
|
||||||
|
ref="uploadRef"
|
||||||
|
:show-file-list="false"
|
||||||
|
:before-upload="handleBeforeUpload"
|
||||||
|
:http-request="handleImport"
|
||||||
|
accept=".xlsx,.xls"
|
||||||
|
v-auth="'purchase_purchasingcategory_import'">
|
||||||
|
<el-button icon="Upload" type="warning" :loading="importLoading">
|
||||||
|
导入
|
||||||
|
</el-button>
|
||||||
|
</el-upload>
|
||||||
|
<el-button
|
||||||
|
icon="Download"
|
||||||
|
type="info"
|
||||||
|
v-auth="'purchase_purchasingcategory_export'"
|
||||||
|
@click="handleExport">
|
||||||
|
导出
|
||||||
|
</el-button>
|
||||||
<right-toolbar class="ml10" />
|
<right-toolbar class="ml10" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -93,20 +118,17 @@
|
|||||||
<script setup lang="ts" name="PurchasingCategory">
|
<script setup lang="ts" name="PurchasingCategory">
|
||||||
import { ref, reactive, defineAsyncComponent } from 'vue'
|
import { ref, reactive, defineAsyncComponent } from 'vue'
|
||||||
import { BasicTableProps, useTable } from "/@/hooks/table";
|
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||||
import { getTreeRoots, getTreeChildren, delObj } from "/@/api/purchase/purchasingcategory";
|
import { getTreeRoots, getTreeChildren, delObj, downloadTemplate, importData, exportData } from "/@/api/purchase/purchasingcategory";
|
||||||
import { useMessage, useMessageBox } from "/@/hooks/message";
|
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||||
import { List, Document, DocumentCopy, EditPen } from '@element-plus/icons-vue'
|
import { List, Document, DocumentCopy, EditPen } from '@element-plus/icons-vue'
|
||||||
|
|
||||||
// 引入组件
|
|
||||||
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
|
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
|
||||||
|
|
||||||
// 定义变量内容
|
|
||||||
const tableRef = ref()
|
const tableRef = ref()
|
||||||
const formDialogRef = ref()
|
const formDialogRef = ref()
|
||||||
|
const uploadRef = ref()
|
||||||
|
const importLoading = ref(false)
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询树根节点(懒加载:首屏只加载根节点)
|
|
||||||
*/
|
|
||||||
const queryTreeRoots = () => {
|
const queryTreeRoots = () => {
|
||||||
return getTreeRoots().then((res: any) => {
|
return getTreeRoots().then((res: any) => {
|
||||||
const list = res?.data ?? [];
|
const list = res?.data ?? [];
|
||||||
@@ -114,12 +136,6 @@ const queryTreeRoots = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 懒加载子节点:展开某行时按需请求子节点
|
|
||||||
* @param row 当前行
|
|
||||||
* @param treeNode 树节点信息
|
|
||||||
* @param resolve 回调,传入子节点数组
|
|
||||||
*/
|
|
||||||
const loadTreeNode = (row: any, treeNode: any, resolve: (data: any[]) => void) => {
|
const loadTreeNode = (row: any, treeNode: any, resolve: (data: any[]) => void) => {
|
||||||
const parentCode = row?.code;
|
const parentCode = row?.code;
|
||||||
if (!parentCode) {
|
if (!parentCode) {
|
||||||
@@ -134,33 +150,18 @@ const loadTreeNode = (row: any, treeNode: any, resolve: (data: any[]) => void) =
|
|||||||
.catch(() => resolve([]));
|
.catch(() => resolve([]));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 定义响应式表格数据
|
|
||||||
*/
|
|
||||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||||
pageList: queryTreeRoots,
|
pageList: queryTreeRoots,
|
||||||
queryForm: {},
|
queryForm: {},
|
||||||
isPage: false, // 树形表格不分页
|
isPage: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用 useTable 定义表格相关操作
|
|
||||||
*/
|
|
||||||
const { getDataList, tableStyle } = useTable(state);
|
const { getDataList, tableStyle } = useTable(state);
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算行序号(考虑树形结构)
|
|
||||||
*/
|
|
||||||
const getRowIndex = (index: number, row: any) => {
|
const getRowIndex = (index: number, row: any) => {
|
||||||
// 对于树形表格,序号需要根据实际显示的行来计算
|
|
||||||
// 这里简化处理,直接返回 index + 1
|
|
||||||
return index + 1;
|
return index + 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除当前行
|
|
||||||
* @param row - 当前行数据
|
|
||||||
*/
|
|
||||||
const handleDelete = async (row: any) => {
|
const handleDelete = async (row: any) => {
|
||||||
try {
|
try {
|
||||||
await useMessageBox().confirm('确定要删除该记录吗?', '提示', {
|
await useMessageBox().confirm('确定要删除该记录吗?', '提示', {
|
||||||
@@ -173,7 +174,6 @@ const handleDelete = async (row: any) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 使用 id 或 code 作为删除参数(根据后端接口决定)
|
|
||||||
const deleteId = row.id || row.code;
|
const deleteId = row.id || row.code;
|
||||||
await delObj(deleteId);
|
await delObj(deleteId);
|
||||||
useMessage().success('删除成功');
|
useMessage().success('删除成功');
|
||||||
@@ -182,6 +182,57 @@ const handleDelete = async (row: any) => {
|
|||||||
useMessage().error(err.msg || '删除失败');
|
useMessage().error(err.msg || '删除失败');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDownloadTemplate = async () => {
|
||||||
|
try {
|
||||||
|
const res: any = await downloadTemplate();
|
||||||
|
downloadFile(res, '采购品目导入模板.xlsx');
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '下载模板失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBeforeUpload = (file: File) => {
|
||||||
|
const isExcel = file.name.endsWith('.xlsx') || file.name.endsWith('.xls');
|
||||||
|
if (!isExcel) {
|
||||||
|
useMessage().error('请上传Excel文件');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleImport = async (options: any) => {
|
||||||
|
importLoading.value = true;
|
||||||
|
try {
|
||||||
|
const res: any = await importData(options.file);
|
||||||
|
useMessage().success(res.msg || '导入成功');
|
||||||
|
getDataList();
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '导入失败');
|
||||||
|
} finally {
|
||||||
|
importLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleExport = async () => {
|
||||||
|
try {
|
||||||
|
const res: any = await exportData();
|
||||||
|
downloadFile(res, '采购品目数据.xlsx');
|
||||||
|
} catch (err: any) {
|
||||||
|
useMessage().error(err.msg || '导出失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const downloadFile = (blob: Blob, fileName: string) => {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = fileName;
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -188,12 +188,6 @@
|
|||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<!-- <el-col :span="8" class="mb12" v-if="showAutoInviteSelect && dataForm.hasSupplier === '1'">
|
|
||||||
<el-form-item label="推荐供应商" prop="suppliers" class="mb16">
|
|
||||||
<el-input v-model="dataForm.suppliers" placeholder="请输入三家供应商名称,用逗号分隔" clearable />
|
|
||||||
<div class="template-note mt5"><el-text type="info" size="small">请输入三家供应商名称,用逗号分隔</el-text></div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col> -->
|
|
||||||
<el-col :span="8" class="mb12" v-if="showAutoInviteSelect && dataForm.hasSupplier === '1'">
|
<el-col :span="8" class="mb12" v-if="showAutoInviteSelect && dataForm.hasSupplier === '1'">
|
||||||
<el-form-item label="服务商城项目需求模板(邀请比选)" prop="serviceInviteSelect" required>
|
<el-form-item label="服务商城项目需求模板(邀请比选)" prop="serviceInviteSelect" required>
|
||||||
<upload-file v-model="dataForm.serviceInviteSelect" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.serviceInviteSelect }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('serviceInviteSelect')" />
|
<upload-file v-model="dataForm.serviceInviteSelect" :limit="1" :file-type="['doc', 'docx', 'pdf']" :data="{ fileType: FILE_TYPE_MAP.serviceInviteSelect }" upload-file-url="/purchase/purchasingfiles/upload" :disabled="flowFieldDisabled('serviceInviteSelect')" />
|
||||||
@@ -226,8 +220,8 @@
|
|||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8" class="mb12" >
|
<el-col :span="8" class="mb12" >
|
||||||
<el-form-item label="采购方式" prop="purchaseType" :required="!isDeptPurchase">
|
<el-form-item label="采购方式" prop="purchaseType">
|
||||||
<el-select v-model="dataForm.purchaseType" placeholder="请选择采购方式" clearable :disabled="(isFlowEmbed && isPurchaseCenter) ? false : (isAutoSelectPurchaseTypeUnion || flowFieldDisabled('purchaseType') || !isPurchaseCenter)" style="width: 100%">
|
<el-select v-model="dataForm.purchaseType" placeholder="请选择采购方式" clearable :disabled="(isFlowEmbed && isPurchaseCenter) ? false : (isAutoSelectPurchaseTypeUnion || flowFieldDisabled('purchaseType') || !isPurchaseCenter)" style="width: 100%">
|
||||||
<el-option v-for="item in purchaseTypeUnionList" :key="item.value" :label="item.label" :value="item.value" />
|
<el-option v-for="item in purchaseTypeUnionList" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
@@ -1150,11 +1144,16 @@ const dataRules = reactive({
|
|||||||
trigger: 'change',
|
trigger: 'change',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
purchaseType: [
|
purchaseType: [
|
||||||
{
|
{
|
||||||
validator: (_rule: any, value: string, callback: (e?: Error) => void) => {
|
validator: (_rule: any, value: string, callback: (e?: Error) => void) => {
|
||||||
// 部门自行采购且采购途径为“委托采购中心采购”并且为申请阶段:此处不校验采购方式
|
// 学校统一采购:申请阶段不要求采购方式,由审批环节采购中心补充
|
||||||
if (isDeptPurchase.value && isEntrustCenterChannel.value && !isFlowEmbed.value) {
|
if (!isDeptPurchase.value) {
|
||||||
|
callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 部门自行采购且采购途径为"委托采购中心采购"并且为申请阶段:此处不校验采购方式
|
||||||
|
if (isEntrustCenterChannel.value && !isFlowEmbed.value) {
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user