From 6d0552908bc5c17ab9af74120819ec6d3e5df674 Mon Sep 17 00:00:00 2001
From: licp <lichunping@guanfang.com.cn>
Date: 星期五, 27 十二月 2024 13:27:22 +0800
Subject: [PATCH] 搬迁cnas6.6

---
 src/components/do/a6.service-and-supply-purchase/components/AddProject.vue |   96 ++
 src/components/do/a6.service-and-supply-purchase/components/Edit.vue       |  264 +++++
 src/components/do/a6.service-and-supply-purchase/contents.vue              |  297 ++++++
 src/components/view/a6.service-and-supply-purchase.vue                     |  178 +++
 src/components/caorui/6-6/ConsumableOverview/index.vue                     |  136 ++
 src/components/caorui/6-6/components/Edit.vue                              |  237 +++++
 src/components/do/a6.service-and-supply-purchase/Store.vue                 |  516 ++++++++++
 src/components/do/a6.service-and-supply-purchase/ConsumableOverview.vue    |  126 ++
 src/assets/api/controller.js                                               |   23 
 src/components/do/a6.service-and-supply-purchase/ConsumableList.vue        |  287 ++++++
 src/components/view/a6-supplier-manage.vue                                 |  154 +++
 src/components/caorui/6-6/ConsumableOverview/components/CardPanel.vue      |   74 +
 src/main.js                                                                |    4 
 src/components/do/a6.service-and-supply-purchase/ConsumableProject.vue     |  175 +++
 src/components/caorui/6-6/QualifiedSuppliers/index.vue                     |  220 ++++
 15 files changed, 2,785 insertions(+), 2 deletions(-)

diff --git a/src/assets/api/controller.js b/src/assets/api/controller.js
index 8f53c03..842a970 100644
--- a/src/assets/api/controller.js
+++ b/src/assets/api/controller.js
@@ -73,6 +73,8 @@
     personPostAuthorizationRecord,
     deviceCheck,
     personCommunicationAbility,
+    procurementSuppliesContents,
+    procurementSuppliesStore,
   }
 }
 
@@ -977,3 +979,24 @@
 const personCommunicationAbility = {
   exportPersonCommunicationAbility:'/personCommunicationAbility/exportPersonCommunicationAbility',//瀵煎嚭
 }
+
+const procurementSuppliesContents = {
+  directoryListing: "/procurementSuppliesContents/directoryListing", // 閲囪喘鐗╄祫鐩綍鍒楄〃
+  selectById: "/procurementSuppliesContents/selectProcurementSuppliesContentById", // 閲囪喘鐗╄祫鐩綍璇︽儏
+  add: "/procurementSuppliesContents/addProcurementSuppliesContents", // 閲囪喘鐗╄祫鐩綍鏂板
+  update: "/procurementSuppliesContents/updateProcurementSuppliesContents", // 閲囪喘鐗╄祫鐩綍淇敼
+  deleteById: "/procurementSuppliesContents/deleteProcurementSuppliesContentById", // 閲囪喘鐗╄祫鐩綍鍒犻櫎
+  getUserList: "/procurementSuppliesContents/getUserList", // 閲囪喘鐗╄祫鐩綍鑾峰彇鐢ㄦ埛鍒楄〃
+  getNodeNames: "/procurementSuppliesContents/getNodeNames", // 閲囪喘鐗╄祫鐩綍鑾峰彇鑺傜偣鍚嶇О
+  selectSuppliersDirectoryContentsById:'/suppliersDirectoryContents/selectSuppliersDirectoryContentsById',//渚涘簲鍟嗙洰褰曡鎯�
+}
+
+const procurementSuppliesStore = {
+  storeList: '/procurementSuppliesStore/storeList', // 鑰楁潗鍏ュ簱鍒楄〃
+  addStore: '/procurementSuppliesStore/addStore', // 鑰楁潗鍏ュ簱鏂板
+  deleteStore: '/procurementSuppliesStore/deleteStore', // 鑰楁潗鍏ュ簱鍒犻櫎
+  updateStore: '/procurementSuppliesStore/updateStore', // 鑰楁潗鍏ュ簱淇敼
+  selectStoreById: '/procurementSuppliesStore/selectStoreById', // 鏍规嵁id鏌ヨ鑰楁潗鍏ュ簱
+  exportExcel: '/procurementSuppliesStore/exportExcel', // 鑰楁潗鍏ュ簱瀵煎嚭
+  updateStore: '/procurementSuppliesStore/updateStore', // 鑰楁潗鍏ュ簱淇敼
+}
diff --git a/src/components/caorui/6-6/ConsumableOverview/components/CardPanel.vue b/src/components/caorui/6-6/ConsumableOverview/components/CardPanel.vue
new file mode 100644
index 0000000..ec4034f
--- /dev/null
+++ b/src/components/caorui/6-6/ConsumableOverview/components/CardPanel.vue
@@ -0,0 +1,74 @@
+<template>
+    <div class="card-container" @click="handleCard">
+        <div class="card-panel" :class="[isActive == index ? 'isActive' : '']">
+            <el-image
+                style="width: 80%; height: 140px"
+                :src="javaApi + '/img/' + data.logo"
+                fit="fill"
+            />
+        </div>
+        <div class="title">
+            {{ data.supplierRef }}
+        </div>
+    </div>
+</template>
+<script>
+
+export default {
+    props: {
+        data: {
+            type: Object,
+            default: () => {}
+        },
+        index: {
+            type: Number,
+            default: -1
+        },
+        isActive: {
+            type: Number,
+            default: -1
+        }
+    },
+    data(){
+        return {
+
+        }
+    },
+    mounted() {
+      // console.log(1111,this.data)
+    },
+    methods: {
+        handleCard() {
+            this.$emit('handleCard', this.data, this.index)
+        }
+    }
+}
+</script>
+<style scoped>
+.card-container  {
+    margin: 10px 10px 10px 0;
+    text-align: center;
+}
+.card-panel {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 90%;
+    height: 180px;
+    box-shadow: 0px 0px 20px 0px #0000001A;
+    cursor: pointer;
+    border-radius: 5px;
+    border: 1px solid transparent;
+}
+.card-panel:hover {
+    border: 1px solid #409EFF;
+    background: #1D56C50D;
+}
+.isActive {
+    border: 1px solid #409EFF;
+    background: #1D56C50D;
+}
+.title {
+    margin-top: 15px;
+}
+</style>
diff --git a/src/components/caorui/6-6/ConsumableOverview/index.vue b/src/components/caorui/6-6/ConsumableOverview/index.vue
new file mode 100644
index 0000000..b25302c
--- /dev/null
+++ b/src/components/caorui/6-6/ConsumableOverview/index.vue
@@ -0,0 +1,136 @@
+<template>
+    <div>
+        <el-row class="card-box">
+            <el-col :span="4" v-for="(item, index) in cardList" :key="index">
+                <CardPanel
+                    :isActive="isActive"
+                    :data="item"
+                    :index="index"
+                    @handleCard="handleCard"
+                />
+            </el-col>
+        </el-row>
+        <TableCard title="渚涘簲鍟嗕俊鎭�" :showForm="false" style="margin-top: 5px">
+            <template v-slot:table>
+                <ZTTable
+                    style="margin-top: 18px; padding: 0 15px;"
+                    :height="'40vh'"
+                    :column="columns"
+                    :table-data="tableData"
+                >
+                    <div slot="action" slot-scope="scope">
+                        <el-button type="text" @click="showDialog(scope)">鏌ョ湅</el-button>
+                    </div>
+                </ZTTable>
+            </template>
+        </TableCard>
+        <Edit ref="editRef" @submit="getTableData" type="璇︽儏" />
+    </div>
+</template>
+<script>
+import CardPanel from './components/CardPanel.vue';
+import TableCard from '@/components/caorui/TableCard/index.vue';
+import ZTTable from '@/components/caorui/ZTTable/index.vue';
+import Edit from "../components/Edit.vue"
+import { selectSupplierManagementPage } from "@/assets/api/api";
+import axios from 'axios';
+
+export default {
+    components: {CardPanel, TableCard, ZTTable, Edit},
+    props: {
+        contentsId: {
+            type: Number,
+            default: 0
+        }
+    },
+    data() {
+        return {
+            columns: [
+                {
+                    label: "渚涘簲鍟嗙紪鍙�",
+                    prop: "supplierRef"
+                },
+                {
+                    label: "渚涘簲鍟嗗悕绉�",
+                    prop: "supplierRef"
+                },
+                {
+                    label: "鍦板潃",
+                    prop: "supplierName"
+                },
+                {
+                    label: "鑱旂郴浜�",
+                    prop: "contacts"
+                },
+                {
+                    label: "鑱旂郴鐢佃瘽",
+                    prop: "phone"
+                },
+                {
+                    label: "浼犵湡",
+                    prop: "fax"
+                },
+                {
+                    label: "缃戝潃",
+                    prop: "website"
+                },
+                {
+                    label: "閭",
+                    prop: "email"
+                },
+                {
+                    label: "涓婃鏇存柊鏃堕棿",
+                    prop: "updateTime"
+                },
+                {
+                    fixed: "right",
+                    dataType: "slot",
+                    slot: "action",
+                    label: "鎿嶄綔"
+                }
+            ],
+            cardList: [],
+            tableData: [],
+            isActive: -1
+        }
+    },
+    watch: {
+        contentsId(newVal) {
+            if (newVal !== 0) {
+                this.getTableData();
+            }
+        },
+    },
+    mounted() {
+        this.getTableData(this.contentsId)
+    },
+    methods: {
+         // 鑾峰彇琛ㄦ牸鏁版嵁
+         async getTableData() {
+            const {code, data } = await axios({
+                method: 'get',
+                url: `${selectSupplierManagementPage}/${this.contentsId}`,
+            })
+            if(code == 200) {
+                this.cardList = data;
+            }
+        },
+        handleCard(data, index) {
+            this.isActive = index
+            this.tableData = [data]
+        },
+        showDialog(row) {
+            this.$refs.editRef.openDialog(row)
+        }
+    }
+}
+</script>
+<style scoped>
+.card-box {
+    width: 100%;
+    padding-left: 5px;
+    padding-right: 5px;
+    height: 30vh;
+    overflow-y: auto;
+}
+</style>
diff --git a/src/components/caorui/6-6/QualifiedSuppliers/index.vue b/src/components/caorui/6-6/QualifiedSuppliers/index.vue
new file mode 100644
index 0000000..524d8d2
--- /dev/null
+++ b/src/components/caorui/6-6/QualifiedSuppliers/index.vue
@@ -0,0 +1,220 @@
+<template>
+    <div>
+        <TableCard :showTitle="false">
+            <template slot="form">
+                <div class="action-box">
+                    <div></div>
+                    <div class="flex">
+                        <el-button :disabled="contentsId == 0" icon="el-icon-plus" type="primary" @click="showDialog()">
+                            鏂板缓
+                        </el-button>
+                        <el-button icon="el-icon-upload2" @click="exportExcel">
+                            瀵煎嚭Excel
+                        </el-button>
+                    </div>
+                </div>
+            </template>
+            <template v-slot:table>
+                <ZTTable
+                    :column="columns"
+                    :height="'70vh'"
+                    :isSelection="true"
+                    :table-data="tableData"
+                    style="margin-top: 18px; padding: 0 15px;"
+                >
+                    <div slot="action" slot-scope="scope">
+                        <el-button type="text" @click="showDialog(scope)">缂栬緫</el-button>
+                        <el-button type="text" @click="delRow(scope)">
+                            <span style="color: #F56C6C">鍒犻櫎</span>
+                        </el-button>
+                    </div>
+                </ZTTable>
+                <div class="pagination">
+                    <div></div>
+                    <el-pagination
+                        :page-size="pagination.pageSize"
+                        :page-sizes="[10, 20, 30, 40]"
+                        :total="pagination.total"
+                        layout="total, sizes, prev, pager, next, jumper"
+                        @current-change="handleCurrent"
+                        @size-change="handleSize"
+                    >
+                    </el-pagination>
+                </div>
+            </template>
+        </TableCard>
+        <Edit ref="editRef" :contentsId="contentsId" @submit="getTableData" type="缂栬緫" />
+    </div>
+</template>
+
+<script>
+import TableCard from '@/components/caorui/TableCard/index.vue';
+import ZTTable from '@/components/caorui/ZTTable/index.vue';
+import Edit from "../components/Edit.vue"
+import { selectQualifiedSupplierManagementPage, delSupplierManagement, exportSupplierManagement } from "@/assets/api/api";
+import axios from "axios";
+
+export default {
+    components: {
+        TableCard, ZTTable, Edit
+    },
+    props: {
+        contentsId: {
+            type: Number,
+            default: 0
+        }
+    },
+    data() {
+        return {
+            columns: [
+                {
+                    label: "渚涘簲鍟嗙紪鍙�",
+                    prop: "supplierRef"
+                },
+                {
+                    label: "渚涘簲鍟�",
+                    prop: "supplierName"
+                },
+                {
+                    label: "渚涘簲鐗╁搧(鏈嶅姟)鍚嶇О",
+                    prop: "supplierItemServiceName"
+                },
+                {
+                    label: "鍦板潃",
+                    prop: "adress"
+                },
+                {
+                    label: "鑱旂郴鐢佃瘽",
+                    prop: "phone"
+                },
+                {
+                    fixed: "right",
+                    dataType: "slot",
+                    slot: "action",
+                    label: "鎿嶄綔"
+                }
+            ],
+            tableData: [],
+            pagination: {
+                current: 1,
+                pageSize: 20,
+                total: 0
+            },
+        }
+    },
+    mounted() {
+        this.getTableData()
+    },
+    watch: {
+        contentsId(newVal) {
+            if (newVal !== 0) {
+                this.getTableData();
+            }
+        },
+    },
+    methods: {
+        // 鑾峰彇琛ㄦ牸鏁版嵁
+        async getTableData() {
+            const {code, data } = await axios({
+                method: 'get',
+                url: selectQualifiedSupplierManagementPage,
+                params: {
+                  ...this.pagination,
+                  parentId: this.contentsId
+                }
+            })
+            if(code == 200) {
+                this.tableData = data.records;
+            }
+        },
+        showDialog(scope) {
+            this.$refs.editRef.openDialog(scope)
+        },
+        handleCurrent(val) {
+            this.pagination.current = val;
+            this.getTableData()
+        },
+        handleSize(size) {
+            this.pagination.pageSize = size;
+            this.getTableData()
+        },
+        // 鍒犻櫎鏁版嵁
+        delRow(scope) {
+            this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ枃浠�, 鏄惁缁х画?', '鎻愮ず', {
+                confirmButtonText: '纭畾',
+                cancelButtonText: '鍙栨秷',
+                type: 'warning'
+            }).then( async () => {
+                const { code } = await axios({
+                    method: 'post',
+                    url: `${delSupplierManagement}/${scope.row.supplierManagementId}`,
+                })
+                if(code == 200) {
+                    this.$message.success('鍒犻櫎鎴愬姛')
+                    this.getTableData()
+                } else {
+                    this.$message.error('鍒犻櫎澶辫触')
+                }
+            }).catch(() => {
+                this.$message({
+                    type: 'info',
+                    message: '宸插彇娑堝垹闄�'
+                });
+            })
+        },
+        async exportExcel() {
+            const res = await axios({
+                method: "post",
+                url: `${exportSupplierManagement}/${this.contentsId}`,
+                responseType: "blob"
+            })
+            const blob = new Blob([res], {type: 'application/octet-stream'});
+          //灏咮lob 瀵硅薄杞崲鎴愬瓧绗︿覆
+          let reader = new FileReader();
+          reader.readAsText(blob, 'utf-8');
+          reader.onload = () => {
+            try {
+              let result = JSON.parse(reader.result);
+              if (result.message) {
+                this.$message.error(result.message);
+              } else {
+                const url = URL.createObjectURL(blob);
+                const link = document.createElement('a');
+                link.href = url;
+                link.download = '鍚堟牸渚涘簲鍟�.xlsx';
+                link.click();
+                this.$message.success('瀵煎嚭鎴愬姛')
+              }
+            } catch (err) {
+              console.log(err);
+              const url = URL.createObjectURL(blob);
+              const link = document.createElement('a');
+              link.href = url;
+              link.download = '鍚堟牸渚涘簲鍟�.xlsx';
+              link.click();
+              this.$message.success('瀵煎嚭鎴愬姛')
+            }
+          }
+        }
+    }
+}
+</script>
+
+<style scoped>
+.flex {
+    display: flex;
+}
+.action-box {
+    width: 100%;
+    padding-top: 10px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+}
+.pagination {
+    padding-top: 15px;
+    padding-right: 10px;
+    display: flex;
+    justify-content: space-between
+}
+</style>
diff --git a/src/components/caorui/6-6/components/Edit.vue b/src/components/caorui/6-6/components/Edit.vue
new file mode 100644
index 0000000..23c6ae5
--- /dev/null
+++ b/src/components/caorui/6-6/components/Edit.vue
@@ -0,0 +1,237 @@
+<template>
+    <el-dialog
+        title="渚涘簲鍟嗚鎯�"
+        width="40%"
+        :visible.sync="dialogVisible"
+    >
+        <el-form :model="model" label-width="auto">
+            <el-row>
+                <el-col :span="12">
+                    <el-form-item label="渚涘簲鍟�">
+                        <el-input v-model="model.supplierName" placeholder="璇疯緭鍏�" :disabled="type=='璇︽儏'" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="缂栧彿">
+                        <el-input v-model="model.supplierRef" placeholder="璇疯緭鍏�" :disabled="type=='璇︽儏'" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row>
+                <el-col :span="24">
+                    <el-form-item label="渚涘簲鍟嗙墿鍝佹湇鍔″悕绉�">
+                        <el-input v-model="model.supplierItemServiceName" :disabled="type=='璇︽儏'" placeholder="璇疯緭鍏�" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row>
+                <el-col :span="12">
+                    <el-form-item label="閭紪">
+                        <el-input v-model="model.postalCode" :disabled="type=='璇︽儏'" placeholder="璇疯緭鍏�" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="鍦板潃">
+                        <el-input v-model="model.adress" :disabled="type=='璇︽儏'" placeholder="璇疯緭鍏�" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row>
+                <el-col :span="24">
+                    <el-form-item label="logo">
+                        <div class="rows">
+                            <el-input placeholder="璇疯緭鍏�" :disabled="type=='璇︽儏'" v-model="model.logo" style="width: 100%;" />
+                            <el-upload
+                                ref="upload"
+                                style="float: left; margin: 0 12px 0 20px;"
+                                :action="action"
+                                :show-file-list="false"
+                                :on-success="onSuccess"
+                            >
+                                <el-button class="uploadFile" slot="trigger" type="primary" :disabled="type=='璇︽儏'">娴忚</el-button>
+                            </el-upload>
+                        </div>
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row>
+                <el-col :span="12">
+                    <el-form-item label="鑱旂郴浜�">
+                        <el-input v-model="model.contacts" placeholder="璇疯緭鍏�" :disabled="type=='璇︽儏'" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="鑱旂郴鐢佃瘽">
+                        <el-input v-model="model.phone" placeholder="璇疯緭鍏�" :disabled="type=='璇︽儏'" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row>
+                <el-col :span="12">
+                    <el-form-item label="鎴峰悕">
+                        <el-input v-model="model.householdName" placeholder="璇疯緭鍏�" :disabled="type=='璇︽儏'" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="浼犵湡">
+                        <el-input v-model="model.fax" placeholder="璇疯緭鍏�" :disabled="type=='璇︽儏'" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row>
+                <el-col :span="12">
+                    <el-form-item label="寮�鎴疯">
+                        <el-input v-model="model.openingName" placeholder="璇疯緭鍏�" :disabled="type=='璇︽儏'" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="缃戝潃">
+                        <el-input v-model="model.website" placeholder="璇疯緭鍏�" :disabled="type=='璇︽儏'" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            <el-row>
+                <el-col :span="12">
+                    <el-form-item label="璐﹀彿">
+                        <el-input v-model="model.accountName" placeholder="璇疯緭鍏�" :disabled="type=='璇︽儏'" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="Email">
+                        <el-input v-model="model.email" placeholder="璇疯緭鍏�" :disabled="type=='璇︽儏'" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+        </el-form>
+        <span slot="footer" v-if="type!='璇︽儏'">
+            <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
+            <el-button type="primary" @click="submit">淇� 瀛�</el-button>
+        </span>
+    </el-dialog>
+</template>
+
+<script>
+import { addSupplierManagement, updateSupplierManagement } from "@/assets/api/api";
+import axios from 'axios';
+export default {
+    props: {
+        contentsId: {
+            type: Number,
+            default: 0
+        },
+        type:{
+            type: String,
+            default: '缂栬緫'
+        }
+    },
+    data() {
+        return {
+            dialogVisible: false,
+            model: {
+                parentId: this.contentsId,
+                supplierManagementId: undefined,
+                supplierName: undefined,    // 渚涘簲鍟�
+                supplierRef: undefined, // 缂栧彿
+                supplierItemServiceName: undefined, // 渚涘簲鍟嗙墿鍝佹湇鍔″悕绉�
+                postalCode: undefined, // 閭紪
+                adress: undefined, // 鍦板潃
+                logo: undefined, // logo
+                contacts: undefined, // 鑱旂郴浜�
+                phone: undefined, // 鑱旂郴鐢佃瘽
+                householdName: undefined, // 鎴峰悕
+                fax: undefined, // 浼犵湡
+                openingName: undefined, // 寮�鎴疯
+                website: undefined, // 缃戝潃
+                accountName: undefined, // 璐﹀彿
+                email: undefined    // Email
+            }
+        }
+    },
+    computed: {
+        action() {
+            return `${this.javaApi}/${this.$api.personnel.saveCNASFile}`
+        }
+    },
+    methods: {
+        openDialog(form) {
+            if(form) {
+                console.log(form.row)
+                this.model.supplierManagementId = form.row.supplierManagementId
+                this.model.supplierName = form.row.supplierName
+                this.model.supplierRef = form.row.supplierRef
+                this.model.supplierItemServiceName = form.row.supplierItemServiceName
+                this.model.postalCode = form.row.postalCode
+                this.model.adress = form.row.adress
+                this.model.logo = form.row.logo
+                this.model.contacts = form.row.contacts
+                this.model.phone = form.row.phone
+                this.model.householdName = form.row.householdName
+                this.model.fax = form.row.fax
+                this.model.openingName = form.row.openingName
+                this.model.website = form.row.website
+                this.model.accountName = form.row.accountName
+                this.model.email = form.row.email
+            }else{
+              this.model = {
+                parentId: this.contentsId,
+                supplierManagementId: undefined,
+                supplierName: undefined,    // 渚涘簲鍟�
+                supplierRef: undefined, // 缂栧彿
+                supplierItemServiceName: undefined, // 渚涘簲鍟嗙墿鍝佹湇鍔″悕绉�
+                postalCode: undefined, // 閭紪
+                adress: undefined, // 鍦板潃
+                logo: undefined, // logo
+                contacts: undefined, // 鑱旂郴浜�
+                phone: undefined, // 鑱旂郴鐢佃瘽
+                householdName: undefined, // 鎴峰悕
+                fax: undefined, // 浼犵湡
+                openingName: undefined, // 寮�鎴疯
+                website: undefined, // 缃戝潃
+                accountName: undefined, // 璐﹀彿
+                email: undefined    // Email
+              }
+            }
+            this.model.parentId = this.contentsId
+            this.dialogVisible = true
+        },
+        async submit() {
+            if(this.model.supplierManagementId) {
+                const { code } = await axios({
+                    url: updateSupplierManagement,
+                    method: 'post',
+                    data: this.model,
+                    noQs: true
+                })
+                if(code == 200) {
+                    this.$message.success('淇敼鎴愬姛')
+                    this.$emit('submit')
+                    this.dialogVisible = false
+                }
+            } else {
+                const { code } = await axios({
+                    url: addSupplierManagement,
+                    method: 'post',
+                    data: this.model,
+                    noQs: true
+                })
+                if(code == 200) {
+                    this.$message.success('鏂板鎴愬姛')
+                    this.$emit('submit')
+                    this.dialogVisible = false
+                }
+            }
+        },
+        async onSuccess(response) {
+            this.$set(this.model, "logo", response.data)
+        }
+    }
+}
+</script>
+
+<style scoped>
+.rows {
+    width: 100%;
+    display: flex;
+    justify-content: space-between;
+}
+</style>
diff --git a/src/components/do/a6.service-and-supply-purchase/ConsumableList.vue b/src/components/do/a6.service-and-supply-purchase/ConsumableList.vue
new file mode 100644
index 0000000..09a7a85
--- /dev/null
+++ b/src/components/do/a6.service-and-supply-purchase/ConsumableList.vue
@@ -0,0 +1,287 @@
+<template>
+  <div>
+    <TableCard :showTitle="false">
+      <template slot="form">
+        <div class="action-box">
+          <div></div>
+          <div class="flex">
+            <el-button icon="el-icon-plus" size="small" type="primary" @click="showDialog(undefined)">
+              鏂板缓
+            </el-button>
+            <el-button icon="el-icon-upload2" size="small" @click="exportExcel">
+              瀵煎嚭Excel
+            </el-button>
+          </div>
+        </div>
+      </template>
+      <template v-slot:table>
+        <ZTTable
+          :column="columns"
+          :currentChange="rowClick"
+          :height="'25vh'"
+          :highlightCurrentRow="true"
+          :isSelection="false"
+          :rowStyle="tableRowStyle"
+          :table-data="tableData"
+          rowKey="id"
+          style="margin-top: 18px; padding: 0 15px;"
+        >
+          <template v-slot:consumablesTypeSlot="{row}">
+            {{ findType(row.consumablesType) }}
+          </template>
+          <template v-slot:operation="scope">
+            <el-button size="small" type="text" @click="showDialog(scope.row)">缂栬緫</el-button>
+            <el-button size="small" style="color: #f56c6c" type="text" @click="handleDelete(scope.row)">鍒犻櫎</el-button>
+          </template>
+        </ZTTable>
+        <div class="pagination">
+          <div></div>
+          <el-pagination
+            :page-size="pagination.pageSize"
+            :page-sizes="[10, 20, 30, 40]"
+            :total="pagination.total"
+            layout="total, sizes, prev, pager, next, jumper"
+            @current-change="handleCurrent"
+            @size-change="handleSize"
+          >
+          </el-pagination>
+        </div>
+      </template>
+    </TableCard>
+    <el-divider></el-divider>
+    <div>
+      <ConsumableProject ref="consumableProject" @submit="fetchData"></ConsumableProject>
+    </div>
+    <Edit ref="editRef" :contentsId="contentsId" @submit="fetchData"/>
+  </div>
+</template>
+
+<script>
+import TableCard from '@/components/caorui/TableCard/index.vue';
+import ZTTable from '@/components/caorui/ZTTable/index.vue';
+import Edit from "./components/Edit.vue"
+import axios from "axios";
+import {
+  addProcurementSuppliesList,
+  deleteProcurementSuppliesList,
+  procurementSuppliesList,
+  procurementSuppliesListExport
+} from "@/assets/api/api";
+import ConsumableProject from "@/components/do/a6.service-and-supply-purchase/ConsumableProject.vue"
+
+export default {
+  components: {
+    TableCard, ZTTable, Edit, ConsumableProject
+  },
+  props: {
+    contentsId: {
+      type: Number,
+      required: true,
+    }
+  },
+  watch: {
+    contentsId(newVal, oldVal) {
+      if (newVal !== 0) {
+        this.fetchData()
+      }
+    }
+  },
+  data() {
+    return {
+      columns: [
+        {
+          label: "璐у彿",
+          prop: "itemNumber"
+        },
+        {
+          label: "绫诲埆",
+          prop: "consumablesType",
+          dataType: "slot",
+          slot: "consumablesTypeSlot"
+        },
+        {
+          label: "鍚嶇О",
+          prop: "consumablesName"
+        },
+        {
+          label: "瑙勬牸",
+          prop: "specifications"
+        },
+        {
+          label: "鍙傝�冧緵搴斿晢",
+          prop: "supplierName"
+        },
+        {
+          label: "搴撳瓨涓嬮檺",
+          prop: "lowerLimit"
+        },
+        {
+          label: "褰撳墠搴撳瓨",
+          prop: "currentAmount"
+        },
+        {
+          label: "璁¢噺鍗曚綅",
+          prop: "unit"
+        },
+        {
+          label: "澶囨敞",
+          prop: "remark"
+        },
+        {
+          label: "璐熻矗浜�",
+          prop: "personInChargeName"
+        },
+        {
+          label: "鏈�杩戞洿鏂颁汉",
+          prop: "updateUserName"
+        },
+        {
+          label: "鏈�杩戞洿鏂版棩鏈�",
+          prop: "updateTime"
+        },
+        {
+          fixed: 'right',
+          label: "鎿嶄綔",
+          width: 120,
+          dataType: "slot",
+          slot: "operation"
+        }
+      ],
+      tableData: [],
+      pagination: {
+        current: 1,
+        pageSize: 20,
+        total: 0
+      },
+      options: [],
+    }
+  },
+  mounted() {
+    this.fetchData()
+    this.selectEnumByCategory()
+  },
+  methods: {
+    async fetchData() {
+      const res = await axios({
+        method: 'get',
+        url: `${procurementSuppliesList}`,
+        params: {
+          // page: this.pagination.current,
+          // pageSize: this.pagination.pageSize,
+          contentsId: this.contentsId
+        }
+      })
+      if (res.code === 200) {
+        this.tableData = res.data.records
+        if (this.tableData.length > 0) {
+          this.rowClick(this.tableData[0])
+        }
+      }
+    },
+    // 鑾峰彇瀛楀吀
+    async selectEnumByCategory() {
+      await this.$axios.post(this.$api.enums.selectEnumByCategory, {
+        category: "鑰楁潗绫诲瀷"
+      }).then(res => {
+        this.options = res.data
+      })
+    },
+    findType(val) {
+      this.$nextTick()
+      let res
+      const e = this.options.find(item => item.value == val)
+      if(e) {
+        res = e.label
+      } else {
+        res = '-'
+      }
+      return res
+    },
+    showDialog(row) {
+      this.$refs.editRef.openDialog(row);
+    },
+    async exportExcel() {
+      const res = await axios({
+        method: "post",
+        url: `${procurementSuppliesListExport}/${this.contentsId}`,
+        responseType: "blob"
+      })
+      const blob = new Blob([res], {type: 'application/octet-stream'});
+      //灏咮lob 瀵硅薄杞崲鎴愬瓧绗︿覆
+      let reader = new FileReader();
+      reader.readAsText(blob, 'utf-8');
+      reader.onload = () => {
+        try {
+          let result = JSON.parse(reader.result);
+          if (result.message) {
+            this.$message.error(result.message);
+          } else {
+            const url = URL.createObjectURL(blob);
+            const link = document.createElement('a');
+            link.href = url;
+            link.download = '鑰楁潗鍒楄〃.xlsx';
+            link.click();
+            this.$message.success('瀵煎嚭鎴愬姛')
+          }
+        } catch (err) {
+          console.log(err);
+          const url = URL.createObjectURL(blob);
+          const link = document.createElement('a');
+          link.href = url;
+          link.download = '鑰楁潗鍒楄〃.xlsx';
+          link.click();
+          this.$message.success('瀵煎嚭鎴愬姛')
+        }
+      }
+    },
+    handleCurrent() {
+    },
+    handleSize() {
+    },
+    handleDelete(row) {
+      this.$axios.post(deleteProcurementSuppliesList, row, {
+        headers: {
+          'Content-Type': 'application/json'
+        }
+      }).then(res => {
+        if (res.code === 200) {
+          this.$message.success('鍒犻櫎鎴愬姛')
+          this.fetchData()
+        }
+      })
+    },
+    rowClick(row) {
+      this.$refs.consumableProject.fetchListId(row)
+    },
+    tableRowStyle({row}) {
+      if(row.currentAmount <= row.lowerLimit) {
+        return { background: '#ffcaca' }
+      } else {
+        return {}
+      }
+    }
+  }
+}
+</script>
+
+
+<style scoped>
+.flex {
+  display: flex;
+}
+
+.action-box {
+  width: 100%;
+  padding-top: 10px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+
+.pagination {
+  padding-top: 15px;
+  padding-right: 10px;
+  display: flex;
+  justify-content: space-between
+}
+</style>
diff --git a/src/components/do/a6.service-and-supply-purchase/ConsumableOverview.vue b/src/components/do/a6.service-and-supply-purchase/ConsumableOverview.vue
new file mode 100644
index 0000000..2557ed7
--- /dev/null
+++ b/src/components/do/a6.service-and-supply-purchase/ConsumableOverview.vue
@@ -0,0 +1,126 @@
+<template>
+    <div>
+        <el-row class="card-box">
+            <el-col :span="4" v-for="(item, index) in cardList" :key="index">
+                <CardPanel
+                    :isActive="isActive"
+                    :data="item"
+                    :index="index"
+                    @handleCard="handleCard"
+                />
+            </el-col>
+            <el-col :span="24" v-if="cardList.length==0" style="color: #909399;font-size: 14px;text-align: center;margin-top: 20px;">鏆傛棤鏁版嵁</el-col>
+        </el-row>
+        <TableCard title="鑰楁潗淇℃伅" :showForm="false" style="margin-top: 5px">
+            <template v-slot:table>
+                <ZTTable
+                    style="margin-top: 18px; padding: 0 15px;"
+                    :height="'20vh'"
+                    :column="columns"
+                    :table-data="tableData"
+                >
+                </ZTTable>
+            </template>
+        </TableCard>
+    </div>
+</template>
+<script>
+import CardPanel from '@/components/caorui/6-6/ConsumableOverview/components/CardPanel';
+import TableCard from '@/components/caorui/TableCard/index.vue';
+import ZTTable from '@/components/caorui/ZTTable/index.vue';
+import { procurementSuppliesList } from "@/assets/api/api";
+import axios from "axios";
+
+export default {
+    components: { CardPanel, TableCard, ZTTable },
+    props: {
+        contentsId: {
+            type: Number,
+            default: 0
+        }
+    },
+    data() {
+        return {
+            isActive: -1,
+            columns: [
+                {
+                    label: "鑰楁潗缂栧彿",
+                    prop: "itemNumber"
+                },
+                {
+                    label: "鑰楁潗鍚嶇О",
+                    prop: "consumablesName"
+                },
+                {
+                    label: "鑰楁潗绫诲瀷",
+                    prop: "consumablesType"
+                },
+                {
+                    label: "瑙勬牸",
+                      prop: "specifications"
+                },
+                {
+                    label: "鍗曚綅",
+                    prop: "unit"
+                },
+                {
+                    label: "鍗曚环",
+                    prop: "referencePrice"
+                },
+                {
+                    label: "褰撳墠搴撳瓨",
+                    prop: "currentAmount"
+                },
+                {
+                    label: "璐熻矗浜�",
+                    prop: "personInChargeName"
+                },
+                {
+                    label: "涓婃鏇存柊鏃堕棿",
+                    prop: "updateTime"
+                }
+            ],
+            cardList: [],
+            tableData: []
+        }
+    },
+    watch: {
+        contentsId(newVal, oldVal) {
+            this.getTableData(newVal)
+        }
+    },
+    mounted() {
+        this.getTableData(this.contentsId)
+    },
+    methods: {
+        handleCard(data, index) {
+            this.isActive = index
+            this.tableData = [data]
+        },
+        async getTableData(id) {
+            const { code, data } = await axios({
+                method: 'get',
+                url: `${procurementSuppliesList}`,
+                params: {
+                    contentsId: id
+                }
+            })
+            if(code == 200) {
+                this.cardList = data.records.map(m=>{
+                  m.logo = m.consumablesIcon
+                  return m
+                })
+            }
+        }
+    }
+}
+</script>
+<style scoped>
+.card-box {
+    width: 100%;
+    padding-left: 5px;
+    padding-right: 5px;
+    height: 30vh;
+    overflow-y: auto;
+}
+</style>
diff --git a/src/components/do/a6.service-and-supply-purchase/ConsumableProject.vue b/src/components/do/a6.service-and-supply-purchase/ConsumableProject.vue
new file mode 100644
index 0000000..dfdcbeb
--- /dev/null
+++ b/src/components/do/a6.service-and-supply-purchase/ConsumableProject.vue
@@ -0,0 +1,175 @@
+<template>
+  <div>
+    <TableCard :showTitle="false">
+      <template slot="form">
+        <div class="action-box">
+          <div></div>
+          <div class="flex">
+            <el-button icon="el-icon-plus" size="small" type="primary" @click="showDialog">
+              娣诲姞椤圭洰
+            </el-button>
+            <!-- <el-button icon="el-icon-upload2" size="small" @click="exportExcel">
+              瀵煎嚭
+            </el-button> -->
+          </div>
+        </div>
+      </template>
+      <template v-slot:table>
+        <ZTTable
+          :column="columns"
+          :height="'25vh'"
+          :isSelection="true"
+          :table-data="tableData"
+          style="margin-top: 18px; padding: 0 15px;"
+        >
+          <template v-slot:operation="scope">
+            <el-button size="small" type="text" @click="deleteData(scope.row)">鍒犻櫎</el-button>
+          </template>
+        </ZTTable>
+        <div class="pagination">
+          <div></div>
+          <el-pagination
+            :page-size="pagination.pageSize"
+            :page-sizes="[10, 20, 30, 40]"
+            :total="pagination.total"
+            layout="total, sizes, prev, pager, next, jumper"
+            @current-change="handleCurrent"
+            @size-change="handleSize"
+          >
+          </el-pagination>
+        </div>
+      </template>
+    </TableCard>
+    <AddProject ref="AddProjectRef" @submit="fetchData,$emit('submit')"/>
+  </div>
+</template>
+
+<script>
+import TableCard from '@/components/caorui/TableCard/index.vue';
+import ZTTable from '@/components/caorui/ZTTable/index.vue';
+import Edit from "./components/Edit.vue"
+import AddProject from './components/AddProject.vue';
+import {
+  deleteProcurementSuppliesExpends,
+  procurementSuppliesExpendsList,
+  procurementSuppliesList
+} from "../../../assets/api/api";
+import axios from "axios";
+
+export default {
+  components: {
+    TableCard, ZTTable, Edit, AddProject
+  },
+  data() {
+    return {
+      columns: [
+        // {
+        //   label: "缂栧彿"
+        // },
+        {
+          label: "椤圭洰鍚嶇О",
+          prop: "listName"
+        },
+        {
+          label: "娑堣�楁暟閲�",
+          prop: "amount"
+        },
+        {
+          label: "褰曞叆浜�",
+          prop: "enterUserName"
+        },
+        {
+          label: "鏈�杩戞洿鏂颁汉",
+          prop: "updateUserName"
+        },
+        {
+          label: "鏈�杩戞洿鏂版棩鏈�",
+          prop: "updateTime"
+        },
+        {
+          label: "鎿嶄綔",
+          dataType: "slot",
+          slot: "operation"
+        }
+      ],
+      tableData: [],
+      pagination: {
+        current: 1,
+        pageSize: 20,
+        total: 0
+      },
+      listId: 0,
+      row: undefined
+    }
+  },
+  mounted() {
+    this.fetchData()
+  },
+  methods: {
+    fetchListId(row) {
+      if(row) {
+        this.listId = row.id
+        this.row = row
+      }
+      this.fetchData()
+    },
+    async fetchData() {
+      if (this.listId === 0) return
+      const res = await axios({
+        method: 'get',
+        url: `${procurementSuppliesExpendsList}/${this.listId}`,
+        params: {
+          // page: this.pagination.current,
+          // pageSize: this.pagination.pageSize,
+        }
+      })
+      if (res.code === 200) {
+        this.tableData = res.data
+      }
+    },
+    showDialog() {
+      this.$refs.AddProjectRef.openDialog(this.row);
+    },
+    deleteData(row) {
+      this.$axios.post(deleteProcurementSuppliesExpends, row, {
+              headers: {
+                'Content-Type': 'application/json'
+              }
+            }).then(res => {
+        if (res.code === 200) {
+          this.$message.success('鍒犻櫎鎴愬姛')
+          this.$emit('submit')
+          this.fetchData()
+        }
+      })
+    },
+    handleCurrent() {
+    },
+    handleSize() {
+    },
+    exportExcel() {
+    }
+  }
+}
+</script>
+
+<style scoped>
+.flex {
+  display: flex;
+}
+
+.action-box {
+  width: 100%;
+  padding-top: 10px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+
+.pagination {
+  padding-top: 15px;
+  padding-right: 10px;
+  display: flex;
+  justify-content: space-between
+}
+</style>
diff --git a/src/components/do/a6.service-and-supply-purchase/Store.vue b/src/components/do/a6.service-and-supply-purchase/Store.vue
new file mode 100644
index 0000000..affc864
--- /dev/null
+++ b/src/components/do/a6.service-and-supply-purchase/Store.vue
@@ -0,0 +1,516 @@
+<template>
+  <div>
+    <div style="
+        display: flex;
+        justify-content: flex-end;
+        margin-right: 20px;
+        margin-bottom: 20px;
+      ">
+      <el-button icon="el-icon-plus" size="small" type="primary" @click="addOrUpdateStore('add')">娣诲姞
+      </el-button>
+      <el-button icon="el-icon-download" size="small" @click="importExcel">
+        瀵煎嚭excel
+      </el-button>
+    </div>
+    <div class="table">
+      <ZTTable
+        :column="tableColumn"
+        :height="'calc(100vh - 20em)'"
+        :table-data="storageTableData"
+        :table-loading="tableLoading"
+        style="padding: 0 10px;margin-bottom: 16px">
+      </ZTTable>
+      <el-pagination
+        :current-page="1"
+        :page-size="page.size"
+        :page-sizes="[10, 20, 30, 50, 100]"
+        :total="total" layout="->,total, sizes, prev, pager, next, jumper"
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange">
+      </el-pagination>
+    </div>
+
+    <!-- 缂栬緫-鏂板寮规 -->
+    <el-dialog :before-close="handleClose" :close-on-click-modal="false"
+               :close-on-press-escape="false" :title="title"
+               :visible.sync="dialogVisible" width="70%">
+      <!-- 鍏ュ簱鍗� -->
+      <div>
+        <div style="display: flex; align-items: center">
+          <span style="margin-left: 10px">鍏ュ簱鍗�</span>
+        </div>
+        <el-form ref="formModel" :model="form" label-width="auto">
+          <el-col :span="12">
+            <el-form-item label="鍏ュ簱鍗曞彿">
+              <el-input v-model="form.oddNumbers" placeholder="璇疯緭鍏ュ叆搴撳崟鍙�" size="small"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鍏ュ簱搴撳瓨">
+              <el-input v-model="form.inventory" placeholder="璇疯緭鍏ュ叆搴撳簱瀛�" size="small"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鍏ュ簱鎬婚噾棰�">
+              <el-input v-model="form.totalAmount" placeholder="璇疯緭鍏ュ叆搴撴�婚噾棰�" size="small"></el-input>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鍏ュ簱鏃ユ湡">
+              <el-date-picker v-model="form.storageTime" format="yyyy-MM-dd"
+                              placeholder="閫夋嫨鏃ユ湡"
+                              size="small"
+                              style="width: 100%" type="date" value-format="yyyy-MM-dd"></el-date-picker>
+            </el-form-item>
+          </el-col>
+            <el-col :span="12">
+              <el-form-item label="鍏ュ簱浜�">
+                <el-select v-model="form.storageUser" size="small" style="width: 100%">
+                  <el-option v-for="item in users" :key="item.id" :label="item.nodeName" :value="item.id"></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+          <el-col :span="12">
+            <el-form-item label="鍏ュ簱璇存槑">
+              <el-input v-model="form.remark" :rows="2" placeholder="璇疯緭鍏ュ唴瀹�" type="textarea">
+              </el-input>
+            </el-form-item>
+          </el-col>
+        </el-form>
+      </div>
+      <!-- 鍏ュ簱鏄庣粏 -->
+      <div>
+        <div>鍏ュ簱鏄庣粏</div>
+        <div class="input-form">
+          <div>
+            <div>
+              <span>鑰楁潗鍚嶇О:</span>
+              <el-select v-model="formTwo.id" filterable placeholder="璇烽�夋嫨鑰楁潗鍚嶇О" size="small" style="width: 70%">
+                <el-option v-for="(v, i) in consumableOptions" :key="i" :label="v.consumablesName"
+                  :value="v.id"></el-option>
+              </el-select>
+            </div>
+          </div>
+          <div>
+            <div>
+              <span>鍗曚环:</span>
+              <el-input v-model="formTwo.unitPrice" placeholder="璇疯緭鍏ュ崟浠�" size="small" style="width: 70%">
+              </el-input>
+            </div>
+          </div>
+          <div>
+            <div>
+              <span>鍏ュ簱鏁伴噺:</span>
+              <el-input v-model="formTwo.storeNumber" placeholder="璇疯緭鍏ュ叆搴撴暟閲�" size="small" style="width: 70%">
+              </el-input>
+            </div>
+          </div>
+          <div>
+            <div>
+              <span>鎬讳环:</span>
+              <el-input v-model="formTwo.totalPrice" placeholder="璇疯緭鍏ユ�讳环" size="small" style="width: 70%">
+              </el-input>
+            </div>
+          </div>
+          <el-button size="mini" type="primary"
+            @click="addTableData">娣诲姞
+          </el-button>
+        </div>
+        <el-table :data="consumables" style="margin-top: 10px">
+          <el-table-column label="缂栧彿" type="index" width="120px"></el-table-column>
+          <el-table-column label="璐у彿" prop="itemNumber"></el-table-column>
+          <el-table-column label="绫诲埆" prop="type"></el-table-column>
+          <el-table-column label="鍚嶇О" prop="consumablesName"></el-table-column>
+          <el-table-column label="瑙勬牸" prop="specifications"></el-table-column>
+          <el-table-column label="鍙傝�冧緵搴斿晢" prop="supplier"></el-table-column>
+          <el-table-column label="璁¢噺鍗曚綅" prop="unit"></el-table-column>
+          <el-table-column label="鍗曚环" prop="unitPrice"></el-table-column>
+          <el-table-column label="鍏ュ簱鏁伴噺" prop="storeNumber"></el-table-column>
+          <el-table-column label="鎬讳环" prop="totalPrice"></el-table-column>
+          <el-table-column label="鎿嶄綔" width="80px">
+            <template slot-scope="scope">
+              <el-button size="mini" style="color: #f56c6c" type="text" @click="deleteTableData(scope.$index)">鍒犻櫎
+              </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="handleClose">鍙� 娑�</el-button>
+        <el-button type="primary" @click="save">淇� 瀛�</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { procurementSuppliesList, procurementSuppliesStoreExportExcel } from "../../../assets/api/api";
+import axios from "axios";
+import ZTTable from '../../caorui/ZTTable/index.vue';
+
+export default {
+  computed: {
+    title() {
+      return this.dialogType == "add" ? "鏂板缓鍏ュ簱" : "缂栬緫鍏ュ簱";
+    },
+  },
+  props: {
+    contentsId: {
+      type: Number,
+      default: 0
+    }
+  },
+  watch: {
+
+  },
+  data() {
+    return {
+      mutiList: [],
+      consumables: [],
+      users: [],
+      form: {
+        oddNumbers: null,
+        inventory: null,
+        totalAmount: null,
+        storageTime: null,
+        storageUser: null,
+        remark: null,
+      },
+      formTwo: {
+        consumablesName: null,
+        unitPrice: null,
+        storeNumber: null,
+        totalPrice: null,
+      },
+      dialogVisible: false,
+      dialogType: "",
+      upIndex: 0,
+      tableColumn: [
+        {
+          label: '鍏ュ簱鍗曞彿',
+          prop: 'oddNumbers',
+          minWidth: '100'
+        },
+        {
+          label: '鑰楁潗鍚嶇О',
+          prop: 'consumablesName',
+          minWidth: '100'
+        },
+        {
+          label: '鍏ュ簱鏁伴噺',
+          prop: 'storeNumber',
+          minWidth: '100'
+        },
+        {
+          label: '鍏ュ簱鎬讳环',
+          prop: 'totalPrice',
+          minWidth: '100'
+        },
+        {
+          label: '鍏ュ簱浜�',
+          prop: 'storageUserName',
+          minWidth: '100'
+        }, {
+          label: '鍏ュ簱鏃ユ湡',
+          prop: 'storageTime',
+          minWidth: '100'
+        }, {
+          label: '璇存槑',
+          prop: 'remark',
+          minWidth: '100'
+        }, {
+          label: '鐧昏浜�',
+          prop: 'registrantName',
+          minWidth: '160'
+        },{
+          label: '鐧昏鏃ユ湡',
+          prop: 'registrantTime',
+          minWidth: '100'
+        },
+        {
+          dataType: 'action',
+          fixed: 'right',
+          minWidth: '120',
+          label: '鎿嶄綔',
+          operation: [
+            {
+              name: '缂栬緫',
+              type: 'text',
+              clickFun: (row) => {
+                this.addOrUpdateStore('edit', row);
+              },
+            },
+            {
+              name: '鍒犻櫎',
+              type: 'text',
+              color: '#f56c6c',
+              clickFun: (row) => {
+                this.deleteStore(row)
+              },
+            }
+          ]
+        }
+      ],
+      tableLoading: false,
+      page: {
+        size: 20,
+        current: 1,
+      },
+      total: 0,
+      consumableOptions: [],
+      options: [],
+      storageTableData: [],
+      searchForm: {
+        orderBy: {
+          field: "id",
+          order: "desc",
+        },
+      },
+    };
+  },
+  components: {
+    ZTTable,
+  },
+  mounted() {
+    this.searchList();
+    this.getUserList();
+    this.fetchListOptions()
+    this.selectEnumByCategory()
+  },
+  methods: {
+    // 淇濆瓨
+    save() {
+      let data = {
+        store: this.form,
+        consumables: this.consumables,
+      };
+      if(this.form.id){
+        // 缂栬緫
+        this.$axios
+        .post(this.$api.procurementSuppliesStore.updateStore, data, {
+          headers: {
+            "Content-Type": "application/json",
+          },
+        })
+        .then((res) => {
+          if (res.code == 200) {
+            this.$message.success("淇濆瓨鎴愬姛");
+            this.handleClose();
+            // this.$refs.selectList()
+            this.searchList()
+          }
+        });
+      }else{
+        // 鏂板
+        this.$axios
+        .post(this.$api.procurementSuppliesStore.addStore, data, {
+          headers: {
+            "Content-Type": "application/json",
+          },
+        })
+        .then((res) => {
+          if (res.code == 200) {
+            this.$message.success("淇濆瓨鎴愬姛");
+            this.handleClose();
+            // this.$refs.selectList()
+            this.searchList()
+          }
+        });
+      }
+    },
+    // 鑾峰彇瀛楀吀
+    selectEnumByCategory() {
+      this.$axios.post(this.$api.enums.selectEnumByCategory, {
+        category: "鑰楁潗绫诲瀷"
+      }).then(res => {
+        this.options = res.data
+      })
+    },
+    findType(val) {
+      console.log(val)
+      return this.options.find(item => item.value === val).label
+    },
+    // 娣诲姞琛ㄦ牸鏁版嵁
+    addTableData() {
+      this.$nextTick()
+      this.consumableOptions.forEach(item => {
+        if (item.id === this.formTwo.id) {
+          this.consumables.push({
+            itemNumber: null,
+            type: this.findType(item.consumablesType),
+            consumablesName: item.consumablesName,
+            specifications: item.specifications,
+            supplier: item.supplierName,
+            unit: item.unit,
+            unitPrice: this.formTwo.unitPrice,
+            storeNumber: this.formTwo.storeNumber,
+            totalPrice: this.formTwo.totalPrice,
+          });
+        }
+      })
+    },
+    deleteTableData(index) {
+      this.consumables.splice(index, 1);
+    },
+    // 鎵撳紑寮规
+    addOrUpdateStore(type,row) {
+      if (type === 'edit') {
+        this.dialogType = "update";
+        this.$axios.get(this.$api.procurementSuppliesStore.selectStoreById + '?id=' + row.id).then(res => {
+          if (res.code === 201) return
+          this.consumables = res.data.consumables
+          this.form = {...res.data.store}
+        }).catch(err => {
+          console.log('err---', err);
+        })
+      } else {
+        this.dialogType = "add";
+      }
+      this.dialogVisible = true;
+    },
+    // 鏌ヨ鍒楄〃
+    searchList () {
+      const entity = this.searchForm
+      const page = this.page
+      this.tableLoading = true
+      this.$axios.post(this.$api.procurementSuppliesStore.storeList, {entity, page}, {
+        headers: {
+          "Content-Type": "application/json"
+        },
+        noQs: true
+      }).then(res => {
+        this.tableLoading = false
+        if (res.code === 201) return
+        this.storageTableData = res.data.body.records
+        this.total = res.data.body.total
+      }).catch(err => {
+        console.log('err---', err);
+        this.tableLoading = false
+      })
+    },
+    // 鍒嗛〉
+    handleSizeChange(val) {
+      this.page.size = val;
+      this.searchList();
+    },
+    handleCurrentChange(val) {
+      this.page.current = val;
+      this.searchList();
+    },
+    // 瀵煎嚭excel
+    async importExcel() {
+      const res = await axios({
+        method: "post",
+        url: `${procurementSuppliesStoreExportExcel}/${this.contentsId}`,
+        responseType: "blob"
+      })
+      const blob = new Blob([res], {type: 'application/octet-stream'});
+      //灏咮lob 瀵硅薄杞崲鎴愬瓧绗︿覆
+      let reader = new FileReader();
+      reader.readAsText(blob, 'utf-8');
+      reader.onload = () => {
+        try {
+          let result = JSON.parse(reader.result);
+          if (result.message) {
+            this.$message.error(result.message);
+          } else {
+            const url = URL.createObjectURL(blob);
+            const link = document.createElement('a');
+            link.href = url;
+            link.download = '鑰楁潗鍏ュ簱.xlsx';
+            link.click();
+            this.$message.success('瀵煎嚭鎴愬姛')
+          }
+        } catch (err) {
+          console.log(err);
+          const url = URL.createObjectURL(blob);
+          const link = document.createElement('a');
+          link.href = url;
+          link.download = '鑰楁潗鍏ュ簱.xlsx';
+          link.click();
+          this.$message.success('瀵煎嚭鎴愬姛')
+        }
+      }
+    },
+    handleClose() {
+      this.form = {
+        oddNumbers: null,
+        inventory: null,
+        totalAmount: null,
+        storageTime: null,
+        storageUser: null,
+        remark: null,
+      };
+      this.formTwo = {
+        consumablesName: null,
+        unitPrice: null,
+        storeNumber: null,
+        totalPrice: null,
+      };
+      this.consumables = [];
+      this.dialogVisible = false;
+    },
+    viewIssued(row) {
+      console.log(row);
+    },
+    // 鑾峰彇鎵�鏈夌敤鎴�
+    getUserList() {
+      this.$axios
+        .get(this.$api.procurementSuppliesContents.getUserList)
+        .then((res) => {
+          this.users = res.data;
+        });
+    },
+    async fetchListOptions() {
+      const res = await axios({
+        method: 'get',
+        url: `${procurementSuppliesList}`,
+        params: {
+          contentsId: this.contentsId
+        }
+      })
+      if (res.code === 200) {
+        this.consumableOptions = res.data.records
+      }
+    },
+    // 鍒犻櫎
+    deleteStore (row) {
+      this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ユ暟鎹�, 鏄惁缁х画?', '鎻愮ず', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }).then(() => {
+        this.tableLoading = true
+        this.$axios.get(this.$api.procurementSuppliesStore.deleteStore + '?id=' + row.id + '&consumablesId=' + row.consumablesId).then(res => {
+          this.tableLoading = false
+          if (res.code === 201) return
+          this.$message.success('鍒犻櫎鎴愬姛')
+          this.searchList()
+        }).catch(err => {
+          this.tableLoading = false
+          console.log('err---', err);
+        })
+      }).catch(() => {
+        this.$message({
+          type: 'info',
+          message: '宸插彇娑堝垹闄�'
+        });
+      });
+    },
+  },
+};
+</script>
+
+<style scoped>
+>>>.el-dialog {
+  margin: 6vh auto 50px !important;
+}
+>>> .el-dialog__body {
+  max-height: 42em;
+  overflow-y: auto;
+}
+.input-form {
+  display: flex;
+  margin: 10px 0;
+}
+</style>
diff --git a/src/components/do/a6.service-and-supply-purchase/components/AddProject.vue b/src/components/do/a6.service-and-supply-purchase/components/AddProject.vue
new file mode 100644
index 0000000..2c967cd
--- /dev/null
+++ b/src/components/do/a6.service-and-supply-purchase/components/AddProject.vue
@@ -0,0 +1,96 @@
+<template>
+  <el-dialog
+    :title="dialogTitle"
+    width="60%"
+    :visible.sync="dialogVisible"
+  >
+    <el-form :model="model" label-width="100px">
+      <el-col :span="12">
+        <el-form-item label="椤圭洰鍚嶇О">
+          <el-select 
+            v-model="model.name"
+            placeholder="璇烽�夋嫨椤圭洰鍚嶇О"
+            style="width: 100%"
+            :disabled="row ? true:false"
+            @change="handleSelect"
+          >
+            <el-option 
+              v-for="(v, i) in consumableOptions" 
+              :label="v.consumablesName" 
+              :value="v"
+              :key="i"
+            />
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="娑堣�楁暟閲�">
+          <el-input-number v-model="model.amount" :min="0" :step="1" placeholder="璇疯緭鍏ユ秷鑰楁暟閲�"></el-input-number>
+        </el-form-item>
+      </el-col>
+    </el-form>
+    <span slot="footer" class="dialog-footer">
+            <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
+            <el-button type="primary" @click="sumbit">纭� 瀹�</el-button>
+        </span>
+  </el-dialog>
+</template>
+
+<script>
+import {addProcurementSuppliesExpends, procurementSuppliesList} from "../../../../assets/api/api";
+
+export default {
+  data() {
+    return {
+      dialogTitle: "",
+      dialogVisible: false,
+      model: {
+        listId: undefined,
+        name: ""
+      },
+      consumableOptions: [],
+      row: undefined
+    }
+  },
+  created() {
+    this.fetchConsumableOptions()
+  },
+  methods: {
+    fetchConsumableOptions() {
+      this.$axios.get(procurementSuppliesList).then(res => {
+        if (res.code === 200) {
+          this.consumableOptions = res.data.records
+        }
+      })
+    },
+    openDialog(row) {
+      if(row) {
+        console.log(row, 'true')
+        this.dialogTitle = `${row.consumablesName}娣诲姞娑堣�楅」`
+        this.row = row
+        this.model.listId = row.id
+        this.model.name = row.consumablesName
+      } else {
+        this.dialogTitle = '娣诲姞娑堣�楅」'
+      }
+      this.dialogVisible = true
+    },
+    handleSelect(item) {
+      console.log(item)
+      this.model.listId = item.id
+      this.model.name = item.consumablesName
+    },
+    sumbit() {
+      this.$axios.post(addProcurementSuppliesExpends, this.model, {
+        headers: {
+          'Content-Type': 'application/json'
+        }}).then(res => {
+        if (res.code === 200) {
+          this.dialogVisible = false
+          this.$emit('submit')
+        }
+      })
+    }
+    }
+  }
+</script>
diff --git a/src/components/do/a6.service-and-supply-purchase/components/Edit.vue b/src/components/do/a6.service-and-supply-purchase/components/Edit.vue
new file mode 100644
index 0000000..09669fe
--- /dev/null
+++ b/src/components/do/a6.service-and-supply-purchase/components/Edit.vue
@@ -0,0 +1,264 @@
+<template>
+  <el-dialog
+    :visible.sync="dialogVisible"
+    title="娣诲姞鑰楁潗椤圭洰淇℃伅"
+    width="70%"
+  >
+    <el-form ref="modelForm" :model="model" :rules="rules" label-width="100px">
+      <el-col :span="12">
+        <el-form-item label="鑰楁潗绫诲瀷" prop="consumablesType">
+          <el-select v-model="model.consumablesType" placeholder="璇烽�夋嫨鑰楁潗绫诲瀷" size="small" style="width: 100%">
+            <el-option v-for="(v, i) in options" :key="i" :label="v.label" :value="v.value"></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="璐у彿">
+          <el-input v-model="model.itemNumber" placeholder="璇疯緭鍏ヨ揣鍙�" size="small"></el-input>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="鑰楁潗鍚嶇О">
+          <el-input v-model="model.consumablesName" placeholder="璇疯緭鍏ヨ�楁潗鍚嶇О" size="small"></el-input>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="瑙勬牸">
+          <el-input v-model="model.specifications" placeholder="璇疯緭鍏ヨ鏍�" size="small"></el-input>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="璁¢噺鍗曚綅">
+          <el-input v-model="model.unit" placeholder="璇疯緭鍏ヨ閲忓崟浣�" size="small"></el-input>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="鍙傝�冧环鏍�">
+          <el-input-number v-model="model.referencePrice" :min="0" :precision="2" :step="0.01" placeholder="璇疯緭鍏ュ弬鑰冧环鏍�"
+                           size="small"></el-input-number>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="瀛樻斁浣嶇疆">
+          <el-select v-model="model.contentId" placeholder="璇烽�夋嫨瀛樻斁浣嶇疆" size="small" style="width: 100%">
+            <el-option v-for="(v, i) in procurementSuppliesContentOptions" :key="i" :label="v.nodeName"
+                       :value="v.id"></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="璐熻矗浜�">
+          <el-select v-model="model.personInCharge" placeholder="璇烽�夋嫨璐熻矗浜�" size="small" style="width: 100%">
+            <el-option v-for="(v, i) in userOptions" :key="i" :label="v.nodeName" :value="v.id"></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="搴撳瓨涓婇檺">
+          <el-input-number v-model="model.upperLimit" :min="0" :step="1" placeholder="璇疯緭鍏ュ簱瀛樹笂闄�" size="small"></el-input-number>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="搴撳瓨涓嬮檺">
+          <el-input-number v-model="model.lowerLimit" :min="0" :step="1" placeholder="璇疯緭鍏ュ簱瀛樹笅闄�" size="small"></el-input-number>
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="渚涘簲鍟�">
+          <el-select v-model="model.supplier" placeholder="璇烽�夋嫨渚涘簲鍟�" size="small" style="width: 100%">
+            <el-option v-for="(v, i) in supplierOptions" :key="i" :label="v.supplierName"
+                       :value="v.supplierManagementId"></el-option>
+          </el-select>
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="鑰楁潗鍥炬爣">
+          <div class="rows">
+            <el-input v-model="model.consumablesIcon" placeholder="璇疯緭鍏ヨ�楁潗鍥炬爣" size="small" style="width: 90%;"/>
+            <el-upload
+              ref="upload"
+              :action="action"
+              :on-success="onSuccessIcon"
+              :show-file-list="false"
+              style="float: left; margin: 0 12px 0 20px;"
+            >
+              <el-button slot="trigger" class="uploadFile" size="small" type="primary">娴忚</el-button>
+            </el-upload>
+          </div>
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="鑰楁潗闄勪欢">
+          <div class="rows">
+            <el-input v-model="model.attachment" placeholder="璇疯緭鍏ヨ�楁潗闄勪欢" size="small" style="width: 90%;"/>
+            <el-upload
+              ref="upload"
+              :action="action"
+              :on-success="onSuccessFile"
+              :show-file-list="false"
+              style="float: left; margin: 0 12px 0 20px;"
+            >
+              <el-button slot="trigger" class="uploadFile" size="small" type="primary">娴忚</el-button>
+            </el-upload>
+          </div>
+        </el-form-item>
+      </el-col>
+      <el-col :span="24">
+        <el-form-item label="澶囨敞">
+          <el-input
+            v-model="model.remark"
+            :rows="2"
+            placeholder="璇疯緭鍏ュ娉�"
+            size="small"
+            type="textarea"
+          >
+          </el-input>
+        </el-form-item>
+      </el-col>
+    </el-form>
+    <span slot="footer" class="dialog-footer">
+            <el-button @click="resetForm">鍙� 娑�</el-button>
+            <el-button type="primary" @click="submit">淇� 瀛�</el-button>
+        </span>
+  </el-dialog>
+</template>
+
+<script>
+import {addProcurementSuppliesList, selectSupplierManagementPage} from "@/assets/api/api";
+import {selectSupplierManagementAll, updateProcurementSuppliesList} from "../../../../assets/api/api";
+
+export default {
+  data() {
+    return {
+      dialogVisible: false,
+      model: {
+        consumablesType: undefined,
+        consumablesIcon: undefined,
+        attachment: undefined,
+      },
+      options: [],
+      procurementSuppliesContentOptions: [],
+      userOptions: [],
+      supplierOptions: [],
+      rules: {
+        consumablesType: [{ required: true, message: '璇烽�夋嫨鑰楁潗绫诲瀷', trigger: 'blur' }],
+      },
+    }
+  },
+  props: {
+    contentsId: {
+      type: Number,
+      required: true,
+    }
+  },
+  computed: {
+    action() {
+      return `${this.javaApi}/${this.$api.personnel.saveCNASFile}`
+    }
+  },
+  mounted() {
+    this.selectEnumByCategory()
+    this.findProcurementSuppliesContentOptions()
+    this.findUserOptions()
+    this.findSupplierOptions()
+  },
+  methods: {
+    // 閲嶇疆琛ㄥ崟
+    resetForm() {
+      this.$refs.modelForm.resetFields();
+      this.dialogVisible = false
+    },
+    openDialog(row) {
+      if (row) {
+        console.log("row", row)
+        this.model = row
+      } else {
+        this.model = {}
+      }
+      this.dialogVisible = true
+    },
+    // 鑾峰彇瀛楀吀
+    selectEnumByCategory() {
+      this.$axios.post(this.$api.enums.selectEnumByCategory, {
+        category: "鑰楁潗绫诲瀷"
+      }).then(res => {
+        this.options = res.data
+      })
+    },
+    findProcurementSuppliesContentOptions() {
+      this.$axios.get(this.$api.procurementSuppliesContents.getNodeNames, {}).then(res => {
+        if (res.code === 200) {
+          this.procurementSuppliesContentOptions = res.data
+        }
+      })
+    },
+    findUserOptions() {
+      this.$axios.get(this.$api.procurementSuppliesContents.getUserList, {}).then(res => {
+        if (res.code === 200) {
+          this.userOptions = res.data
+        }
+      })
+    },
+    findSupplierOptions() {
+      this.$axios.get(selectSupplierManagementAll, {}).then(res => {
+        if (res.code === 200) {
+          this.supplierOptions = res.data
+        }
+      })
+    },
+    async onSuccessIcon(response) {
+      this.$set(this.model, "consumablesIcon", response.data)
+    },
+    async onSuccessFile(response) {
+      this.$set(this.model, "attachment", response.data)
+    },
+    submit() {
+      this.$refs.modelForm.validate((valid) => {
+        if (valid) {
+          this.model.contentsId = this.model.contentId
+          if (this.model.id) {
+            this.$axios.post(updateProcurementSuppliesList, this.model, {
+              headers: {
+                'Content-Type': 'application/json'
+              }
+            }).then(res => {
+              if (res.code === 200) {
+                this.dialogVisible = false
+              }
+            })
+          } else {
+            this.$axios.post(addProcurementSuppliesList, this.model, {
+              headers: {
+                'Content-Type': 'application/json'
+              }
+            }).then(res => {
+              if (res.code === 200) {
+                this.dialogVisible = false
+                this.$emit('submit')
+              }
+            })
+          }
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+>>>.el-dialog {
+  margin: 6vh auto 50px !important;
+}
+>>> .el-dialog__body {
+  max-height: 42em;
+  overflow-y: auto;
+}
+.rows {
+  width: 100%;
+  display: flex;
+  justify-content: space-between;
+}
+>>>.el-form-item__content {
+  line-height: 39px;
+}
+</style>
diff --git a/src/components/do/a6.service-and-supply-purchase/contents.vue b/src/components/do/a6.service-and-supply-purchase/contents.vue
new file mode 100644
index 0000000..fcbf33c
--- /dev/null
+++ b/src/components/do/a6.service-and-supply-purchase/contents.vue
@@ -0,0 +1,297 @@
+<template>
+  <div class="parent-class">
+    <div style="display: flex; justify-content: flex-end; margin-right: 20px">
+      <el-button
+        type="primary"
+        @click="addContents"
+        size="small"
+        icon="el-icon-plus"
+        >娣诲姞瀛愯妭鐐�</el-button
+      >
+      <el-button
+        type="danger"
+        @click="deletetContents"
+        size="small"
+        icon="el-icon-delete"
+        >鍒犻櫎瀛愯妭鐐�</el-button
+      >
+      <el-button
+        type="warning"
+        @click="updateContents"
+        size="small"
+        icon="el-icon-edit"
+        >鏇存柊瀛愯妭鐐�</el-button
+      >
+    </div>
+    <el-form label-width="100px">
+      <el-form-item label="鑺傜偣鍚嶇О">
+        <el-input
+          v-model="form.nodeName"
+          style="width: 200px"
+          size="small"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="浠e彿">
+        <el-input
+          v-model="form.code"
+          style="width: 200px"
+          size="small"
+        ></el-input>
+      </el-form-item>
+    </el-form>
+
+    <!-- 鏂板寮规 -->
+    <el-dialog title="娣诲姞鑺傜偣" :visible.sync="dialogVisible" width="40%">
+      <el-form
+        label-width="100px"
+        :model="addForm"
+        ref="addForm"
+        :rules="rules"
+      >
+        <el-form-item label="鐖惰妭鐐瑰悕绉�">
+          <!-- <el-select v-model="addForm.parentId">
+              <el-option v-for="(item,index) in nodeNames" :key="index" :label="item.nodeName" :value="item.id"></el-option>
+            </el-select> -->
+          <el-cascader
+            v-model="addForm.parentId"
+            :options="treeData"
+            :props="{ checkStrictly: true, value: 'id', label: 'nodeName' }"
+            clearable
+          ></el-cascader>
+        </el-form-item>
+        <el-form-item label="鑺傜偣鍚嶇О" prop="nodeName">
+          <el-input
+            v-model="addForm.nodeName"
+            style="width: 200px"
+            size="small"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="浠e彿">
+          <el-input
+            v-model="addForm.code"
+            style="width: 200px"
+            size="small"
+          ></el-input>
+        </el-form-item>
+      </el-form>
+
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
+        <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+  <script>
+import {
+  suppliersDirectoryContentsAddSuppliersDirectoryContents,
+  suppliersDirectoryContentsUpdateSuppliersDirectoryContents,
+  suppliersDirectoryContentsDeleteSuppliersDirectoryContentsById,
+  suppliersDirectoryContentsGetSuppliersDirectoryContentsNodeNames
+} from '@/assets/api/api'
+export default {
+  props: {
+    id: {
+      type: Number,
+      default: 0,
+    },
+    treeData: {
+      type: Array,
+      default: () => [],
+    },
+    from: {
+      type: String,
+      default: "鑰楁潗鏍�"
+    }
+  },
+  data() {
+    return {
+      nodeNames: [],
+      users: [],
+      dialogVisible: false,
+      form: {
+        nodeName: "",
+        code: "",
+      },
+      addForm: {
+        nodeName: "",
+        code: "",
+        parentId: null,
+      },
+      rules: {
+        nodeName: [
+          { required: true, message: "璇疯緭鍏ヨ妭鐐瑰悕绉�", trigger: "blur" },
+        ],
+      },
+    };
+  },
+  mounted() {
+    if (this.id !== 0) {
+      this.getContentsDetail();
+    }
+    this.getNodeNames();
+    this.getUserList();
+  },
+  watch: {
+    id(newVal, oldVal) {
+      if (newVal !== 0) {
+        console.log(newVal, oldVal);
+        this.getContentsDetail();
+      }
+    },
+  },
+  methods: {
+    // 鑾峰彇鐩綍璇︽儏
+    getContentsDetail() {
+      this.$axios
+        .get(
+          this.from=='鑰楁潗鏍�'?(this.$api.procurementSuppliesContents.selectById + "?id=" + this.id):(this.$api.procurementSuppliesContents.selectSuppliersDirectoryContentsById + "?id=" + this.id)
+        )
+        .then((res) => {
+          if (res.data == null) {
+            this.form = {
+              nodeName: "",
+              code: "",
+            };
+            return;
+          }
+          this.form = res.data;
+        });
+    },
+    // 鏂板缓
+    addContents() {
+      this.dialogVisible = true;
+      this.resetForm();
+    },
+    resetForm() {
+      this.addForm = {
+        nodeName: "",
+        code: "",
+        parentId: null,
+      };
+    },
+    submitForm() {
+      let flag = true;
+      this.$refs.addForm.validate((valid) => {
+        if (!valid) {
+          flag = false;
+          return false;
+        }
+      });
+      if (this.addForm.parentId) {
+        this.addForm.parentId =
+          this.addForm.parentId[this.addForm.parentId.length - 1];
+      }
+      if (!flag) {
+        return;
+      }
+
+      this.$axios
+        .post(
+          this.from == '鑰楁潗鏍�'
+          ? this.$api.procurementSuppliesContents.add
+          : suppliersDirectoryContentsAddSuppliersDirectoryContents,
+          this.addForm,
+          {
+            headers: {
+              "Content-Type": "application/json",
+            },
+          }
+        )
+        .then((res) => {
+          if (res.code === 200) {
+            this.$message.success("娣诲姞鎴愬姛");
+            this.dialogVisible = false;
+            this.$emit("contentsUpdate", res.data);
+            this.getContentsDetail();
+          }
+        });
+    },
+    // 鏇存柊
+    updateContents() {
+      Object.keys(this.form).forEach((key) => {
+        if (key == "children") {
+          delete this.form[key];
+        }
+      });
+      this.$axios
+        .post(
+          this.from == '鑰楁潗鏍�'
+          ? this.$api.procurementSuppliesContents.update
+          : suppliersDirectoryContentsUpdateSuppliersDirectoryContents,
+
+          this.form,
+        {
+          headers: {
+            "Content-Type": "application/json",
+          },
+        })
+        .then((res) => {
+          if (res.code === 200) {
+            this.$message.success("鏇存柊鎴愬姛");
+            this.$emit("contentsUpdate", this.id);
+            this.dialogVisible = false;
+            this.getContentsDetail();
+          }
+        });
+    },
+    // 鍒犻櫎
+    deletetContents() {
+      if (
+        this.form.id == null ||
+        this.form.id == "" ||
+        this.form.id == undefined
+      ) {
+        this.$message.error("璇烽�夋嫨瑕佸垹闄ょ殑鑺傜偣");
+        return;
+      }
+      this.$confirm("姝ゆ搷浣滃皢鍒犻櫎璇ヨ妭鐐�, 鏄惁缁х画?", "鎻愮ず", {
+        confirmButtonText: "纭畾",
+        cancelButtonText: "鍙栨秷",
+        type: "warning",
+      }).then(() => {
+        this.$axios
+          .get(
+            this.from == '鑰楁潗鏍�'
+            ? `${this.$api.procurementSuppliesContents.deleteById}?id=${this.form.id}`
+            : `${suppliersDirectoryContentsDeleteSuppliersDirectoryContentsById}?id=${this.form.id}`
+          )
+          .then((res) => {
+            if (res.code == 200) {
+              this.$message.success("鍒犻櫎鎴愬姛");
+              this.$emit("contentsUpdate", this.form.parentId, true);
+              this.getContentsDetail();
+            }
+          });
+      });
+    },
+    // 鑾峰彇鎵�鏈夌洰褰曡妭鐐�
+    getNodeNames() {
+      this.$axios
+        .get(
+          this.from == '鑰楁潗鏍�'
+          ? this.$api.procurementSuppliesContents.getNodeNames
+          : suppliersDirectoryContentsGetSuppliersDirectoryContentsNodeNames
+        )
+        .then((res) => {
+          this.nodeNames = res.data;
+        });
+    },
+    // 鑾峰彇鎵�鏈夌敤鎴�
+    getUserList() {
+      this.$axios
+        .get(this.$api.procurementSuppliesContents.getUserList)
+        .then((res) => {
+          this.users = res.data;
+        });
+    },
+  },
+  created() {},
+};
+</script>
+
+  <style scoped>
+.parent-class {
+  margin-top: 20px;
+}
+</style>
diff --git a/src/components/view/a6-supplier-manage.vue b/src/components/view/a6-supplier-manage.vue
new file mode 100644
index 0000000..6e9bd37
--- /dev/null
+++ b/src/components/view/a6-supplier-manage.vue
@@ -0,0 +1,154 @@
+<template>
+    <div class="purchase-page">
+        <div class="purchase-left">
+            <el-input v-model="form.nodeName" placeholder="璇疯緭鍏ヨ妭鐐瑰悕绉�" suffix-icon="el-icon-search" size="small" clearable
+                @keyup.enter.native="searchFilter(treeData)" @blur="searchFilter(treeData)"
+                @clear="searchFilter(treeData)">
+            </el-input>
+            <el-tree ref="tree" :data="treeData" :props="defaultProps" @node-click="handleNodeClick"
+                :default-expanded-keys="expandedKeys" node-key="id">
+            </el-tree>
+        </div>
+        <div class="purchase-right">
+            <el-tabs v-model="activeName" @tab-click="handleClick" style="height: 100%;">
+                <el-tab-pane label="鎬昏" name="1" style="height: 100%;">
+                    <ConsumableOverview v-if="activeName == '1'" ref="consumableOverviewRef" :contentsId="contentsId" style="height: 100%;"></ConsumableOverview>
+                </el-tab-pane>
+                <el-tab-pane label="鍚堟牸渚涙柟鍚嶅綍" name="2">
+                    <QualifiedSuppliers v-if="activeName == '2'" :contentsId="contentsId"></QualifiedSuppliers>
+                </el-tab-pane>
+                <el-tab-pane label="鐩綍缁存姢" name="3">
+                    <Contents
+                        v-if="activeName == '3'"
+                        :id="contentsId"
+                        :treeData="treeData"
+                        @contentsUpdate="contentsUpdate"
+                        from="渚涘簲鏍�"
+                    ></Contents>
+                </el-tab-pane>
+            </el-tabs>
+        </div>
+    </div>
+</template>
+<script>
+import Contents from "@/components/do/a6.service-and-supply-purchase/contents.vue";
+import ConsumableOverview from "@/components/caorui/6-6/ConsumableOverview/index.vue";
+import QualifiedSuppliers from "@/components/caorui/6-6/QualifiedSuppliers/index.vue";
+import {suppliersDirectoryContentsSuppliersDirectoryContentsListing } from "@/assets/api/api";
+export default {
+    components: {
+        ConsumableOverview, QualifiedSuppliers, Contents
+    },
+    data() {
+        return {
+            contentsId: 0,
+            activeName: "1",
+            form: {
+                nodeName: "",
+            },
+            treeData: [],
+            expandedKeys: [],
+            defaultProps: {
+                children: "children",
+                label: "nodeName",
+            },
+        }
+    },
+    mounted() {
+        this.getTreeData();
+    },
+    methods: {
+        searchFilter() {
+            this.treeData = JSON.parse(JSON.stringify(this.treeData));
+            this.expandedKeys = [];
+            if (this.form.nodeName == "") {
+                return;
+            }
+            const findNodesWithFiber = (nodes) => {
+                nodes.forEach((node) => {
+                    if (node.nodeName && node.nodeName.includes(this.form.nodeName)) {
+                        this.expandedKeys.push(node.id);
+                    }
+                    if (node.children && node.children.length > 0) {
+                        findNodesWithFiber(node.children);
+                    }
+                });
+            };
+            findNodesWithFiber(this.treeData);
+        },
+        // 鐩綍缁存姢鏇存柊
+        contentsUpdate(val, flag = false) {
+            if (val) {
+                this.getTreeData();
+                this.expandedKeys = [];
+                if (flag) {
+                    const findNodesWithFiber = (nodes) => {
+                        nodes.forEach((item) => {
+                            if (item.parentId == val) {
+                                this.expandedKeys.push(item.id);
+                            }
+                            if (item.children && item.children.length > 0) {
+                                findNodesWithFiber(item.children);
+                            }
+                        });
+                    };
+                    findNodesWithFiber(this.treeData);
+                    this.expandedKeys = this.expandedKeys.filter((item) => item !== val);
+                } else {
+                    this.expandedKeys.push(val);
+                }
+            } else {
+                this.getTreeData();
+            }
+        },
+        // 鏌ヨ鎵�鏈夌洰褰�
+        getTreeData() {
+            this.$axios
+                .get(suppliersDirectoryContentsSuppliersDirectoryContentsListing)
+                .then((res) => {
+                    this.treeData = res.data;
+                });
+        },
+        // 鐐瑰嚮鏍戣妭鐐�
+        handleNodeClick(data) {
+            this.contentsId = data.id;
+            // this.$refs.consumableOverviewRef.getTableData(data.id)
+        },
+        handleClick(tab, event) {
+        },
+    }
+}
+</script>
+
+<style scoped>
+.purchase-left {
+    width: 250px;
+    height: 100%;
+    background: #fff;
+    margin-right: 10px;
+    border-radius: 16px;
+    box-sizing: border-box;
+    padding: 10px 16px;
+    flex-shrink: 0;
+}
+
+.purchase-right {
+    background: #fff;
+    width: calc(100% - 15em);
+    height: 100%;
+    border-radius: 16px;
+    box-sizing: border-box;
+    padding: 10px 16px;
+}
+
+.purchase-page {
+    display: flex;
+    padding-top: 10px;
+    padding-bottom: 10px;
+    box-sizing: border-box;
+    width: 100%;
+}
+>>>.el-tabs__content{
+  height: calc(100% - 40px);
+}
+</style>
diff --git a/src/components/view/a6.service-and-supply-purchase.vue b/src/components/view/a6.service-and-supply-purchase.vue
new file mode 100644
index 0000000..718621f
--- /dev/null
+++ b/src/components/view/a6.service-and-supply-purchase.vue
@@ -0,0 +1,178 @@
+<template>
+  <div class="purchase-page">
+    <div class="purchase-left">
+      <el-input
+        v-model="form.nodeName"
+        placeholder="璇疯緭鍏ヨ妭鐐瑰悕绉�"
+        suffix-icon="el-icon-search"
+        size="small"
+        clearable
+        @keyup.enter.native="searchFilter(treeData)"
+        @blur="searchFilter(treeData)"
+        @clear="searchFilter(treeData)"
+      >
+      </el-input>
+      <el-tree
+        ref="tree"
+        :data="treeData"
+        :props="defaultProps"
+        @node-click="handleNodeClick"
+        :default-expanded-keys="expandedKeys"
+        node-key="id"
+      >
+      </el-tree>
+    </div>
+    <div class="purchase-right">
+      <el-tabs v-model="activeName" @tab-click="handleClick">
+        <el-tab-pane label="鑰楁潗鎬昏" name="first" :lazy="true">
+          <ConsumableOverview v-if="activeName == 'first'" :contentsId="contentsId"></ConsumableOverview>
+        </el-tab-pane>
+        <el-tab-pane label="鑰楁潗鍒楄〃" name="second" :lazy="true">
+          <ConsumableList v-if="activeName == 'second'" :contentsId="contentsId"></ConsumableList>
+        </el-tab-pane>
+        <el-tab-pane label="鑰楁潗鍏ュ簱" name="third" :lazy="true">
+          <Store v-if="activeName == 'third'" :contentsId="contentsId"></Store>
+        </el-tab-pane>
+        <el-tab-pane label="鐩綍缁存姢" name="fourth" :lazy="true">
+          <Contents
+            v-if="activeName == 'fourth'"
+            :id="contentsId"
+            @contentsUpdate="contentsUpdate"
+            :treeData="treeData"
+            from="鑰楁潗鏍�"
+          ></Contents>
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+  </div>
+</template>
+<script>
+import Contents from "@/components/do/a6.service-and-supply-purchase/contents.vue";
+import Store from "@/components/do/a6.service-and-supply-purchase/store.vue";
+import ConsumableOverview from "@/components/do/a6.service-and-supply-purchase/ConsumableOverview.vue";
+import ConsumableList from "@/components/do/a6.service-and-supply-purchase/ConsumableList.vue"
+
+export default {
+  data() {
+    return {
+      tabsKey: 0,
+      contentsId: 0,
+      activeName: "first",
+      form: {
+        nodeName: "",
+      },
+      treeData: [],
+      expandedKeys: [],
+      defaultProps: {
+        children: "children",
+        label: "nodeName",
+      },
+    };
+  },
+  components: {
+    Contents,
+    Store,
+    ConsumableOverview,
+    ConsumableList
+  },
+  watch: {
+    contentsId(newVal, oldVal) {
+      if(newVal != oldVal) {
+        this.tabsKey = Math.random();
+      }
+    }
+  },
+  methods: {
+    searchFilter() {
+      this.treeData = JSON.parse(JSON.stringify(this.treeData));
+      this.expandedKeys = [];
+      if(this.form.nodeName == "") {
+        return;
+      }
+      const findNodesWithFiber = (nodes) => {
+        nodes.forEach((node) => {
+          if (node.nodeName && node.nodeName.includes(this.form.nodeName)) {
+            this.expandedKeys.push(node.id);
+          }
+          if (node.children && node.children.length > 0) {
+            findNodesWithFiber(node.children);
+          }
+        });
+      };
+      findNodesWithFiber(this.treeData);
+    },
+
+    // 鐩綍缁存姢鏇存柊
+    contentsUpdate(val, flag = false) {
+      if (val) {
+        this.getTreeData();
+        this.expandedKeys = [];
+        if (flag) {
+          const findNodesWithFiber = (nodes) => {
+            nodes.forEach((item) => {
+              if (item.parentId == val) {
+                this.expandedKeys.push(item.id);
+              }
+              if(item.children && item.children.length > 0) {
+                findNodesWithFiber(item.children);
+              }
+            });
+          };
+          findNodesWithFiber(this.treeData);
+          this.expandedKeys = this.expandedKeys.filter((item) => item !== val);
+        } else {
+          this.expandedKeys.push(val);
+        }
+      }else {
+        this.getTreeData();
+      }
+    },
+    // 鏌ヨ鎵�鏈夌洰褰�
+    getTreeData() {
+      this.$axios
+        .get(this.$api.procurementSuppliesContents.directoryListing)
+        .then((res) => {
+          this.treeData = res.data;
+        });
+    },
+    // 鐐瑰嚮鏍戣妭鐐�
+    handleNodeClick(data) {
+      this.contentsId = data.id;
+    },
+    handleClick(tab, event) {
+      console.log(tab, event);
+    },
+  },
+  created() {
+    this.getTreeData();
+  },
+};
+</script>
+
+<style scoped>
+.purchase-left {
+  width: 250px;
+  height: 100%;
+  background: #fff;
+  margin-right: 10px;
+  border-radius: 16px;
+  box-sizing: border-box;
+  padding: 10px 16px;
+  flex-shrink: 0;
+}
+.purchase-right {
+  background: #fff;
+  width: calc(100% - 15em);
+  height: 100%;
+  border-radius: 16px;
+  box-sizing: border-box;
+  padding: 10px 16px;
+}
+.purchase-page {
+  display: flex;
+  padding-top: 10px;
+  padding-bottom: 10px;
+  box-sizing: border-box;
+  width: 100%;
+}
+</style>
diff --git a/src/main.js b/src/main.js
index 2e86d84..548dc3a 100644
--- a/src/main.js
+++ b/src/main.js
@@ -29,8 +29,8 @@
 // const javaApi = 'http://10.1.13.77:8001';
 
 // 閫氫俊姝e紡搴�
-Vue.prototype.LOCATIONVUE = "http://10.193.45.63:8080";
-const javaApi = 'https://ztwxlims.ztt.cn:7443/lims/';
+// Vue.prototype.LOCATIONVUE = "http://10.193.45.63:8080";
+// const javaApi = 'https://ztwxlims.ztt.cn:7443/lims/';
 
 // //浜�
 // Vue.prototype.LOCATIONVUE = "http://114.132.189.42:8080";

--
Gitblit v1.9.3