Bläddra i källkod

Merge branch 'purchaseDev' of http://172.16.100.139/new-business/drp-web into purchaseDev

002390 2 år sedan
förälder
incheckning
a96ed98596
57 ändrade filer med 5145 tillägg och 1390 borttagningar
  1. 60 0
      src/api/business/purchase/apply.js
  2. 60 0
      src/api/business/purchase/catalogue.js
  3. 6 6
      src/api/business/purchase/contract.js
  4. 0 10
      src/api/business/purchase/purchase-task.js
  5. 27 0
      src/api/business/purchase/task.js
  6. 0 0
      src/components/input-dialog/api/index.js
  7. 0 0
      src/components/input-dialog/components/ALLOCATION_PARAM.js
  8. 0 0
      src/components/input-dialog/components/BALATYPE_PARAM.js
  9. 0 0
      src/components/input-dialog/components/CURRENCY_PARAM.js
  10. 0 0
      src/components/input-dialog/components/CUSTOMERDEPT_PARAM.js
  11. 0 0
      src/components/input-dialog/components/CUSTOMER_PARAM.js
  12. 0 0
      src/components/input-dialog/components/DEPT_PARAM.js
  13. 0 0
      src/components/input-dialog/components/MATERIAL_PARAM.js
  14. 0 0
      src/components/input-dialog/components/OPERATING_PARAM.js
  15. 0 0
      src/components/input-dialog/components/ORG_PARAM.js
  16. 0 0
      src/components/input-dialog/components/PAYAGREEMENT_PARAM.js
  17. 0 0
      src/components/input-dialog/components/PROCESSTYPE_PARAM.js
  18. 0 0
      src/components/input-dialog/components/PROJECT_PARAM.js
  19. 0 0
      src/components/input-dialog/components/RETREASON_PARAM.js
  20. 0 0
      src/components/input-dialog/components/SUPPLIERCONTACTS_PARAM.js
  21. 0 0
      src/components/input-dialog/components/SUPPLIER_PARAM.js
  22. 0 0
      src/components/input-dialog/components/WAREHOUSE_PARAM.js
  23. 14 12
      src/components/input-dialog/components/index.vue
  24. 0 0
      src/components/input-dialog/components/init-column.js
  25. 53 31
      src/components/input-dialog/index.vue
  26. 1 1
      src/views/purchase/apply/add/column.js
  27. 2 2
      src/views/purchase/apply/add/index.vue
  28. 50 0
      src/views/purchase/apply/column.js
  29. 8 10
      src/views/purchase/apply/edit/index.vue
  30. 194 0
      src/views/purchase/apply/index.vue
  31. 1 1
      src/views/purchase/apply/see/index.vue
  32. 514 0
      src/views/purchase/catalogue/add/column.js
  33. 380 0
      src/views/purchase/catalogue/add/index.vue
  34. 61 0
      src/views/purchase/catalogue/column.js
  35. 399 0
      src/views/purchase/catalogue/edit/index.vue
  36. 194 0
      src/views/purchase/catalogue/index.vue
  37. 317 0
      src/views/purchase/catalogue/see/index.vue
  38. 514 0
      src/views/purchase/contract/add/column.js
  39. 380 0
      src/views/purchase/contract/add/index.vue
  40. 0 0
      src/views/purchase/contract/column.js
  41. 399 0
      src/views/purchase/contract/edit/index.vue
  42. 35 19
      src/views/purchase/contract/index.vue
  43. 317 0
      src/views/purchase/contract/see/index.vue
  44. 3 3
      src/views/purchase/purchase-content/index.vue
  45. 1 1
      src/views/purchase/purchase-order/add/index.vue
  46. 1 1
      src/views/purchase/purchase-order/edit/index.vue
  47. 0 151
      src/views/purchase/purchase-task/add-purchase-task.vue
  48. 0 386
      src/views/purchase/purchase-task/direct-sourcing.vue
  49. 0 598
      src/views/purchase/purchase-task/index.vue
  50. 0 158
      src/views/purchase/purchase-task/see-purchase-task.vue
  51. 48 0
      src/views/purchase/task/column.js
  52. 0 0
      src/views/purchase/task/config/add.js
  53. 49 0
      src/views/purchase/task/first-direct/column.js
  54. 167 0
      src/views/purchase/task/first-direct/index.vue
  55. 262 0
      src/views/purchase/task/index.vue
  56. 514 0
      src/views/purchase/task/see/column.js
  57. 114 0
      src/views/purchase/task/see/index.vue

+ 60 - 0
src/api/business/purchase/apply.js

@@ -0,0 +1,60 @@
+import request from "@/utils/request";
+
+export function list(params) {
+  return request({
+    url: "/pu/priceApply/list",
+    method: "GET",
+    params: params,
+  });
+}
+
+export function add(data) {
+  return request({
+    url: "/pu/contract/add",
+    method: "POST",
+    data: data,
+  });
+}
+
+export function edit(data) {
+  return request({
+    url: "/pu/contract/edit",
+    method: "POST",
+    data: data,
+  });
+}
+
+export function remove(data) {
+  return request({
+    url: `/pu/contract/${data}`,
+    method: "delete",
+  });
+}
+
+export function item(data) {
+  return request({
+    url: `/pu/contract/${data}`,
+    method: "GET",
+  });
+}
+
+export function generateCode() {
+  return request({
+    url: "/pu/contract/generateNo",
+    method: "GET",
+  });
+}
+
+export function itemTableList(params, name) {
+  let url = "";
+  if (name === "contractItemList") url = "/pu/contract/item/list";
+  if (name === "contractClauseList") url = "/pu/contract/clause/list";
+  if (name === "contractExpenseList") url = "/pu/contract/expense/list";
+  if (name === "contractAgreementList") url = "/pu/contract/agreement/list";
+  if (name === "contractApplyOrgList") url = "/pu/contract/org/list";
+  return request({
+    url: url,
+    method: "GET",
+    params: params,
+  });
+}

+ 60 - 0
src/api/business/purchase/catalogue.js

@@ -0,0 +1,60 @@
+import request from "@/utils/request";
+
+export function list(params) {
+  return request({
+    url: "/pu/price/catalogue/list",
+    method: "GET",
+    params: params,
+  });
+}
+
+export function add(data) {
+  return request({
+    url: "/pu/contract/add",
+    method: "POST",
+    data: data,
+  });
+}
+
+export function edit(data) {
+  return request({
+    url: "/pu/contract/edit",
+    method: "POST",
+    data: data,
+  });
+}
+
+export function remove(data) {
+  return request({
+    url: `/pu/contract/${data}`,
+    method: "delete",
+  });
+}
+
+export function item(data) {
+  return request({
+    url: `/pu/contract/${data}`,
+    method: "GET",
+  });
+}
+
+export function generateCode() {
+  return request({
+    url: "/pu/contract/generateNo",
+    method: "GET",
+  });
+}
+
+export function itemTableList(params, name) {
+  let url = "";
+  if (name === "contractItemList") url = "/pu/contract/item/list";
+  if (name === "contractClauseList") url = "/pu/contract/clause/list";
+  if (name === "contractExpenseList") url = "/pu/contract/expense/list";
+  if (name === "contractAgreementList") url = "/pu/contract/agreement/list";
+  if (name === "contractApplyOrgList") url = "/pu/contract/org/list";
+  return request({
+    url: url,
+    method: "GET",
+    params: params,
+  });
+}

+ 6 - 6
src/api/business/purchase/purchase-contract.js → src/api/business/purchase/contract.js

@@ -3,7 +3,7 @@ import request from "@/utils/request";
 export function list(params) {
   return request({
     url: "/pu/contract/list",
-    method: "get",
+    method: "GET",
     params: params,
   });
 }
@@ -11,7 +11,7 @@ export function list(params) {
 export function add(data) {
   return request({
     url: "/pu/contract/add",
-    method: "post",
+    method: "POST",
     data: data,
   });
 }
@@ -19,7 +19,7 @@ export function add(data) {
 export function edit(data) {
   return request({
     url: "/pu/contract/edit",
-    method: "post",
+    method: "POST",
     data: data,
   });
 }
@@ -34,14 +34,14 @@ export function remove(data) {
 export function item(data) {
   return request({
     url: `/pu/contract/${data}`,
-    method: "get",
+    method: "GET",
   });
 }
 
 export function generateCode() {
   return request({
     url: "/pu/contract/generateNo",
-    method: "get",
+    method: "GET",
   });
 }
 
@@ -54,7 +54,7 @@ export function itemTableList(params, name) {
   if (name === "contractApplyOrgList") url = "/pu/contract/org/list";
   return request({
     url: url,
-    method: "get",
+    method: "GET",
     params: params,
   });
 }

+ 0 - 10
src/api/business/purchase/purchase-task.js

@@ -1,10 +0,0 @@
-import request from "@/utils/request";
-
-// 查询任务列表
-export function taskList(data) {
-  return request({
-    url: "/pu/order/generate/list",
-    method: "POST",
-    data: data,
-  });
-}

+ 27 - 0
src/api/business/purchase/task.js

@@ -0,0 +1,27 @@
+import request from "@/utils/request";
+
+// 查询任务列表
+export function list(data) {
+  return request({
+    url: "/pu/order/generate/list",
+    method: "POST",
+    data: data,
+  });
+}
+
+// 查询任务列表
+export function item(data) {
+  return request({
+    url: `/pu/order/generate/${data}`,
+    method: "GET",
+  });
+}
+
+// 查询任务列表
+export function FirstDirect(data) {
+  return request({
+    url: "/pu/order/generate/manualAgreement",
+    method: "POST",
+    data: data,
+  });
+}

+ 0 - 0
src/views/input-dialog/api/index.js → src/components/input-dialog/api/index.js


+ 0 - 0
src/views/input-dialog/components/ALLOCATION_PARAM.js → src/components/input-dialog/components/ALLOCATION_PARAM.js


+ 0 - 0
src/views/input-dialog/components/BALATYPE_PARAM.js → src/components/input-dialog/components/BALATYPE_PARAM.js


+ 0 - 0
src/views/input-dialog/components/CURRENCY_PARAM.js → src/components/input-dialog/components/CURRENCY_PARAM.js


+ 0 - 0
src/views/input-dialog/components/CUSTOMERDEPT_PARAM.js → src/components/input-dialog/components/CUSTOMERDEPT_PARAM.js


+ 0 - 0
src/views/input-dialog/components/CUSTOMER_PARAM.js → src/components/input-dialog/components/CUSTOMER_PARAM.js


+ 0 - 0
src/views/input-dialog/components/DEPT_PARAM.js → src/components/input-dialog/components/DEPT_PARAM.js


+ 0 - 0
src/views/input-dialog/components/MATERIAL_PARAM.js → src/components/input-dialog/components/MATERIAL_PARAM.js


+ 0 - 0
src/views/input-dialog/components/OPERATING_PARAM.js → src/components/input-dialog/components/OPERATING_PARAM.js


+ 0 - 0
src/views/input-dialog/components/ORG_PARAM.js → src/components/input-dialog/components/ORG_PARAM.js


+ 0 - 0
src/views/input-dialog/components/PAYAGREEMENT_PARAM.js → src/components/input-dialog/components/PAYAGREEMENT_PARAM.js


+ 0 - 0
src/views/input-dialog/components/PROCESSTYPE_PARAM.js → src/components/input-dialog/components/PROCESSTYPE_PARAM.js


+ 0 - 0
src/views/input-dialog/components/PROJECT_PARAM.js → src/components/input-dialog/components/PROJECT_PARAM.js


+ 0 - 0
src/views/input-dialog/components/RETREASON_PARAM.js → src/components/input-dialog/components/RETREASON_PARAM.js


+ 0 - 0
src/views/input-dialog/components/SUPPLIERCONTACTS_PARAM.js → src/components/input-dialog/components/SUPPLIERCONTACTS_PARAM.js


+ 0 - 0
src/views/input-dialog/components/SUPPLIER_PARAM.js → src/components/input-dialog/components/SUPPLIER_PARAM.js


+ 0 - 0
src/views/input-dialog/components/WAREHOUSE_PARAM.js → src/components/input-dialog/components/WAREHOUSE_PARAM.js


+ 14 - 12
src/views/input-dialog/components/index.vue → src/components/input-dialog/components/index.vue

@@ -1,11 +1,11 @@
 <script>
 import { refer } from "../api/index";
-import InitColumnHooks from "./init-column";
 import { initParams } from "@/utils/init";
+import InitColumnHooks from "./init-column";
 
 export default {
   name: "InputDialog",
-  props: ["title", "type"],
+  props: ["type", "title", "queryParams"],
   components: {},
   data() {
     const { type } = this.$props;
@@ -22,7 +22,7 @@ export default {
       visible: false,
       loading: false,
       // search
-      params: initParams(SearchColumns),
+      params: { search: "" },
       searchColumns: SearchColumns,
       // table
       data: [],
@@ -45,13 +45,14 @@ export default {
     async fetchList(prop, page) {
       try {
         this.loading = true;
-        const { type } = this.$props;
         const { pageNum, pageSize } = page;
+        const { type, queryParams } = this.$props;
         const { code, msg, rows, total } = await refer(
           {
-            ...prop,
             type: type,
             isPage: true,
+            ...prop,
+            ...queryParams,
           },
           { pageNum, pageSize }
         );
@@ -117,13 +118,14 @@ export default {
     append-to-body
     @open="beforeOpen"
   >
-    <el-form :size="size" :inline="true" :model="params">
-      <el-form-item
-        v-for="(column, index) in searchColumns"
-        :key="index"
-        :label="column.title"
-      >
-        <el-input v-model="params[column.key]" @change="queryList"> </el-input>
+    <el-form :size="size" :inline="true" :model="params" @submit.native.prevent>
+      <el-form-item prop="search">
+        <el-input
+          v-model="params.search"
+          @keydown.enter="queryList"
+          @change="queryList"
+        >
+        </el-input>
       </el-form-item>
       <el-form-item>
         <el-button icon="el-icon-refresh" @click="resetList"></el-button>

+ 0 - 0
src/views/input-dialog/components/init-column.js → src/components/input-dialog/components/init-column.js


+ 53 - 31
src/views/input-dialog/index.vue → src/components/input-dialog/index.vue

@@ -1,18 +1,48 @@
 <script>
 export default {
   name: "DrInputDialog",
-  props: [
-    "value",
-    "title",
-    "type",
-    "dataMapping",
-    "source",
-    "placeholder",
-    "clearable",
-    "disabled",
-    "readonly",
-    "size",
-  ],
+  props: {
+    // 参照类型 ,对应后端
+    type: {
+      type: String,
+      require: true,
+    },
+    // Input显示数据
+    value: {
+      type: String,
+      require: true,
+    },
+    // 需映射源数据
+    source: {
+      type: Object,
+      require: true,
+    },
+    // 参照内外映射
+    dataMapping: {
+      type: Object,
+      require: true,
+    },
+    // 参照弹窗标题
+    title: {
+      type: String,
+      default: "TITLE",
+    },
+    // 默认查询参数
+    queryParams: {
+      type: Object,
+      default: () => ({}),
+    },
+    //
+    size: String,
+    //
+    readonly: Boolean,
+    //
+    disabled: Boolean,
+    //
+    clearable: Boolean,
+    //
+    placeholder: String,
+  },
   components: {
     InputDialog: () => import("./components/index.vue"),
   },
@@ -22,27 +52,23 @@ export default {
   computed: {},
   watch: {},
   methods: {
+    // 打开弹窗
     handleAsyncOpenDialog() {
       this.$nextTick(() => {
         const { setVisible } = this.$refs.InputDialogFef;
         setVisible(true);
       });
     },
+    // 更新映射数据
     handleUpdateSource(prop) {
       const { source, dataMapping } = this.$props;
       for (let key in dataMapping) {
         source[key] = prop[dataMapping[key]];
       }
       this.$emit("update:source", source);
-      console.log("type", this.$props.type);
-      console.log("dataMapping", dataMapping);
-      console.log("prop", prop);
-      console.log("source", this.$props.source);
     },
   },
-  created() {
-    console.log("prop", this.$props);
-  },
+  created() {},
   mounted() {},
   destroyed() {},
 };
@@ -50,28 +76,24 @@ export default {
 <template>
   <el-input
     v-model="value"
-    :placeholder="placeholder"
-    :clearable="clearable"
-    :disabled="disabled"
-    :readonly="readonly"
     :size="size"
+    :readonly="readonly"
+    :disabled="disabled"
+    :clearable="clearable"
+    :placeholder="placeholder"
     style="width: 100%; cursor: pointer"
     @click.native.stop="handleAsyncOpenDialog"
   >
     <template #suffix>
-      <el-icon class="el-icon-thumb"></el-icon>
+      <el-icon class="el-icon-milk-tea"></el-icon>
       <input-dialog
         ref="InputDialogFef"
-        :title="title"
         :type="type"
+        :title="title"
+        :queryParams="queryParams"
         @confirm="handleUpdateSource"
       ></input-dialog>
     </template>
   </el-input>
 </template>
-<style scoped>
-::v-deep.el-input .el-input__suffix {
-  display: flex;
-  align-items: center;
-}
-</style>
+<style scoped></style>

+ 1 - 1
src/views/purchase/purchase-contract/add/column.js → src/views/purchase/apply/add/column.js

@@ -433,7 +433,7 @@ export const TabColumns = [
         type: "InputDialog",
         width: 200,
         config: {
-          componentName: "MATERIAL_PARAM",
+          componentName: "SUPPLIER_PARAM",
           dataMapping: {
             material: "code",
             materialName: "name",

+ 2 - 2
src/views/purchase/purchase-contract/add/index.vue → src/views/purchase/apply/add/index.vue

@@ -1,6 +1,6 @@
 <script>
 import { Columns, TabColumns } from "./column";
-import { add, generateCode } from "@/api/business/purchase/purchase-contract";
+import { add, generateCode } from "@/api/business/purchase/contract";
 import { initColumns, initDicts, initRules, initParams } from "@/utils/init";
 
 const NewColumns = initColumns(Columns);
@@ -13,7 +13,7 @@ export default {
   name: "AddDrawer",
   dicts: initDicts(NewColumns),
   components: {
-    DrInputDialog: () => import("@/views/input-dialog/index.vue"),
+    DrInputDialog: () => import("@/components/input-dialog/index.vue"),
   },
   data() {
     return {

+ 50 - 0
src/views/purchase/apply/column.js

@@ -0,0 +1,50 @@
+export const TableColumns = [
+  { key: "id", title: "id" },
+  { key: "status", title: "单据状态" },
+  { key: "priceName", title: "价格名称" },
+  { key: "supplier", title: "供应商" },
+  {
+    key: "supplierName",
+    title: "供应商名称",
+    search: true,
+    config: {
+      componentName: "SUPPLIER_PARAM",
+      dataMapping: {
+        supplier: "code",
+        supplierName: "name",
+      },
+    },
+  },
+  { key: "puOrg", title: "采购组织" },
+  {
+    key: "puOrgName",
+    title: "采购组织名称",
+    search: true,
+    config: {
+      componentName: "ORG_PARAM",
+      dataMapping: {
+        puOrg: "code",
+        puOrgName: "name",
+      },
+    },
+  },
+  { key: "currency", title: "币种" },
+  { key: "currencyName", title: "币种名称" },
+  { key: "explain", title: "价格合理性说明" },
+  { key: "buyer", title: "采购员" },
+  { key: "buyerName", title: "采购员名称" },
+  { key: "puDept", title: "采购部门" },
+  { key: "puDeptName", title: "采购部门名称" },
+  { key: "sourceType", title: "来源单据类型" },
+  { key: "source", title: "来源单据号" },
+  { key: "isEffective", title: "是否已推价格" },
+  { key: "effectiveDate", title: "生效日期" },
+  { key: "file", title: "附件" },
+  { key: "tenantId", title: "租户号" },
+  { key: "revision", title: "乐观锁" },
+  { key: "createByName", title: "创建人名称" },
+  { key: "updateByName", title: "更新人" },
+  { key: "delFlag", title: "删除标记" },
+];
+
+export const SearchColumns = TableColumns.filter((element) => element.search);

+ 8 - 10
src/views/purchase/purchase-contract/edit/index.vue → src/views/purchase/apply/edit/index.vue

@@ -4,7 +4,7 @@ import {
   edit,
   item,
   itemTableList,
-} from "@/api/business/purchase/purchase-contract";
+} from "@/api/business/purchase/contract";
 import { initColumns, initDicts, initRules, initParams } from "@/utils/init";
 
 const NewColumns = initColumns(Columns);
@@ -17,7 +17,7 @@ export default {
   name: "EditDrawer",
   dicts: initDicts(NewColumns),
   components: {
-    DrInputDialog: () => import("@/views/input-dialog/index.vue"),
+    DrInputDialog: () => import("@/components/input-dialog/index.vue"),
   },
   data() {
     return {
@@ -204,15 +204,14 @@ export default {
               <dr-input-dialog
                 v-if="column.type === 'InputDialog'"
                 v-model="params[column.key]"
-                :placeholder="column.placeholder"
-                :clearable="column.clearable"
-                :disabled="column.disabled"
-                :readonly="column.readonly"
-
-                :title="column.title"
+                :source.sync="params"
                 :type="column.config.componentName"
                 :data-mapping="column.config.dataMapping"
-                :source.sync="params"
+                :title="column.title"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                :clearable="column.clearable"
+                :placeholder="column.placeholder"
               >
               </dr-input-dialog>
               <el-input
@@ -355,7 +354,6 @@ export default {
                     :clearable="cColumn.clearable"
                     :disabled="cColumn.disabled"
                     :readonly="cColumn.readonly"
-                    
                     :title="cColumn.title"
                     :type="cColumn.config.componentName"
                     :data-mapping="cColumn.config.dataMapping"

+ 194 - 0
src/views/purchase/apply/index.vue

@@ -0,0 +1,194 @@
+<script>
+import { TableColumns, SearchColumns } from "./column";
+import { list, remove } from "@/api/business/purchase/apply";
+import { initPage, initLayout, initPageSizes, initParams } from "@/utils/init";
+export default {
+  name: "PuchaseContract",
+  components: {
+    AddDrawer: () => import("./add/index.vue"),
+    SeeDrawer: () => import("./see/index.vue"),
+    EditDrawer: () => import("./edit/index.vue"),
+  },
+  data() {
+    return {
+      size: "mini",
+      loading: false,
+      searchColumns: SearchColumns,
+      params: initParams(SearchColumns),
+      tableData: [],
+      tableColumns: TableColumns,
+      page: initPage(),
+      layout: initLayout(),
+      pageSizes: initPageSizes(),
+    };
+  },
+  computed: {},
+  created() {
+    this.handleQueryList();
+  },
+  methods: {
+    //
+    async fetchList(params, page) {
+      try {
+        this.loading = true;
+        const { pageNum, pageSize } = page;
+        const { code, msg, rows, total } = await list({
+          pageNum,
+          pageSize,
+          ...params,
+        });
+        if (code === 200) {
+          this.tableData = rows;
+          this.page.total = total;
+          this.$notify.success({ title: msg });
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    // 查询操作
+    handleQueryList() {
+      this.fetchList(this.params, this.page);
+    },
+    // 重置操作
+    handleResetList() {
+      this.page = initPage();
+      this.params = initParams(SearchColumns);
+      this.fetchList(this.params, this.page);
+    },
+    // 删除操作
+    async handleDeleteList(prop) {
+      try {
+        this.loading = true;
+        const { id } = prop;
+        const { code, msg } = await remove(id);
+        if (code === 200) {
+          this.$notify.success({ title: msg });
+          this.fetchList(this.params, this.page);
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    // 页大小变
+    handleSizeChange(prop) {
+      this.page.pageSize = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // 当前页变
+    handleCurrentChange(prop) {
+      this.page.pageNum = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // 打开新增drawer
+    handleOpenAddDrawer() {
+      console.log(this.$refs.AddDrawerFef);
+      const { setVisible } = this.$refs.AddDrawerFef;
+      setVisible(true);
+    },
+    // 打开查看drawer
+    async handleOpenSeeDrawer(prop) {
+      const { id } = prop;
+      const { setVisible, fetchItem } = this.$refs.SeeDrawerFef;
+      await setVisible(true);
+      await fetchItem(id);
+    },
+    // 打开编辑drawer
+    async handleOpenEditDrawer(prop) {
+      const { id } = prop;
+      const { setVisible, fetchItem } = this.$refs.EditDrawerFef;
+      await setVisible(true);
+      await fetchItem(id);
+    },
+  },
+};
+</script>
+
+<template>
+  <el-card
+    v-loading="loading"
+    style="width: calc(100% - 24px); height: 100%; margin: 10px"
+    :body-style="{ padding: 0 }"
+  >
+    <see-drawer ref="SeeDrawerFef"></see-drawer>
+    <add-drawer ref="AddDrawerFef" @close="handleResetList"></add-drawer>
+    <edit-drawer ref="EditDrawerFef" @close="handleResetList"></edit-drawer>
+    <el-form :size="size" label-position="top" :model="params">
+      <el-row :gutter="24" style="padding: 0 20px">
+        <el-col
+          v-for="column in searchColumns"
+          :key="column.title"
+          :xl="4"
+          :lg="4"
+          :md="8"
+          :sm="12"
+          :xs="24"
+        >
+          <el-form-item :prop="column.key" :label="column.title">
+            <el-input
+              v-model="params[column.key]"
+              :placeholder="column.placeholder"
+            ></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :xl="6" :lg="6" :md="8" :sm="12" :xs="24"> </el-col>
+      </el-row>
+    </el-form>
+    <el-row :gutter="24" style="padding: 0 20px">
+      <el-col :span="24">
+        <el-button :size="size" icon="el-icon-search" @click="handleQueryList"
+          >搜索</el-button
+        >
+        <el-button :size="size" icon="el-icon-refresh" @click="handleResetList"
+          >重置</el-button
+        >
+      </el-col>
+    </el-row>
+    <el-table
+      @row-dblclick="handleOpenSeeDrawer"
+      :data="tableData"
+      :size="size"
+      style="width: 100%; margin: 20px 0 0 0"
+    >
+      <el-table-column
+        v-for="(column, index) in tableColumns"
+        :key="index"
+        :prop="column.key"
+        :label="column.title"
+        :width="column.width || 180"
+        :show-overflow-tooltip="column.showOverflowTooltip || true"
+      >
+      </el-table-column>
+      <el-table-column fixed="right" label="操作" width="120">
+        <template slot-scope="scope">
+          <el-button
+            @click.native.prevent="handleDeleteList(scope.row)"
+            type="text"
+            size="small"
+          >
+            删 除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <el-pagination
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+      :total="page.total"
+      :page-sizes="pageSizes"
+      :page-size="page.pageSize"
+      :current-page="page.pageNum"
+      :layout="layout"
+      style="margin: 16px 0"
+    >
+    </el-pagination>
+  </el-card>
+</template>

+ 1 - 1
src/views/purchase/purchase-contract/see/index.vue → src/views/purchase/apply/see/index.vue

@@ -1,6 +1,6 @@
 <script>
 import { Columns, TabColumns } from "../add/column";
-import { item, itemTableList } from "@/api/business/purchase/purchase-contract";
+import { item, itemTableList } from "@/api/business/purchase/contract";
 import { initColumns, initDicts, initRules, initParams } from "@/utils/init";
 
 const NewColumns = initColumns(Columns, { disabled: true, readonly: true });

+ 514 - 0
src/views/purchase/catalogue/add/column.js

@@ -0,0 +1,514 @@
+export const Columns = [
+  {
+    key: "puOrgName",
+    title: "采购组织",
+    type: "InputDialog",
+    config: {
+      componentName: "ORG_PARAM",
+      dataMapping: {
+        puOrg: "code",
+        puOrgName: "name",
+      },
+    },
+    require: true,
+  },
+  { key: "code", title: "合同编码", type: "Input" },
+  {
+    key: "lastPuMoney",
+    title: "上年度采购额",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "buyerName",
+    title: "采购员",
+    type: "InputDialog",
+    config: {
+      componentName: "ORG_PARAM",
+      dataMapping: {
+        buyer: "userId",
+        buyerName: "userName",
+        puDept: "deptId",
+        puDeptName: "deptName",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "supplierName",
+    title: "供应商",
+    type: "InputDialog",
+    config: {
+      componentName: "SUPPLIER_PARAM",
+      dataMapping: {
+        supplier: "code",
+        supplierName: "name",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "contractType",
+    title: "合同类型",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_contract_type",
+    },
+  },
+  {
+    key: "puMoneyYear",
+    title: "本年度采购额",
+    type: "InputNumber",
+    require: true,
+  },
+  {
+    key: "puDeptName",
+    title: "采购部门",
+    type: "InputDialog",
+    config: {
+      componentName: "DEPT_PARAM",
+      dataMapping: {
+        puDept: "code",
+        puDeptName: "name",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "supplierTier",
+    title: "供应商层级",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_supplier_tier",
+    },
+  },
+  { key: "contractName", title: "合同名称", type: "Input", require: true },
+  {
+    key: "grossRateAverage",
+    title: "平均毛利率",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "approveFlow",
+    title: "审批流程",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_approve_flow",
+    },
+  },
+  {
+    key: "consumableClass",
+    title: "耗材类别",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_consumable_class",
+    },
+  },
+  {
+    key: "effectiveDate",
+    title: "合同生效日期",
+    type: "DatePicker",
+    require: true,
+  },
+  {
+    key: "brandGrossRate",
+    title: "同类品牌及毛利率",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "contractFormat",
+    title: "合同格式",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "productName",
+    title: "产品类别&名称",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "endDate",
+    title: "合同终止日期",
+    type: "DatePicker",
+    require: true,
+  },
+  {
+    key: "invoiceTax",
+    title: "发票税率",
+    type: "InputDialog",
+    config: {
+      componentName: "ORG_PARAM",
+      dataMapping: {
+        invoiceTax: "mattaxesname",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "emergencyDegree",
+    title: "紧急程度",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_emergency_degree",
+    },
+  },
+  { key: "project", title: "项目医院", type: "Input", require: true },
+  {
+    key: "signDate",
+    title: "合同签订日期",
+    type: "DatePicker",
+    require: true,
+  },
+  {
+    key: "deliveryType",
+    title: "交货方式",
+    type: "Select",
+    config: {
+      optionsName: "purchase_contract_delivery_type",
+    },
+  },
+  {
+    key: "source",
+    title: "合同来源",
+    type: "Input",
+    value: "自制",
+    disabled: true,
+  },
+  {
+    key: "contractPartycName",
+    title: "合同丙方",
+    type: "InputDialog",
+    config: {
+      componentName: "SUPPLIER_PARAM",
+      dataMapping: {
+        contractPartyc: "code",
+        contractPartycName: "name",
+      },
+    },
+  },
+  {
+    key: "guaranteePeriodEnd",
+    title: "质保期限",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "freightMethods",
+    title: "运费承担方式",
+    type: "Select",
+    config: {
+      optionsName: "purchase_contract_freight_methods",
+    },
+  },
+  {
+    key: "signDate",
+    title: "合同创建时间",
+    type: "DatePicker",
+    disabled: true,
+  },
+  {
+    key: "isTarget",
+    title: "是否有指标",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_is_target",
+    },
+  },
+  {
+    key: "contractTarget",
+    title: "合同指标",
+    type: "Input",
+    require: true,
+    placeholder: '当【是否有指标】="有"时,必填',
+  },
+  {
+    key: "exemptionPostageCondtion",
+    title: "包邮条件",
+    type: "Input",
+    placeholder:
+      "当运费承担方式为供应商有条件承担时,该字段必填,填写要求,写明什么条件下供应商承担全部,什么条件下我方承担,什么条件下分别承担",
+    span: 12,
+  },
+  {
+    key: "isRebate",
+    title: "是否有返利",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_is_rebate",
+    },
+  },
+  {
+    key: "rebatePolicy",
+    title: "返利政策",
+    type: "Input",
+    placeholder: '当【是否有返利】="有"时,必填',
+    span: 18,
+  },
+  { key: "externalContract", title: "外部合同号", type: "Input" },
+  {
+    key: "rollbackPolicy",
+    title: "退换货政策",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "contractContent",
+    title: "合同主要内容",
+    type: "Textarea",
+    require: true,
+    span: 24,
+  },
+  { key: "refusalReasons", title: "拒绝理由", type: "Input", span: 24 },
+  { key: "enquiryCode", title: "询价单号", type: "Input" },
+  { key: "externalFile", title: "对外附件", type: "Upload", span: 24 },
+  { key: "puFile", title: "采购商盖章合同附件", type: "Upload", span: 24 },
+  {
+    key: "supplierFile",
+    title: "供应商盖章合同附件",
+    type: "Upload",
+    span: 24,
+  },
+  { key: "projectCode", title: "项目编号", type: "Input" },
+  { key: "projectName", title: "项目名称", type: "Input" },
+  { key: "area", title: "区域", type: "Input" },
+  { key: "consigneePhone", title: "收货人联系方式", type: "Input" },
+  {
+    key: "paymentAgreementName",
+    title: "付款协议",
+    type: "InputDialog",
+    config: {
+      componentName: "PAYAGREEMENT_PARAM",
+      dataMapping: {
+        paymentAgreement: "code",
+        paymentAgreementName: "name",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "taxPrice",
+    title: "价税合计",
+    type: "InputNumber",
+  },
+  {
+    key: "currencyName",
+    title: "币种",
+    type: "InputDialog",
+    config: {
+      componentName: "CURRENCY_PARAM",
+      dataMapping: {
+        currency: "code",
+        currencyName: "name",
+      },
+    },
+    require: true,
+  },
+  { key: "guaranteePeriod", title: "质保期", type: "Input" },
+
+  // { key: "buyerName", title: "采购员名称" },
+  // { key: "supplierName", title: "供应商名称" },
+
+  // { key: "puDeptName", title: "采购部门名称" },
+
+  // { key: "contractPartycName", title: "合同丙方名称" },
+
+  // { key: "currencyName", title: "币种名称" },
+  // { key: "tenantId", title: "租户号" },
+  // { key: "revision", title: "乐观锁" },
+  // { key: "createByName", title: "创建人" },
+  // { key: "updateByName", title: "创建人名称" },
+  // { key: "delFlag", title: "删除标记" },
+];
+
+export const TabColumns = [
+  {
+    show: {
+      contractType: [1, 2],
+    },
+    title: "物料基本信息",
+    key: "contractItemList",
+    tableColumns: [
+      { title: "物料编码", key: "material", width: 200 },
+      {
+        title: "物料名称",
+        key: "materialName",
+        type: "InputDialog",
+        width: 200,
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      {
+        title: "规格",
+        key: "specification",
+        width: 200,
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      {
+        title: "品牌",
+        key: "brand",
+        type: "InputDialog",
+        width: 200,
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      { title: "生产厂家", key: "manufacturer", type: "Input", width: 200 },
+      {
+        title: "采购单位",
+        key: "puUnit",
+        type: "InputDialog",
+        width: 200,
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      {
+        title: "税率%",
+        key: "tax",
+        type: "InputDialog",
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+        width: 200,
+      },
+      {
+        title: "采购数量",
+        key: "qty",
+        type: "InputNumber",
+
+        width: 200,
+      },
+      {
+        title: "含税单价",
+        key: "taxPrice",
+        type: "InputNumber",
+
+        width: 200,
+      },
+      { title: "含税金额合计", key: "taxMoney", width: 200 },
+      { title: "无税单价", key: "taxFreePrice" },
+      { title: "无税金额合计", key: "taxFreeMoney", width: 200 },
+      {
+        title: "注册证号及备案凭证号",
+        key: "registration",
+        type: "Input",
+        width: 200,
+      },
+      {
+        title: "收货客户",
+        key: "customerName",
+        type: "InputDialog",
+        width: 200,
+        config: {
+          componentName: "SUPPLIER_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      { title: "备注", key: "remark", type: "Input", width: 200 },
+    ],
+  },
+  {
+    title: "合同条款",
+    key: "contractClauseList",
+    tableColumns: [
+      { title: "条款编码", key: "code", type: "Input" },
+      { title: "条款名称", key: "name", type: "Input" },
+      { title: "条款内容", key: "content", type: "Input" },
+      { title: "变量序号", key: "variableRowno" },
+      { title: "变量内容", key: "variableContent", type: "Input" },
+      { title: "备注", key: "remark", type: "Input" },
+    ],
+  },
+  {
+    title: "合同费用",
+    key: "contractExpenseList",
+    tableColumns: [
+      { title: "费用编码", key: "code", type: "Input" },
+      { title: "费用名称", key: "name", type: "Input" },
+      {
+        title: "费用金额",
+        key: "money",
+        type: "InputNumber",
+        width: 200,
+      },
+      { title: "备注", key: "remark", type: "Input" },
+    ],
+  },
+  {
+    title: "付款协议信息",
+    key: "contractAgreementList",
+    tableColumns: [
+      {
+        title: "付款阶段",
+        key: "satge",
+        type: "InputNumber",
+        width: 200,
+      },
+      {
+        title: "付款起点",
+        key: "origin",
+        type: "InputDialog",
+        width: 200,
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      { title: "账期天数", key: "paymetDays", type: "Input", width: 200 },
+      { title: "付款比例%", key: "ratio", type: "Input", width: 200 },
+      { title: "付款金额", key: "money", type: "Input", width: 200 },
+      { title: "是否预付款", key: "isAdvance", width: 200 },
+      { title: "是否质保金", key: "isQuality", width: 200 },
+      { title: "结算方式", key: "paymentMeans", type: "Input", width: 200 },
+      { title: "备注", key: "remark", type: "Input", width: 200 },
+      { title: "需进度确认", key: "schedule", type: "Select", width: 200 },
+    ],
+  },
+  {
+    title: "合同执行组织范围",
+    key: "contractApplyOrgList",
+    tableColumns: [
+      { title: "组织名称", key: "orgName", type: "Input" },
+      { title: "组织编码", key: "org", type: "Input" },
+    ],
+  },
+];

+ 380 - 0
src/views/purchase/catalogue/add/index.vue

@@ -0,0 +1,380 @@
+<script>
+import { Columns, TabColumns } from "./column";
+import { add, generateCode } from "@/api/business/purchase/contract";
+import { initColumns, initDicts, initRules, initParams } from "@/utils/init";
+
+const NewColumns = initColumns(Columns);
+const NewTabColumns = TabColumns.map((element) => ({
+  ...element,
+  tableColumns: initColumns(element.tableColumns),
+}));
+
+export default {
+  name: "AddDrawer",
+  dicts: initDicts(NewColumns),
+  components: {
+    DrInputDialog: () => import("@/components/input-dialog/index.vue"),
+  },
+  data() {
+    return {
+      size: "mini",
+      visible: false,
+      loading: false,
+      columns: NewColumns,
+      rules: initRules(NewColumns),
+      params: {
+        ...initParams(NewColumns),
+        contractItemList: [],
+        contractClauseList: [],
+        contractExpenseList: [],
+        contractAgreementList: [],
+        contractApplyOrgList: [],
+      },
+
+      tabColumns: NewTabColumns,
+      tabName: "contractItemList",
+    };
+  },
+  computed: {},
+  watch: {
+    "params.contractType": function (newProp) {
+      this.tabColumns = NewTabColumns.filter((element) =>
+        newProp === "1" ? element.key !== "contractItemList" : element
+      );
+      this.tabName = this.tabColumns[0].key;
+    },
+  },
+  methods: {
+    beforeOpen() {
+      const { deptName, deptId, name, id, orgName, orgId } =
+        this.$store.state.user;
+      this.params.puOrg = orgId;
+      this.params.puOrgName = orgName;
+      this.params.buyer = id;
+      this.params.buyerName = name;
+      this.params.puDept = deptId;
+      this.params.puDeptName = deptName;
+      this.fetchCode();
+    },
+    setVisible(prop) {
+      this.visible = prop;
+    },
+    async fetchCode() {
+      try {
+        this.loading = true;
+        this.params.code = await generateCode();
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    addTableRow(prop) {
+      const arr = this.tabColumns.find(
+        (element) => element.key === this.tabName
+      ).tableColumns;
+      console.log("arr", arr);
+      prop.push(initParams(arr, "key", "value"));
+    },
+    delTableRow(prop, index) {
+      prop.splice(index, 1);
+    },
+    // 取消
+    handleCancel() {
+      this.setVisible(false);
+      this.params = initParams(this.columns, "key", "value");
+    },
+    // 保存
+    handleSava() {
+      this.setVisible(false);
+    },
+    // 保存并新增
+    async handleSubmit() {
+      try {
+        const createById = this.params.buyer;
+        const createByName = this.params.buyerName;
+        const updateById = this.$store.state.user.id;
+        const updateByName = this.$store.state.user.name;
+        const { code, msg } = await add({
+          createById,
+          createByName,
+          updateById,
+          updateByName,
+          ...this.params,
+        });
+        if (code === 200) {
+          this.$notify.success({ title: msg });
+          this.setVisible(false);
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        // this.setVisible(false);
+      }
+    },
+  },
+  created() {
+    console.log("ADD CREATED");
+  },
+  mounted() {},
+  destroyed() {},
+};
+</script>
+<template>
+  <el-drawer
+    direction="btt"
+    size="100%"
+    :with-header="false"
+    :visible.sync="visible"
+    @open="beforeOpen"
+    @close="$emit('close')"
+  >
+    <el-form
+      v-loading="loading"
+      :size="size"
+      label-position="right"
+      label-width="135px"
+      :model="params"
+      :rules="rules"
+    >
+      <el-card
+        :body-style="{
+          padding: '20px',
+          display: 'flex',
+          'flex-wrap': 'wrap',
+        }"
+        style="margin: 10px"
+      >
+        <div
+          slot="header"
+          style="
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+          "
+        >
+          <h3>新增</h3>
+          <div style="text-align: right">
+            <el-button :size="size" @click="handleCancel">取 消</el-button>
+            <el-button :size="size" type="danger" @click="handleSava"
+              >保 存</el-button
+            >
+            <el-button :size="size" type="info" @click="handleSubmit">
+              新 增
+            </el-button>
+          </div>
+        </div>
+        <el-row>
+          <el-col
+            v-for="(column, index) in columns"
+            :key="index"
+            :span="column.span || 6"
+          >
+            <el-form-item :prop="column.key" :label="column.title">
+              <el-input
+                v-if="column.type === 'Input'"
+                v-model="params[column.key]"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              ></el-input>
+              <dr-input-dialog
+                v-if="column.type === 'InputDialog'"
+                v-model="params[column.key]"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                :title="column.title"
+                :type="column.config.componentName"
+                :data-mapping="column.config.dataMapping"
+                :source.sync="params"
+              >
+              </dr-input-dialog>
+              <el-input
+                v-if="column.type === 'Textarea'"
+                v-model="params[column.key]"
+                type="textarea"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              ></el-input>
+              <el-input-number
+                v-if="column.type === 'InputNumber'"
+                v-model="params[column.key]"
+                :controls-position="column.config.controlsPosition"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              ></el-input-number>
+              <el-select
+                v-if="column.type === 'Select'"
+                v-model="params[column.key]"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              >
+                <el-option
+                  v-for="item in dict.type[column.config.optionsName]"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+              <el-select
+                v-if="column.type === 'TagSelect'"
+                v-model="params[column.key]"
+                multiple
+                clearable
+                collapse-tags
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              >
+                <template #prefix>
+                  <el-icon
+                    class="el-icon-view"
+                    style="cursor: pointer"
+                    @click.stop="$message.info(234)"
+                  ></el-icon>
+                </template>
+                <el-option
+                  v-for="item in options"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+              <el-date-picker
+                v-if="column.type === 'DatePicker'"
+                v-model="params[column.key]"
+                :type="column.config.type"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :picker-options="column.pickerOptions"
+                style="width: 100%"
+              >
+              </el-date-picker>
+              <el-upload
+                v-if="column.type === 'Upload'"
+                :file-list="params[column.key]"
+                :disabled="column.disabled"
+                drag
+                action="https://sy.derom.com/document-center/fastdfs/upload"
+                multiple
+              >
+                <i class="el-icon-upload"></i>
+                <div class="el-upload__text">
+                  将文件拖到此处,或<em>点击上传</em>
+                </div>
+                <!-- <div class="el-upload__tip" slot="tip">
+                  只能上传jpg/png文件,且不超过500kb
+                </div> -->
+              </el-upload>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-card>
+      <el-card
+        :body-style="{
+          padding: '20px',
+          display: 'flex',
+          'flex-wrap': 'wrap',
+          position: 'relative',
+        }"
+        style="margin: 10px"
+      >
+        <el-tabs v-model="tabName" style="width: 100%">
+          <el-tab-pane
+            v-for="(column, index) in tabColumns"
+            :key="index"
+            :label="column.title"
+            :name="column.key"
+          >
+            <el-table :data="params[column.key]" style="width: 100%">
+              <el-table-column label="序号">
+                <template slot-scope="scope">
+                  {{ scope.$index + 1 }}
+                </template>
+              </el-table-column>
+              <el-table-column
+                v-for="(cColumn, cIndex) in column.tableColumns"
+                :key="cIndex"
+                :prop="cColumn.key"
+                :label="cColumn.title"
+                :width="cColumn.width"
+              >
+                <template slot-scope="scope">
+                  <span v-if="!cColumn.type">
+                    {{ scope.row[cColumn.key] }}</span
+                  >
+                  <el-input
+                    v-if="cColumn.type === 'Input'"
+                    v-model="scope.row[cColumn.key]"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    :size="size"
+                    style="width: 100%"
+                  ></el-input>
+                  <dr-input-dialog
+                    v-if="cColumn.type === 'InputDialog'"
+                    v-model="scope.row[cColumn.key]"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    :readonly="cColumn.readonly"
+                    :title="cColumn.title"
+                    :type="cColumn.config.componentName"
+                    :data-mapping="cColumn.config.dataMapping"
+                    :source.sync="scope.row"
+                    :size="size"
+                  >
+                  </dr-input-dialog>
+                  <el-input-number
+                    v-if="cColumn.type === 'InputNumber'"
+                    v-model="scope.row[cColumn.key]"
+                    :controls-position="cColumn.config.controlsPosition"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    :size="size"
+                    style="width: 100%"
+                  ></el-input-number>
+                </template>
+              </el-table-column>
+              <el-table-column fixed="right" label="操作" width="120">
+                <template slot-scope="scope">
+                  <el-button
+                    @click.native.prevent="
+                      delTableRow(params[tabName], scope.$index)
+                    "
+                    type="text"
+                    size="small"
+                  >
+                    删行
+                  </el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-tab-pane>
+        </el-tabs>
+        <el-row style="position: absolute; top: 20px; right: 20px">
+          <el-button :size="size" @click="addTableRow(params[tabName])"
+            >增行</el-button
+          >
+        </el-row>
+      </el-card>
+    </el-form>
+  </el-drawer>
+</template>

+ 61 - 0
src/views/purchase/catalogue/column.js

@@ -0,0 +1,61 @@
+export const TableColumns = [
+  { key: "id", title: "id" },
+  { key: "puOrg", title: "采购组织" },
+  {
+    key: "puOrgName",
+    title: "采购组织名称",
+    search: true,
+    config: {
+      componentName: "ORG_PARAM",
+      dataMapping: {
+        puOrg: "code",
+        puOrgName: "name",
+      },
+    },
+  },
+  { key: "material", title: "物料编码", search: true },
+  { key: "materialClassify", title: "物料一级分类", search: true },
+  { key: "manufacturer", title: "生产厂家" },
+  { key: "materialName", title: "物料名称" },
+  { key: "model", title: "物料型号" },
+  { key: "specification", title: "物料规格" },
+  { key: "supplier", title: "供应商" },
+  {
+    key: "supplierName",
+    title: "供应商名称",
+    search: true,
+    config: {
+      componentName: "SUPPLIER_PARAM",
+      dataMapping: {
+        supplier: "code",
+        supplierName: "name",
+      },
+    },
+  },
+  { key: "customer", title: "客户" },
+  { key: "customerName", title: "客户名称" },
+  { key: "taxPrice", title: "主含税单价" },
+  { key: "unit", title: "主单位" },
+  { key: "unitName", title: "主单位名称" },
+  { key: "effectiveDate", title: "价格生效日期" },
+  { key: "endDate", title: "价格失效日期" },
+  { key: "buyer", title: "采购员" },
+  { key: "buyerName", title: "采购员名称" },
+  { key: "source", title: "来源单据编号", search: true },
+  { key: "status", title: "有效状态" },
+  { key: "enableStatus", title: "启用状态" },
+  { key: "convertRate", title: "换算率" },
+  { key: "materialStatus", title: "物料启用状态" },
+  { key: "isDistribution", title: "配送价" },
+  { key: "priceType", title: "价格类型" },
+  { key: "demandCode", title: "采购需求单号" },
+  { key: "expiryEarly", title: "效期预警" },
+  { key: "priority", title: "含税/无税优先" },
+  { key: "tenantId", title: "租户号" },
+  { key: "revision", title: "乐观锁" },
+  { key: "createByName", title: "创建人" },
+  { key: "updateByName", title: "更新人名称" },
+  { key: "delFlag", title: "删除标记" },
+];
+
+export const SearchColumns = TableColumns.filter((element) => element.search);

+ 399 - 0
src/views/purchase/catalogue/edit/index.vue

@@ -0,0 +1,399 @@
+<script>
+import { Columns, TabColumns } from "../add/column";
+import {
+  edit,
+  item,
+  itemTableList,
+} from "@/api/business/purchase/contract";
+import { initColumns, initDicts, initRules, initParams } from "@/utils/init";
+
+const NewColumns = initColumns(Columns);
+const NewTabColumns = TabColumns.map((element) => ({
+  ...element,
+  tableColumns: initColumns(element.tableColumns),
+}));
+
+export default {
+  name: "EditDrawer",
+  dicts: initDicts(NewColumns),
+  components: {
+    DrInputDialog: () => import("@/components/input-dialog/index.vue"),
+  },
+  data() {
+    return {
+      size: "mini",
+      visible: false,
+      loading: false,
+      columns: NewColumns,
+      rules: initRules(NewColumns),
+      params: {
+        ...initParams(NewColumns),
+        contractItemList: [],
+        contractClauseList: [],
+        contractExpenseList: [],
+        contractAgreementList: [],
+        contractApplyOrgList: [],
+      },
+
+      tabColumns: NewTabColumns,
+      tabName: "contractItemList",
+    };
+  },
+  computed: {},
+  watch: {
+    "params.contractType": function (newProp) {
+      this.tabColumns = NewTabColumns.filter((element) =>
+        newProp === "1" ? element.key !== "contractItemList" : element
+      );
+      this.tabName = this.tabColumns[0].key;
+    },
+    tabName: function (newProp) {
+      const { id } = this.params;
+      this.fetchTable(id, newProp);
+    },
+  },
+  methods: {
+    setVisible(prop) {
+      this.visible = prop;
+    },
+    // 查询详细
+    async fetchItem(prop) {
+      try {
+        this.loading = true;
+        const { code, msg, data } = await item(prop);
+        if (code === 200) {
+          this.params = data;
+          this.$notify.success({ title: msg });
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    // 查询详情关联TABLE
+    async fetchTable(prop, name) {
+      try {
+        this.loading = true;
+        const { code, msg, rows } = await itemTableList({ id: prop }, name);
+        if (code === 200) {
+          this.params[name] = rows;
+          this.$notify.success({ title: msg });
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    // 新增行
+    addTableRow(prop) {
+      const arr = this.tabColumns.find(
+        (element) => element.key === this.tabName
+      ).tableColumns;
+      prop.push(initParams(arr, "key", "value"));
+    },
+    // 删除行
+    delTableRow(prop, index) {
+      prop.splice(index, 1);
+    },
+    // 取消
+    handleCancel() {
+      this.setVisible(false);
+      this.params = initParams(this.columns, "key", "value");
+    },
+    // 保存
+    handleSava() {
+      this.setVisible(false);
+    },
+    // 保存并新增
+    async handleSubmit() {
+      try {
+        const createById = this.params.buyer;
+        const createByName = this.params.buyerName;
+        const updateById = this.$store.state.user.id;
+        const updateByName = this.$store.state.user.name;
+        const { code, msg } = await edit({
+          createById,
+          createByName,
+          updateById,
+          updateByName,
+          ...this.params,
+        });
+        if (code === 200) {
+          this.$notify.success({ title: msg });
+          this.setVisible(false);
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        // this.setVisible(false);
+      }
+    },
+  },
+  created() {
+    console.log("ADD CREATED");
+  },
+  mounted() {},
+  destroyed() {},
+};
+</script>
+<template>
+  <el-drawer
+    direction="btt"
+    size="100%"
+    :with-header="false"
+    :visible.sync="visible"
+    @open="beforeOpen"
+    @close="$emit('close')"
+  >
+    <el-form
+      v-loading="loading"
+      :size="size"
+      label-position="right"
+      label-width="135px"
+      :model="params"
+      :rules="rules"
+    >
+      <el-card
+        :body-style="{
+          padding: '20px',
+          display: 'flex',
+          'flex-wrap': 'wrap',
+        }"
+        style="margin: 10px"
+      >
+        <div
+          slot="header"
+          style="
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+          "
+        >
+          <h3>编辑</h3>
+          <div style="text-align: right">
+            <el-button :size="size" @click="handleCancel">取 消</el-button>
+            <el-button :size="size" type="danger" @click="handleSava"
+              >更 新</el-button
+            >
+          </div>
+        </div>
+        <el-row>
+          <el-col
+            v-for="(column, index) in columns"
+            :key="index"
+            :span="column.span || 6"
+          >
+            <el-form-item :prop="column.key" :label="column.title">
+              <el-input
+                v-if="column.type === 'Input'"
+                v-model="params[column.key]"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              ></el-input>
+              <dr-input-dialog
+                v-if="column.type === 'InputDialog'"
+                v-model="params[column.key]"
+                :source.sync="params"
+                :type="column.config.componentName"
+                :data-mapping="column.config.dataMapping"
+                :title="column.title"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                :clearable="column.clearable"
+                :placeholder="column.placeholder"
+              >
+              </dr-input-dialog>
+              <el-input
+                v-if="column.type === 'Textarea'"
+                v-model="params[column.key]"
+                type="textarea"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              ></el-input>
+              <el-input-number
+                v-if="column.type === 'InputNumber'"
+                v-model="params[column.key]"
+                :controls-position="column.config.controlsPosition"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              ></el-input-number>
+              <el-select
+                v-if="column.type === 'Select'"
+                v-model="params[column.key]"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              >
+                <el-option
+                  v-for="item in dict.type[column.config.optionsName]"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+              <el-select
+                v-if="column.type === 'TagSelect'"
+                v-model="params[column.key]"
+                multiple
+                clearable
+                collapse-tags
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              >
+                <template #prefix>
+                  <el-icon
+                    class="el-icon-view"
+                    style="cursor: pointer"
+                    @click.stop="$message.info(234)"
+                  ></el-icon>
+                </template>
+                <el-option
+                  v-for="item in options"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+              <el-date-picker
+                v-if="column.type === 'DatePicker'"
+                v-model="params[column.key]"
+                :type="column.config.type"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :picker-options="column.pickerOptions"
+                style="width: 100%"
+              >
+              </el-date-picker>
+              <el-upload
+                v-if="column.type === 'Upload'"
+                :file-list="params[column.key]"
+                :disabled="column.disabled"
+                drag
+                action="https://sy.derom.com/document-center/fastdfs/upload"
+                multiple
+              >
+                <i class="el-icon-upload"></i>
+                <div class="el-upload__text">
+                  将文件拖到此处,或<em>点击上传</em>
+                </div>
+                <!-- <div class="el-upload__tip" slot="tip">
+                  只能上传jpg/png文件,且不超过500kb
+                </div> -->
+              </el-upload>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-card>
+      <el-card
+        :body-style="{
+          padding: '20px',
+          display: 'flex',
+          'flex-wrap': 'wrap',
+          position: 'relative',
+        }"
+        style="margin: 10px"
+      >
+        <el-tabs v-model="tabName" style="width: 100%">
+          <el-tab-pane
+            v-for="(column, index) in tabColumns"
+            :key="index"
+            :label="column.title"
+            :name="column.key"
+          >
+            <el-table :data="params[column.key]" style="width: 100%">
+              <el-table-column label="序号">
+                <template slot-scope="scope">
+                  {{ scope.$index + 1 }}
+                </template>
+              </el-table-column>
+              <el-table-column
+                v-for="(cColumn, cIndex) in column.tableColumns"
+                :key="cIndex"
+                :prop="cColumn.key"
+                :label="cColumn.title"
+                :width="cColumn.width"
+              >
+                <template slot-scope="scope">
+                  <span v-if="!cColumn.type">
+                    {{ scope.row[cColumn.key] }}</span
+                  >
+                  <el-input
+                    v-if="cColumn.type === 'Input'"
+                    v-model="scope.row[cColumn.key]"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    :size="size"
+                    style="width: 100%"
+                  ></el-input>
+                  <dr-input-dialog
+                    v-if="cColumn.type === 'InputDialog'"
+                    v-model="scope.row[cColumn.key]"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    :readonly="cColumn.readonly"
+                    :title="cColumn.title"
+                    :type="cColumn.config.componentName"
+                    :data-mapping="cColumn.config.dataMapping"
+                    :source.sync="scope.row"
+                    :size="size"
+                  >
+                  </dr-input-dialog>
+                  <el-input-number
+                    v-if="cColumn.type === 'InputNumber'"
+                    v-model="scope.row[cColumn.key]"
+                    :controls-position="cColumn.config.controlsPosition"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    :size="size"
+                    style="width: 100%"
+                  ></el-input-number>
+                </template>
+              </el-table-column>
+              <el-table-column fixed="right" label="操作" width="120">
+                <template slot-scope="scope">
+                  <el-button
+                    @click.native.prevent="
+                      delTableRow(params[tabName], scope.$index)
+                    "
+                    type="text"
+                    size="small"
+                  >
+                    删行
+                  </el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-tab-pane>
+        </el-tabs>
+        <el-row style="position: absolute; top: 20px; right: 20px">
+          <el-button :size="size" @click="addTableRow(params[tabName])"
+            >增行</el-button
+          >
+        </el-row>
+      </el-card>
+    </el-form>
+  </el-drawer>
+</template>

+ 194 - 0
src/views/purchase/catalogue/index.vue

@@ -0,0 +1,194 @@
+<script>
+import { TableColumns, SearchColumns } from "./column";
+import { list, remove } from "@/api/business/purchase/catalogue";
+import { initPage, initLayout, initPageSizes, initParams } from "@/utils/init";
+export default {
+  name: "PuchaseContract",
+  components: {
+    AddDrawer: () => import("./add/index.vue"),
+    SeeDrawer: () => import("./see/index.vue"),
+    EditDrawer: () => import("./edit/index.vue"),
+  },
+  data() {
+    return {
+      size: "mini",
+      loading: false,
+      searchColumns: SearchColumns,
+      params: initParams(SearchColumns),
+      tableData: [],
+      tableColumns: TableColumns,
+      page: initPage(),
+      layout: initLayout(),
+      pageSizes: initPageSizes(),
+    };
+  },
+  computed: {},
+  created() {
+    this.handleQueryList();
+  },
+  methods: {
+    //
+    async fetchList(params, page) {
+      try {
+        this.loading = true;
+        const { pageNum, pageSize } = page;
+        const { code, msg, rows, total } = await list({
+          pageNum,
+          pageSize,
+          ...params,
+        });
+        if (code === 200) {
+          this.tableData = rows;
+          this.page.total = total;
+          this.$notify.success({ title: msg });
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    // 查询操作
+    handleQueryList() {
+      this.fetchList(this.params, this.page);
+    },
+    // 重置操作
+    handleResetList() {
+      this.page = initPage();
+      this.params = initParams(SearchColumns);
+      this.fetchList(this.params, this.page);
+    },
+    // 删除操作
+    async handleDeleteList(prop) {
+      try {
+        this.loading = true;
+        const { id } = prop;
+        const { code, msg } = await remove(id);
+        if (code === 200) {
+          this.$notify.success({ title: msg });
+          this.fetchList(this.params, this.page);
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    // 页大小变
+    handleSizeChange(prop) {
+      this.page.pageSize = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // 当前页变
+    handleCurrentChange(prop) {
+      this.page.pageNum = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // 打开新增drawer
+    handleOpenAddDrawer() {
+      console.log(this.$refs.AddDrawerFef);
+      const { setVisible } = this.$refs.AddDrawerFef;
+      setVisible(true);
+    },
+    // 打开查看drawer
+    async handleOpenSeeDrawer(prop) {
+      const { id } = prop;
+      const { setVisible, fetchItem } = this.$refs.SeeDrawerFef;
+      await setVisible(true);
+      await fetchItem(id);
+    },
+    // 打开编辑drawer
+    async handleOpenEditDrawer(prop) {
+      const { id } = prop;
+      const { setVisible, fetchItem } = this.$refs.EditDrawerFef;
+      await setVisible(true);
+      await fetchItem(id);
+    },
+  },
+};
+</script>
+
+<template>
+  <el-card
+    v-loading="loading"
+    style="width: calc(100% - 24px); height: 100%; margin: 10px"
+    :body-style="{ padding: 0 }"
+  >
+    <see-drawer ref="SeeDrawerFef"></see-drawer>
+    <add-drawer ref="AddDrawerFef" @close="handleResetList"></add-drawer>
+    <edit-drawer ref="EditDrawerFef" @close="handleResetList"></edit-drawer>
+    <el-form :size="size" label-position="top" :model="params">
+      <el-row :gutter="24" style="padding: 0 20px">
+        <el-col
+          v-for="column in searchColumns"
+          :key="column.title"
+          :xl="4"
+          :lg="4"
+          :md="8"
+          :sm="12"
+          :xs="24"
+        >
+          <el-form-item :prop="column.key" :label="column.title">
+            <el-input
+              v-model="params[column.key]"
+              :placeholder="column.placeholder"
+            ></el-input>
+          </el-form-item>
+        </el-col>
+        <el-col :xl="6" :lg="6" :md="8" :sm="12" :xs="24"> </el-col>
+      </el-row>
+    </el-form>
+    <el-row :gutter="24" style="padding: 0 20px">
+      <el-col :span="24">
+        <el-button :size="size" icon="el-icon-search" @click="handleQueryList"
+          >搜索</el-button
+        >
+        <el-button :size="size" icon="el-icon-refresh" @click="handleResetList"
+          >重置</el-button
+        >
+      </el-col>
+    </el-row>
+    <el-table
+      @row-dblclick="handleOpenSeeDrawer"
+      :data="tableData"
+      :size="size"
+      style="width: 100%; margin: 20px 0 0 0"
+    >
+      <el-table-column
+        v-for="(column, index) in tableColumns"
+        :key="index"
+        :prop="column.key"
+        :label="column.title"
+        :width="column.width || 180"
+        :show-overflow-tooltip="column.showOverflowTooltip || true"
+      >
+      </el-table-column>
+      <el-table-column fixed="right" label="操作" width="120">
+        <template slot-scope="scope">
+          <el-button
+            @click.native.prevent="handleDeleteList(scope.row)"
+            type="text"
+            size="small"
+          >
+            删 除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <el-pagination
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+      :total="page.total"
+      :page-sizes="pageSizes"
+      :page-size="page.pageSize"
+      :current-page="page.pageNum"
+      :layout="layout"
+      style="margin: 16px 0"
+    >
+    </el-pagination>
+  </el-card>
+</template>

+ 317 - 0
src/views/purchase/catalogue/see/index.vue

@@ -0,0 +1,317 @@
+<script>
+import { Columns, TabColumns } from "../add/column";
+import { item, itemTableList } from "@/api/business/purchase/contract";
+import { initColumns, initDicts, initRules, initParams } from "@/utils/init";
+
+const NewColumns = initColumns(Columns, { disabled: true, readonly: true });
+const NewTabColumns = TabColumns.map((element) => ({
+  ...element,
+  tableColumns: initColumns(element.tableColumns, {
+    disabled: true,
+    readonly: true,
+  }),
+}));
+
+export default {
+  name: "SeeDrawer",
+  dicts: initDicts(NewColumns),
+  data() {
+    return {
+      visible: false,
+      loading: false,
+      columns: NewColumns,
+      rules: initRules(NewColumns),
+      params: {
+        ...initParams(NewColumns),
+        contractItemList: [],
+        contractClauseList: [],
+        contractExpenseList: [],
+        contractAgreementList: [],
+        contractApplyOrgList: [],
+      },
+
+      tabColumns: NewTabColumns,
+      tabName: "contractItemList",
+    };
+  },
+  computed: {},
+  watch: {
+    "params.contractType": function (newProp) {
+      this.tabColumns = NewTabColumns.filter((element) =>
+        newProp === "1" ? element.key !== "contractItemList" : element
+      );
+      this.tabName = this.tabColumns[0].key;
+    },
+    tabName: function (newProp) {
+      const { id } = this.params;
+      this.fetchTable(id, newProp);
+    },
+  },
+  methods: {
+    setVisible(prop) {
+      this.visible = prop;
+    },
+    // 查询详细
+    async fetchItem(prop) {
+      try {
+        this.loading = true;
+        const { code, msg, data } = await item(prop);
+        if (code === 200) {
+          this.params = data;
+          this.$notify.success({ title: msg });
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    // 查询详情关联TABLE
+    async fetchTable(prop, name) {
+      try {
+        this.loading = true;
+        const { code, msg, rows } = await itemTableList({ id: prop }, name);
+        if (code === 200) {
+          this.params[name] = rows;
+          this.$notify.success({ title: msg });
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    // 取消操作
+    handleCancel() {
+      this.setVisible(false);
+      this.params = initParams(Columns);
+    },
+    // 编辑操作
+    handleOpenEditDrawer(prop) {
+      this.setVisible(false);
+      this.$parent.$parent.handleOpenEditDrawer(prop);
+    },
+  },
+  created() {},
+  mounted() {},
+  destroyed() {},
+};
+</script>
+<template>
+  <el-drawer
+    direction="btt"
+    size="100%"
+    :with-header="false"
+    :visible.sync="visible"
+    destroy-on-close
+  >
+    <el-form
+      v-loading="loading"
+      size="mini"
+      label-position="right"
+      label-width="135px"
+      :model="params"
+      :rules="rules"
+    >
+      <el-card
+        :body-style="{
+          padding: '20px',
+          display: 'flex',
+          'flex-wrap': 'wrap',
+        }"
+        style="margin: 10px"
+      >
+        <div
+          slot="header"
+          style="
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+          "
+        >
+          <h3>查看</h3>
+          <div style="text-align: right">
+            <el-button size="mini" @click="handleOpenEditDrawer(params)"
+              >编 辑</el-button
+            >
+            <el-button size="mini" @click="handleCancel">取 消</el-button>
+          </div>
+        </div>
+        <el-row>
+          <el-col
+            v-for="(column, index) in columns"
+            :key="index"
+            :span="column.span || 6"
+          >
+            <el-form-item :prop="column.key" :label="column.title">
+              <el-input
+                v-if="column.type === 'Textarea'"
+                v-model="params[column.key]"
+                type="textarea"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                style="width: 100%"
+              ></el-input>
+              <el-input-number
+                v-else-if="column.type === 'InputNumber'"
+                v-model="params[column.key]"
+                :controls-position="column.config.controlsPosition"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                style="width: 100%"
+              ></el-input-number>
+              <el-select
+                v-else-if="column.type === 'Select'"
+                v-model="params[column.key]"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                style="width: 100%"
+              >
+                <el-option
+                  v-for="item in dict.type[column.config.optionsName]"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+              <el-date-picker
+                v-else-if="column.type === 'DatePicker'"
+                v-model="params[column.key]"
+                :type="column.config.type"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                :picker-options="column.pickerOptions"
+                style="width: 100%"
+              >
+              </el-date-picker>
+              <el-upload
+                v-else-if="column.type === 'Upload'"
+                :file-list="params[column.key]"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                drag
+                action="https://jsonplaceholder.typicode.com/posts/"
+                multiple
+              >
+                <i class="el-icon-upload"></i>
+                <div class="el-upload__text">
+                  将文件拖到此处,或<em>点击上传</em>
+                </div>
+                <div class="el-upload__tip" slot="tip">
+                  只能上传jpg/png文件,且不超过500kb
+                </div>
+              </el-upload>
+              <el-input
+                v-else
+                v-model="params[column.key]"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                style="width: 100%"
+              ></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-card>
+      <el-card
+        :body-style="{
+          padding: '20px',
+          display: 'flex',
+          'flex-wrap': 'wrap',
+          position: 'relative',
+        }"
+        style="margin: 10px"
+      >
+        <el-tabs v-model="tabName" style="width: 100%">
+          <el-tab-pane
+            v-for="(column, index) in tabColumns"
+            :key="index"
+            :label="column.title"
+            :name="column.key"
+          >
+            <el-table :data="params[column.key]" style="width: 100%">
+              <el-table-column
+                v-for="(cColumn, cIndex) in column.tableColumns"
+                :key="cIndex"
+                :prop="cColumn.key"
+                :label="cColumn.title"
+                :width="cColumn.width"
+              >
+                <template slot-scope="scope">
+                  <el-tag v-if="cColumn.key === 'index'">
+                    {{ scope.$index + 1 }}
+                  </el-tag>
+                  <el-input
+                    v-if="cColumn.type === 'Input'"
+                    v-model="scope.row[cColumn.key]"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    size="mini"
+                    style="width: 100%"
+                  ></el-input>
+                  <el-input-number
+                    v-if="cColumn.type === 'InputNumber'"
+                    v-model="scope.row[cColumn.key]"
+                    :controls-position="cColumn.config.controlsPosition"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    size="mini"
+                    style="width: 100%"
+                  ></el-input-number>
+                  <el-input
+                    v-if="column.type === 'InputDialog'"
+                    v-model="params[column.key]"
+                    :placeholder="column.placeholder"
+                    :clearable="column.clearable"
+                    :disabled="column.disabled"
+                    :readonly="column.readonly"
+                    style="width: 100%; cursor: pointer"
+                    @click.native.stop="openAsyncInputDialog(column, params)"
+                  >
+                    <template #suffix>
+                      <el-icon class="el-icon-thumb"></el-icon>
+                    </template>
+                  </el-input>
+                </template>
+              </el-table-column>
+              <!-- <el-table-column fixed="right" label="操作" width="120">
+                <template slot-scope="scope">
+                  <el-button
+                    @click.native.prevent="
+                      delTableRow(params[tabName], scope.$index)
+                    "
+                    type="text"
+                    size="small"
+                  >
+                    删行
+                  </el-button>
+                </template>
+              </el-table-column> -->
+            </el-table>
+          </el-tab-pane>
+        </el-tabs>
+        <!-- <el-row style="position: absolute; top: 20px; right: 20px">
+          <el-button size="mini" @click="addTableRow(params[tabName])"
+            >增行</el-button
+          >
+        </el-row> -->
+      </el-card>
+    </el-form>
+  </el-drawer>
+</template>

+ 514 - 0
src/views/purchase/contract/add/column.js

@@ -0,0 +1,514 @@
+export const Columns = [
+  {
+    key: "puOrgName",
+    title: "采购组织",
+    type: "InputDialog",
+    config: {
+      componentName: "ORG_PARAM",
+      dataMapping: {
+        puOrg: "code",
+        puOrgName: "name",
+      },
+    },
+    require: true,
+  },
+  { key: "code", title: "合同编码", type: "Input" },
+  {
+    key: "lastPuMoney",
+    title: "上年度采购额",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "buyerName",
+    title: "采购员",
+    type: "InputDialog",
+    config: {
+      componentName: "ORG_PARAM",
+      dataMapping: {
+        buyer: "userId",
+        buyerName: "userName",
+        puDept: "deptId",
+        puDeptName: "deptName",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "supplierName",
+    title: "供应商",
+    type: "InputDialog",
+    config: {
+      componentName: "SUPPLIER_PARAM",
+      dataMapping: {
+        supplier: "code",
+        supplierName: "name",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "contractType",
+    title: "合同类型",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_contract_type",
+    },
+  },
+  {
+    key: "puMoneyYear",
+    title: "本年度采购额",
+    type: "InputNumber",
+    require: true,
+  },
+  {
+    key: "puDeptName",
+    title: "采购部门",
+    type: "InputDialog",
+    config: {
+      componentName: "DEPT_PARAM",
+      dataMapping: {
+        puDept: "code",
+        puDeptName: "name",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "supplierTier",
+    title: "供应商层级",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_supplier_tier",
+    },
+  },
+  { key: "contractName", title: "合同名称", type: "Input", require: true },
+  {
+    key: "grossRateAverage",
+    title: "平均毛利率",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "approveFlow",
+    title: "审批流程",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_approve_flow",
+    },
+  },
+  {
+    key: "consumableClass",
+    title: "耗材类别",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_consumable_class",
+    },
+  },
+  {
+    key: "effectiveDate",
+    title: "合同生效日期",
+    type: "DatePicker",
+    require: true,
+  },
+  {
+    key: "brandGrossRate",
+    title: "同类品牌及毛利率",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "contractFormat",
+    title: "合同格式",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "productName",
+    title: "产品类别&名称",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "endDate",
+    title: "合同终止日期",
+    type: "DatePicker",
+    require: true,
+  },
+  {
+    key: "invoiceTax",
+    title: "发票税率",
+    type: "InputDialog",
+    config: {
+      componentName: "ORG_PARAM",
+      dataMapping: {
+        invoiceTax: "mattaxesname",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "emergencyDegree",
+    title: "紧急程度",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_emergency_degree",
+    },
+  },
+  { key: "project", title: "项目医院", type: "Input", require: true },
+  {
+    key: "signDate",
+    title: "合同签订日期",
+    type: "DatePicker",
+    require: true,
+  },
+  {
+    key: "deliveryType",
+    title: "交货方式",
+    type: "Select",
+    config: {
+      optionsName: "purchase_contract_delivery_type",
+    },
+  },
+  {
+    key: "source",
+    title: "合同来源",
+    type: "Input",
+    value: "自制",
+    disabled: true,
+  },
+  {
+    key: "contractPartycName",
+    title: "合同丙方",
+    type: "InputDialog",
+    config: {
+      componentName: "SUPPLIER_PARAM",
+      dataMapping: {
+        contractPartyc: "code",
+        contractPartycName: "name",
+      },
+    },
+  },
+  {
+    key: "guaranteePeriodEnd",
+    title: "质保期限",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "freightMethods",
+    title: "运费承担方式",
+    type: "Select",
+    config: {
+      optionsName: "purchase_contract_freight_methods",
+    },
+  },
+  {
+    key: "signDate",
+    title: "合同创建时间",
+    type: "DatePicker",
+    disabled: true,
+  },
+  {
+    key: "isTarget",
+    title: "是否有指标",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_is_target",
+    },
+  },
+  {
+    key: "contractTarget",
+    title: "合同指标",
+    type: "Input",
+    require: true,
+    placeholder: '当【是否有指标】="有"时,必填',
+  },
+  {
+    key: "exemptionPostageCondtion",
+    title: "包邮条件",
+    type: "Input",
+    placeholder:
+      "当运费承担方式为供应商有条件承担时,该字段必填,填写要求,写明什么条件下供应商承担全部,什么条件下我方承担,什么条件下分别承担",
+    span: 12,
+  },
+  {
+    key: "isRebate",
+    title: "是否有返利",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_is_rebate",
+    },
+  },
+  {
+    key: "rebatePolicy",
+    title: "返利政策",
+    type: "Input",
+    placeholder: '当【是否有返利】="有"时,必填',
+    span: 18,
+  },
+  { key: "externalContract", title: "外部合同号", type: "Input" },
+  {
+    key: "rollbackPolicy",
+    title: "退换货政策",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "contractContent",
+    title: "合同主要内容",
+    type: "Textarea",
+    require: true,
+    span: 24,
+  },
+  { key: "refusalReasons", title: "拒绝理由", type: "Input", span: 24 },
+  { key: "enquiryCode", title: "询价单号", type: "Input" },
+  { key: "externalFile", title: "对外附件", type: "Upload", span: 24 },
+  { key: "puFile", title: "采购商盖章合同附件", type: "Upload", span: 24 },
+  {
+    key: "supplierFile",
+    title: "供应商盖章合同附件",
+    type: "Upload",
+    span: 24,
+  },
+  { key: "projectCode", title: "项目编号", type: "Input" },
+  { key: "projectName", title: "项目名称", type: "Input" },
+  { key: "area", title: "区域", type: "Input" },
+  { key: "consigneePhone", title: "收货人联系方式", type: "Input" },
+  {
+    key: "paymentAgreementName",
+    title: "付款协议",
+    type: "InputDialog",
+    config: {
+      componentName: "PAYAGREEMENT_PARAM",
+      dataMapping: {
+        paymentAgreement: "code",
+        paymentAgreementName: "name",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "taxPrice",
+    title: "价税合计",
+    type: "InputNumber",
+  },
+  {
+    key: "currencyName",
+    title: "币种",
+    type: "InputDialog",
+    config: {
+      componentName: "CURRENCY_PARAM",
+      dataMapping: {
+        currency: "code",
+        currencyName: "name",
+      },
+    },
+    require: true,
+  },
+  { key: "guaranteePeriod", title: "质保期", type: "Input" },
+
+  // { key: "buyerName", title: "采购员名称" },
+  // { key: "supplierName", title: "供应商名称" },
+
+  // { key: "puDeptName", title: "采购部门名称" },
+
+  // { key: "contractPartycName", title: "合同丙方名称" },
+
+  // { key: "currencyName", title: "币种名称" },
+  // { key: "tenantId", title: "租户号" },
+  // { key: "revision", title: "乐观锁" },
+  // { key: "createByName", title: "创建人" },
+  // { key: "updateByName", title: "创建人名称" },
+  // { key: "delFlag", title: "删除标记" },
+];
+
+export const TabColumns = [
+  {
+    show: {
+      contractType: [1, 2],
+    },
+    title: "物料基本信息",
+    key: "contractItemList",
+    tableColumns: [
+      { title: "物料编码", key: "material", width: 200 },
+      {
+        title: "物料名称",
+        key: "materialName",
+        type: "InputDialog",
+        width: 200,
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      {
+        title: "规格",
+        key: "specification",
+        width: 200,
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      {
+        title: "品牌",
+        key: "brand",
+        type: "InputDialog",
+        width: 200,
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      { title: "生产厂家", key: "manufacturer", type: "Input", width: 200 },
+      {
+        title: "采购单位",
+        key: "puUnit",
+        type: "InputDialog",
+        width: 200,
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      {
+        title: "税率%",
+        key: "tax",
+        type: "InputDialog",
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+        width: 200,
+      },
+      {
+        title: "采购数量",
+        key: "qty",
+        type: "InputNumber",
+
+        width: 200,
+      },
+      {
+        title: "含税单价",
+        key: "taxPrice",
+        type: "InputNumber",
+
+        width: 200,
+      },
+      { title: "含税金额合计", key: "taxMoney", width: 200 },
+      { title: "无税单价", key: "taxFreePrice" },
+      { title: "无税金额合计", key: "taxFreeMoney", width: 200 },
+      {
+        title: "注册证号及备案凭证号",
+        key: "registration",
+        type: "Input",
+        width: 200,
+      },
+      {
+        title: "收货客户",
+        key: "customerName",
+        type: "InputDialog",
+        width: 200,
+        config: {
+          componentName: "SUPPLIER_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      { title: "备注", key: "remark", type: "Input", width: 200 },
+    ],
+  },
+  {
+    title: "合同条款",
+    key: "contractClauseList",
+    tableColumns: [
+      { title: "条款编码", key: "code", type: "Input" },
+      { title: "条款名称", key: "name", type: "Input" },
+      { title: "条款内容", key: "content", type: "Input" },
+      { title: "变量序号", key: "variableRowno" },
+      { title: "变量内容", key: "variableContent", type: "Input" },
+      { title: "备注", key: "remark", type: "Input" },
+    ],
+  },
+  {
+    title: "合同费用",
+    key: "contractExpenseList",
+    tableColumns: [
+      { title: "费用编码", key: "code", type: "Input" },
+      { title: "费用名称", key: "name", type: "Input" },
+      {
+        title: "费用金额",
+        key: "money",
+        type: "InputNumber",
+        width: 200,
+      },
+      { title: "备注", key: "remark", type: "Input" },
+    ],
+  },
+  {
+    title: "付款协议信息",
+    key: "contractAgreementList",
+    tableColumns: [
+      {
+        title: "付款阶段",
+        key: "satge",
+        type: "InputNumber",
+        width: 200,
+      },
+      {
+        title: "付款起点",
+        key: "origin",
+        type: "InputDialog",
+        width: 200,
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      { title: "账期天数", key: "paymetDays", type: "Input", width: 200 },
+      { title: "付款比例%", key: "ratio", type: "Input", width: 200 },
+      { title: "付款金额", key: "money", type: "Input", width: 200 },
+      { title: "是否预付款", key: "isAdvance", width: 200 },
+      { title: "是否质保金", key: "isQuality", width: 200 },
+      { title: "结算方式", key: "paymentMeans", type: "Input", width: 200 },
+      { title: "备注", key: "remark", type: "Input", width: 200 },
+      { title: "需进度确认", key: "schedule", type: "Select", width: 200 },
+    ],
+  },
+  {
+    title: "合同执行组织范围",
+    key: "contractApplyOrgList",
+    tableColumns: [
+      { title: "组织名称", key: "orgName", type: "Input" },
+      { title: "组织编码", key: "org", type: "Input" },
+    ],
+  },
+];

+ 380 - 0
src/views/purchase/contract/add/index.vue

@@ -0,0 +1,380 @@
+<script>
+import { Columns, TabColumns } from "./column";
+import { add, generateCode } from "@/api/business/purchase/contract";
+import { initColumns, initDicts, initRules, initParams } from "@/utils/init";
+
+const NewColumns = initColumns(Columns);
+const NewTabColumns = TabColumns.map((element) => ({
+  ...element,
+  tableColumns: initColumns(element.tableColumns),
+}));
+
+export default {
+  name: "AddDrawer",
+  dicts: initDicts(NewColumns),
+  components: {
+    DrInputDialog: () => import("@/components/input-dialog/index.vue"),
+  },
+  data() {
+    return {
+      size: "mini",
+      visible: false,
+      loading: false,
+      columns: NewColumns,
+      rules: initRules(NewColumns),
+      params: {
+        ...initParams(NewColumns),
+        contractItemList: [],
+        contractClauseList: [],
+        contractExpenseList: [],
+        contractAgreementList: [],
+        contractApplyOrgList: [],
+      },
+
+      tabColumns: NewTabColumns,
+      tabName: "contractItemList",
+    };
+  },
+  computed: {},
+  watch: {
+    "params.contractType": function (newProp) {
+      this.tabColumns = NewTabColumns.filter((element) =>
+        newProp === "1" ? element.key !== "contractItemList" : element
+      );
+      this.tabName = this.tabColumns[0].key;
+    },
+  },
+  methods: {
+    beforeOpen() {
+      const { deptName, deptId, name, id, orgName, orgId } =
+        this.$store.state.user;
+      this.params.puOrg = orgId;
+      this.params.puOrgName = orgName;
+      this.params.buyer = id;
+      this.params.buyerName = name;
+      this.params.puDept = deptId;
+      this.params.puDeptName = deptName;
+      this.fetchCode();
+    },
+    setVisible(prop) {
+      this.visible = prop;
+    },
+    async fetchCode() {
+      try {
+        this.loading = true;
+        this.params.code = await generateCode();
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    addTableRow(prop) {
+      const arr = this.tabColumns.find(
+        (element) => element.key === this.tabName
+      ).tableColumns;
+      console.log("arr", arr);
+      prop.push(initParams(arr, "key", "value"));
+    },
+    delTableRow(prop, index) {
+      prop.splice(index, 1);
+    },
+    // 取消
+    handleCancel() {
+      this.setVisible(false);
+      this.params = initParams(this.columns, "key", "value");
+    },
+    // 保存
+    handleSava() {
+      this.setVisible(false);
+    },
+    // 保存并新增
+    async handleSubmit() {
+      try {
+        const createById = this.params.buyer;
+        const createByName = this.params.buyerName;
+        const updateById = this.$store.state.user.id;
+        const updateByName = this.$store.state.user.name;
+        const { code, msg } = await add({
+          createById,
+          createByName,
+          updateById,
+          updateByName,
+          ...this.params,
+        });
+        if (code === 200) {
+          this.$notify.success({ title: msg });
+          this.setVisible(false);
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        // this.setVisible(false);
+      }
+    },
+  },
+  created() {
+    console.log("ADD CREATED");
+  },
+  mounted() {},
+  destroyed() {},
+};
+</script>
+<template>
+  <el-drawer
+    direction="btt"
+    size="100%"
+    :with-header="false"
+    :visible.sync="visible"
+    @open="beforeOpen"
+    @close="$emit('close')"
+  >
+    <el-form
+      v-loading="loading"
+      :size="size"
+      label-position="right"
+      label-width="135px"
+      :model="params"
+      :rules="rules"
+    >
+      <el-card
+        :body-style="{
+          padding: '20px',
+          display: 'flex',
+          'flex-wrap': 'wrap',
+        }"
+        style="margin: 10px"
+      >
+        <div
+          slot="header"
+          style="
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+          "
+        >
+          <h3>新增</h3>
+          <div style="text-align: right">
+            <el-button :size="size" @click="handleCancel">取 消</el-button>
+            <el-button :size="size" type="danger" @click="handleSava"
+              >保 存</el-button
+            >
+            <el-button :size="size" type="info" @click="handleSubmit">
+              新 增
+            </el-button>
+          </div>
+        </div>
+        <el-row>
+          <el-col
+            v-for="(column, index) in columns"
+            :key="index"
+            :span="column.span || 6"
+          >
+            <el-form-item :prop="column.key" :label="column.title">
+              <el-input
+                v-if="column.type === 'Input'"
+                v-model="params[column.key]"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              ></el-input>
+              <dr-input-dialog
+                v-if="column.type === 'InputDialog'"
+                v-model="params[column.key]"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                :title="column.title"
+                :type="column.config.componentName"
+                :data-mapping="column.config.dataMapping"
+                :source.sync="params"
+              >
+              </dr-input-dialog>
+              <el-input
+                v-if="column.type === 'Textarea'"
+                v-model="params[column.key]"
+                type="textarea"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              ></el-input>
+              <el-input-number
+                v-if="column.type === 'InputNumber'"
+                v-model="params[column.key]"
+                :controls-position="column.config.controlsPosition"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              ></el-input-number>
+              <el-select
+                v-if="column.type === 'Select'"
+                v-model="params[column.key]"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              >
+                <el-option
+                  v-for="item in dict.type[column.config.optionsName]"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+              <el-select
+                v-if="column.type === 'TagSelect'"
+                v-model="params[column.key]"
+                multiple
+                clearable
+                collapse-tags
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              >
+                <template #prefix>
+                  <el-icon
+                    class="el-icon-view"
+                    style="cursor: pointer"
+                    @click.stop="$message.info(234)"
+                  ></el-icon>
+                </template>
+                <el-option
+                  v-for="item in options"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+              <el-date-picker
+                v-if="column.type === 'DatePicker'"
+                v-model="params[column.key]"
+                :type="column.config.type"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :picker-options="column.pickerOptions"
+                style="width: 100%"
+              >
+              </el-date-picker>
+              <el-upload
+                v-if="column.type === 'Upload'"
+                :file-list="params[column.key]"
+                :disabled="column.disabled"
+                drag
+                action="https://sy.derom.com/document-center/fastdfs/upload"
+                multiple
+              >
+                <i class="el-icon-upload"></i>
+                <div class="el-upload__text">
+                  将文件拖到此处,或<em>点击上传</em>
+                </div>
+                <!-- <div class="el-upload__tip" slot="tip">
+                  只能上传jpg/png文件,且不超过500kb
+                </div> -->
+              </el-upload>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-card>
+      <el-card
+        :body-style="{
+          padding: '20px',
+          display: 'flex',
+          'flex-wrap': 'wrap',
+          position: 'relative',
+        }"
+        style="margin: 10px"
+      >
+        <el-tabs v-model="tabName" style="width: 100%">
+          <el-tab-pane
+            v-for="(column, index) in tabColumns"
+            :key="index"
+            :label="column.title"
+            :name="column.key"
+          >
+            <el-table :data="params[column.key]" style="width: 100%">
+              <el-table-column label="序号">
+                <template slot-scope="scope">
+                  {{ scope.$index + 1 }}
+                </template>
+              </el-table-column>
+              <el-table-column
+                v-for="(cColumn, cIndex) in column.tableColumns"
+                :key="cIndex"
+                :prop="cColumn.key"
+                :label="cColumn.title"
+                :width="cColumn.width"
+              >
+                <template slot-scope="scope">
+                  <span v-if="!cColumn.type">
+                    {{ scope.row[cColumn.key] }}</span
+                  >
+                  <el-input
+                    v-if="cColumn.type === 'Input'"
+                    v-model="scope.row[cColumn.key]"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    :size="size"
+                    style="width: 100%"
+                  ></el-input>
+                  <dr-input-dialog
+                    v-if="cColumn.type === 'InputDialog'"
+                    v-model="scope.row[cColumn.key]"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    :readonly="cColumn.readonly"
+                    :title="cColumn.title"
+                    :type="cColumn.config.componentName"
+                    :data-mapping="cColumn.config.dataMapping"
+                    :source.sync="scope.row"
+                    :size="size"
+                  >
+                  </dr-input-dialog>
+                  <el-input-number
+                    v-if="cColumn.type === 'InputNumber'"
+                    v-model="scope.row[cColumn.key]"
+                    :controls-position="cColumn.config.controlsPosition"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    :size="size"
+                    style="width: 100%"
+                  ></el-input-number>
+                </template>
+              </el-table-column>
+              <el-table-column fixed="right" label="操作" width="120">
+                <template slot-scope="scope">
+                  <el-button
+                    @click.native.prevent="
+                      delTableRow(params[tabName], scope.$index)
+                    "
+                    type="text"
+                    size="small"
+                  >
+                    删行
+                  </el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-tab-pane>
+        </el-tabs>
+        <el-row style="position: absolute; top: 20px; right: 20px">
+          <el-button :size="size" @click="addTableRow(params[tabName])"
+            >增行</el-button
+          >
+        </el-row>
+      </el-card>
+    </el-form>
+  </el-drawer>
+</template>

+ 0 - 0
src/views/purchase/purchase-contract/column.js → src/views/purchase/contract/column.js


+ 399 - 0
src/views/purchase/contract/edit/index.vue

@@ -0,0 +1,399 @@
+<script>
+import { Columns, TabColumns } from "../add/column";
+import {
+  edit,
+  item,
+  itemTableList,
+} from "@/api/business/purchase/contract";
+import { initColumns, initDicts, initRules, initParams } from "@/utils/init";
+
+const NewColumns = initColumns(Columns);
+const NewTabColumns = TabColumns.map((element) => ({
+  ...element,
+  tableColumns: initColumns(element.tableColumns),
+}));
+
+export default {
+  name: "EditDrawer",
+  dicts: initDicts(NewColumns),
+  components: {
+    DrInputDialog: () => import("@/components/input-dialog/index.vue"),
+  },
+  data() {
+    return {
+      size: "mini",
+      visible: false,
+      loading: false,
+      columns: NewColumns,
+      rules: initRules(NewColumns),
+      params: {
+        ...initParams(NewColumns),
+        contractItemList: [],
+        contractClauseList: [],
+        contractExpenseList: [],
+        contractAgreementList: [],
+        contractApplyOrgList: [],
+      },
+
+      tabColumns: NewTabColumns,
+      tabName: "contractItemList",
+    };
+  },
+  computed: {},
+  watch: {
+    "params.contractType": function (newProp) {
+      this.tabColumns = NewTabColumns.filter((element) =>
+        newProp === "1" ? element.key !== "contractItemList" : element
+      );
+      this.tabName = this.tabColumns[0].key;
+    },
+    tabName: function (newProp) {
+      const { id } = this.params;
+      this.fetchTable(id, newProp);
+    },
+  },
+  methods: {
+    setVisible(prop) {
+      this.visible = prop;
+    },
+    // 查询详细
+    async fetchItem(prop) {
+      try {
+        this.loading = true;
+        const { code, msg, data } = await item(prop);
+        if (code === 200) {
+          this.params = data;
+          this.$notify.success({ title: msg });
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    // 查询详情关联TABLE
+    async fetchTable(prop, name) {
+      try {
+        this.loading = true;
+        const { code, msg, rows } = await itemTableList({ id: prop }, name);
+        if (code === 200) {
+          this.params[name] = rows;
+          this.$notify.success({ title: msg });
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    // 新增行
+    addTableRow(prop) {
+      const arr = this.tabColumns.find(
+        (element) => element.key === this.tabName
+      ).tableColumns;
+      prop.push(initParams(arr, "key", "value"));
+    },
+    // 删除行
+    delTableRow(prop, index) {
+      prop.splice(index, 1);
+    },
+    // 取消
+    handleCancel() {
+      this.setVisible(false);
+      this.params = initParams(this.columns, "key", "value");
+    },
+    // 保存
+    handleSava() {
+      this.setVisible(false);
+    },
+    // 保存并新增
+    async handleSubmit() {
+      try {
+        const createById = this.params.buyer;
+        const createByName = this.params.buyerName;
+        const updateById = this.$store.state.user.id;
+        const updateByName = this.$store.state.user.name;
+        const { code, msg } = await edit({
+          createById,
+          createByName,
+          updateById,
+          updateByName,
+          ...this.params,
+        });
+        if (code === 200) {
+          this.$notify.success({ title: msg });
+          this.setVisible(false);
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        // this.setVisible(false);
+      }
+    },
+  },
+  created() {
+    console.log("ADD CREATED");
+  },
+  mounted() {},
+  destroyed() {},
+};
+</script>
+<template>
+  <el-drawer
+    direction="btt"
+    size="100%"
+    :with-header="false"
+    :visible.sync="visible"
+    @open="beforeOpen"
+    @close="$emit('close')"
+  >
+    <el-form
+      v-loading="loading"
+      :size="size"
+      label-position="right"
+      label-width="135px"
+      :model="params"
+      :rules="rules"
+    >
+      <el-card
+        :body-style="{
+          padding: '20px',
+          display: 'flex',
+          'flex-wrap': 'wrap',
+        }"
+        style="margin: 10px"
+      >
+        <div
+          slot="header"
+          style="
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+          "
+        >
+          <h3>编辑</h3>
+          <div style="text-align: right">
+            <el-button :size="size" @click="handleCancel">取 消</el-button>
+            <el-button :size="size" type="danger" @click="handleSava"
+              >更 新</el-button
+            >
+          </div>
+        </div>
+        <el-row>
+          <el-col
+            v-for="(column, index) in columns"
+            :key="index"
+            :span="column.span || 6"
+          >
+            <el-form-item :prop="column.key" :label="column.title">
+              <el-input
+                v-if="column.type === 'Input'"
+                v-model="params[column.key]"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              ></el-input>
+              <dr-input-dialog
+                v-if="column.type === 'InputDialog'"
+                v-model="params[column.key]"
+                :source.sync="params"
+                :type="column.config.componentName"
+                :data-mapping="column.config.dataMapping"
+                :title="column.title"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                :clearable="column.clearable"
+                :placeholder="column.placeholder"
+              >
+              </dr-input-dialog>
+              <el-input
+                v-if="column.type === 'Textarea'"
+                v-model="params[column.key]"
+                type="textarea"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              ></el-input>
+              <el-input-number
+                v-if="column.type === 'InputNumber'"
+                v-model="params[column.key]"
+                :controls-position="column.config.controlsPosition"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              ></el-input-number>
+              <el-select
+                v-if="column.type === 'Select'"
+                v-model="params[column.key]"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              >
+                <el-option
+                  v-for="item in dict.type[column.config.optionsName]"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+              <el-select
+                v-if="column.type === 'TagSelect'"
+                v-model="params[column.key]"
+                multiple
+                clearable
+                collapse-tags
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                style="width: 100%"
+              >
+                <template #prefix>
+                  <el-icon
+                    class="el-icon-view"
+                    style="cursor: pointer"
+                    @click.stop="$message.info(234)"
+                  ></el-icon>
+                </template>
+                <el-option
+                  v-for="item in options"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+              <el-date-picker
+                v-if="column.type === 'DatePicker'"
+                v-model="params[column.key]"
+                :type="column.config.type"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :picker-options="column.pickerOptions"
+                style="width: 100%"
+              >
+              </el-date-picker>
+              <el-upload
+                v-if="column.type === 'Upload'"
+                :file-list="params[column.key]"
+                :disabled="column.disabled"
+                drag
+                action="https://sy.derom.com/document-center/fastdfs/upload"
+                multiple
+              >
+                <i class="el-icon-upload"></i>
+                <div class="el-upload__text">
+                  将文件拖到此处,或<em>点击上传</em>
+                </div>
+                <!-- <div class="el-upload__tip" slot="tip">
+                  只能上传jpg/png文件,且不超过500kb
+                </div> -->
+              </el-upload>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-card>
+      <el-card
+        :body-style="{
+          padding: '20px',
+          display: 'flex',
+          'flex-wrap': 'wrap',
+          position: 'relative',
+        }"
+        style="margin: 10px"
+      >
+        <el-tabs v-model="tabName" style="width: 100%">
+          <el-tab-pane
+            v-for="(column, index) in tabColumns"
+            :key="index"
+            :label="column.title"
+            :name="column.key"
+          >
+            <el-table :data="params[column.key]" style="width: 100%">
+              <el-table-column label="序号">
+                <template slot-scope="scope">
+                  {{ scope.$index + 1 }}
+                </template>
+              </el-table-column>
+              <el-table-column
+                v-for="(cColumn, cIndex) in column.tableColumns"
+                :key="cIndex"
+                :prop="cColumn.key"
+                :label="cColumn.title"
+                :width="cColumn.width"
+              >
+                <template slot-scope="scope">
+                  <span v-if="!cColumn.type">
+                    {{ scope.row[cColumn.key] }}</span
+                  >
+                  <el-input
+                    v-if="cColumn.type === 'Input'"
+                    v-model="scope.row[cColumn.key]"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    :size="size"
+                    style="width: 100%"
+                  ></el-input>
+                  <dr-input-dialog
+                    v-if="cColumn.type === 'InputDialog'"
+                    v-model="scope.row[cColumn.key]"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    :readonly="cColumn.readonly"
+                    :title="cColumn.title"
+                    :type="cColumn.config.componentName"
+                    :data-mapping="cColumn.config.dataMapping"
+                    :source.sync="scope.row"
+                    :size="size"
+                  >
+                  </dr-input-dialog>
+                  <el-input-number
+                    v-if="cColumn.type === 'InputNumber'"
+                    v-model="scope.row[cColumn.key]"
+                    :controls-position="cColumn.config.controlsPosition"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    :size="size"
+                    style="width: 100%"
+                  ></el-input-number>
+                </template>
+              </el-table-column>
+              <el-table-column fixed="right" label="操作" width="120">
+                <template slot-scope="scope">
+                  <el-button
+                    @click.native.prevent="
+                      delTableRow(params[tabName], scope.$index)
+                    "
+                    type="text"
+                    size="small"
+                  >
+                    删行
+                  </el-button>
+                </template>
+              </el-table-column>
+            </el-table>
+          </el-tab-pane>
+        </el-tabs>
+        <el-row style="position: absolute; top: 20px; right: 20px">
+          <el-button :size="size" @click="addTableRow(params[tabName])"
+            >增行</el-button
+          >
+        </el-row>
+      </el-card>
+    </el-form>
+  </el-drawer>
+</template>

+ 35 - 19
src/views/purchase/purchase-contract/index.vue → src/views/purchase/contract/index.vue

@@ -1,6 +1,6 @@
 <script>
 import { TableColumns, SearchColumns } from "./column";
-import { list, remove } from "@/api/business/purchase/purchase-contract";
+import { list, remove } from "@/api/business/purchase/catalogue";
 import { initPage, initLayout, initPageSizes, initParams } from "@/utils/init";
 export default {
   name: "PuchaseContract",
@@ -11,17 +11,15 @@ export default {
   },
   data() {
     return {
+      size: "mini",
       loading: false,
-
-      pageSizes: initPageSizes(),
-      layout: initLayout(),
-      page: initPage(),
-
       searchColumns: SearchColumns,
       params: initParams(SearchColumns),
-
-      tableColumns: TableColumns,
       tableData: [],
+      tableColumns: TableColumns,
+      page: initPage(),
+      layout: initLayout(),
+      pageSizes: initPageSizes(),
     };
   },
   computed: {},
@@ -59,7 +57,7 @@ export default {
     // 重置操作
     handleResetList() {
       this.page = initPage();
-      this.params = initParams();
+      this.params = initParams(SearchColumns);
       this.fetchList(this.params, this.page);
     },
     // 刷新操作
@@ -128,11 +126,10 @@ export default {
     <add-drawer ref="AddDrawerFef" @close="handleResetList"></add-drawer>
     <edit-drawer ref="EditDrawerFef" @close="handleResetList"></edit-drawer>
     <el-form
-      size="mini"
+      :size="size"
       label-position="right"
       label-width="85px"
       :model="params"
-      style="padding: 20px 0 0 0"
     >
       <el-row :gutter="24">
         <el-col
@@ -152,25 +149,44 @@ export default {
           </el-form-item>
         </el-col>
         <el-col :xl="6" :lg="6" :md="8" :sm="12" :xs="24">
-          <el-button type="primary" size="mini" @click="handleQueryList"
-            >搜 索</el-button
-          >
-          <el-button size="mini" @click="handleResetList">重 置</el-button>
+          <el-button
+            circle
+            :size="size"
+            icon="el-icon-search"
+            @click="handleQueryList"
+          ></el-button>
+          <el-button
+            circle
+            :size="size"
+            icon="el-icon-refresh"
+            @click="handleResetList"
+          ></el-button>
         </el-col>
       </el-row>
     </el-form>
     <el-row :gutter="24" style="padding: 0 20px">
       <el-col :span="6">
-        <el-button size="mini" type="danger" @click="handleOpenAddDrawer">
-          新 增
+        <el-button
+          :size="size"
+          type="danger"
+          icon="el-icon-plus"
+          @click="handleOpenAddDrawer"
+        >
+          新增
+        </el-button>
+        <el-button
+          :size="size"
+          icon="el-icon-refresh-right"
+          @click="handleRefreshList"
+        >
+          刷新
         </el-button>
-        <el-button size="mini" @click="handleRefreshList"> 刷 新 </el-button>
       </el-col>
     </el-row>
     <el-table
       @row-dblclick="handleOpenSeeDrawer"
       :data="tableData"
-      size="mini"
+      :size="size"
       style="width: 100%; margin: 20px 0 0 0"
     >
       <el-table-column

+ 317 - 0
src/views/purchase/contract/see/index.vue

@@ -0,0 +1,317 @@
+<script>
+import { Columns, TabColumns } from "../add/column";
+import { item, itemTableList } from "@/api/business/purchase/contract";
+import { initColumns, initDicts, initRules, initParams } from "@/utils/init";
+
+const NewColumns = initColumns(Columns, { disabled: true, readonly: true });
+const NewTabColumns = TabColumns.map((element) => ({
+  ...element,
+  tableColumns: initColumns(element.tableColumns, {
+    disabled: true,
+    readonly: true,
+  }),
+}));
+
+export default {
+  name: "SeeDrawer",
+  dicts: initDicts(NewColumns),
+  data() {
+    return {
+      visible: false,
+      loading: false,
+      columns: NewColumns,
+      rules: initRules(NewColumns),
+      params: {
+        ...initParams(NewColumns),
+        contractItemList: [],
+        contractClauseList: [],
+        contractExpenseList: [],
+        contractAgreementList: [],
+        contractApplyOrgList: [],
+      },
+
+      tabColumns: NewTabColumns,
+      tabName: "contractItemList",
+    };
+  },
+  computed: {},
+  watch: {
+    "params.contractType": function (newProp) {
+      this.tabColumns = NewTabColumns.filter((element) =>
+        newProp === "1" ? element.key !== "contractItemList" : element
+      );
+      this.tabName = this.tabColumns[0].key;
+    },
+    tabName: function (newProp) {
+      const { id } = this.params;
+      this.fetchTable(id, newProp);
+    },
+  },
+  methods: {
+    setVisible(prop) {
+      this.visible = prop;
+    },
+    // 查询详细
+    async fetchItem(prop) {
+      try {
+        this.loading = true;
+        const { code, msg, data } = await item(prop);
+        if (code === 200) {
+          this.params = data;
+          this.$notify.success({ title: msg });
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    // 查询详情关联TABLE
+    async fetchTable(prop, name) {
+      try {
+        this.loading = true;
+        const { code, msg, rows } = await itemTableList({ id: prop }, name);
+        if (code === 200) {
+          this.params[name] = rows;
+          this.$notify.success({ title: msg });
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    // 取消操作
+    handleCancel() {
+      this.setVisible(false);
+      this.params = initParams(Columns);
+    },
+    // 编辑操作
+    handleOpenEditDrawer(prop) {
+      this.setVisible(false);
+      this.$parent.$parent.handleOpenEditDrawer(prop);
+    },
+  },
+  created() {},
+  mounted() {},
+  destroyed() {},
+};
+</script>
+<template>
+  <el-drawer
+    direction="btt"
+    size="100%"
+    :with-header="false"
+    :visible.sync="visible"
+    destroy-on-close
+  >
+    <el-form
+      v-loading="loading"
+      size="mini"
+      label-position="right"
+      label-width="135px"
+      :model="params"
+      :rules="rules"
+    >
+      <el-card
+        :body-style="{
+          padding: '20px',
+          display: 'flex',
+          'flex-wrap': 'wrap',
+        }"
+        style="margin: 10px"
+      >
+        <div
+          slot="header"
+          style="
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+          "
+        >
+          <h3>查看</h3>
+          <div style="text-align: right">
+            <el-button size="mini" @click="handleOpenEditDrawer(params)"
+              >编 辑</el-button
+            >
+            <el-button size="mini" @click="handleCancel">取 消</el-button>
+          </div>
+        </div>
+        <el-row>
+          <el-col
+            v-for="(column, index) in columns"
+            :key="index"
+            :span="column.span || 6"
+          >
+            <el-form-item :prop="column.key" :label="column.title">
+              <el-input
+                v-if="column.type === 'Textarea'"
+                v-model="params[column.key]"
+                type="textarea"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                style="width: 100%"
+              ></el-input>
+              <el-input-number
+                v-else-if="column.type === 'InputNumber'"
+                v-model="params[column.key]"
+                :controls-position="column.config.controlsPosition"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                style="width: 100%"
+              ></el-input-number>
+              <el-select
+                v-else-if="column.type === 'Select'"
+                v-model="params[column.key]"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                style="width: 100%"
+              >
+                <el-option
+                  v-for="item in dict.type[column.config.optionsName]"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                >
+                </el-option>
+              </el-select>
+              <el-date-picker
+                v-else-if="column.type === 'DatePicker'"
+                v-model="params[column.key]"
+                :type="column.config.type"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                :picker-options="column.pickerOptions"
+                style="width: 100%"
+              >
+              </el-date-picker>
+              <el-upload
+                v-else-if="column.type === 'Upload'"
+                :file-list="params[column.key]"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                drag
+                action="https://jsonplaceholder.typicode.com/posts/"
+                multiple
+              >
+                <i class="el-icon-upload"></i>
+                <div class="el-upload__text">
+                  将文件拖到此处,或<em>点击上传</em>
+                </div>
+                <div class="el-upload__tip" slot="tip">
+                  只能上传jpg/png文件,且不超过500kb
+                </div>
+              </el-upload>
+              <el-input
+                v-else
+                v-model="params[column.key]"
+                :placeholder="column.placeholder"
+                :clearable="column.clearable"
+                :disabled="column.disabled"
+                :readonly="column.readonly"
+                style="width: 100%"
+              ></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-card>
+      <el-card
+        :body-style="{
+          padding: '20px',
+          display: 'flex',
+          'flex-wrap': 'wrap',
+          position: 'relative',
+        }"
+        style="margin: 10px"
+      >
+        <el-tabs v-model="tabName" style="width: 100%">
+          <el-tab-pane
+            v-for="(column, index) in tabColumns"
+            :key="index"
+            :label="column.title"
+            :name="column.key"
+          >
+            <el-table :data="params[column.key]" style="width: 100%">
+              <el-table-column
+                v-for="(cColumn, cIndex) in column.tableColumns"
+                :key="cIndex"
+                :prop="cColumn.key"
+                :label="cColumn.title"
+                :width="cColumn.width"
+              >
+                <template slot-scope="scope">
+                  <el-tag v-if="cColumn.key === 'index'">
+                    {{ scope.$index + 1 }}
+                  </el-tag>
+                  <el-input
+                    v-if="cColumn.type === 'Input'"
+                    v-model="scope.row[cColumn.key]"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    size="mini"
+                    style="width: 100%"
+                  ></el-input>
+                  <el-input-number
+                    v-if="cColumn.type === 'InputNumber'"
+                    v-model="scope.row[cColumn.key]"
+                    :controls-position="cColumn.config.controlsPosition"
+                    :placeholder="cColumn.placeholder"
+                    :clearable="cColumn.clearable"
+                    :disabled="cColumn.disabled"
+                    size="mini"
+                    style="width: 100%"
+                  ></el-input-number>
+                  <el-input
+                    v-if="column.type === 'InputDialog'"
+                    v-model="params[column.key]"
+                    :placeholder="column.placeholder"
+                    :clearable="column.clearable"
+                    :disabled="column.disabled"
+                    :readonly="column.readonly"
+                    style="width: 100%; cursor: pointer"
+                    @click.native.stop="openAsyncInputDialog(column, params)"
+                  >
+                    <template #suffix>
+                      <el-icon class="el-icon-thumb"></el-icon>
+                    </template>
+                  </el-input>
+                </template>
+              </el-table-column>
+              <!-- <el-table-column fixed="right" label="操作" width="120">
+                <template slot-scope="scope">
+                  <el-button
+                    @click.native.prevent="
+                      delTableRow(params[tabName], scope.$index)
+                    "
+                    type="text"
+                    size="small"
+                  >
+                    删行
+                  </el-button>
+                </template>
+              </el-table-column> -->
+            </el-table>
+          </el-tab-pane>
+        </el-tabs>
+        <!-- <el-row style="position: absolute; top: 20px; right: 20px">
+          <el-button size="mini" @click="addTableRow(params[tabName])"
+            >增行</el-button
+          >
+        </el-row> -->
+      </el-card>
+    </el-form>
+  </el-drawer>
+</template>

+ 3 - 3
src/views/purchase/purchase-content/index.vue

@@ -1,7 +1,7 @@
 <script>
-import { taskList } from "@/api/business/purchase/purchase-task";
-// import AddPurchaseTaskDrawer from "./add-purchase-task.vue";
-// import SeePurchaseTaskDrawer from "./see-purchase-task.vue";
+import { taskList } from "@/api/business/purchase/task";
+// import AddPurchaseTaskDrawer from "./add-task.vue";
+// import SeePurchaseTaskDrawer from "./see-task.vue";
 // import DirectSourcingTable from "./direct-sourcing.vue";
 export default {
   name: "PuchaseTask",

+ 1 - 1
src/views/purchase/purchase-order/add/index.vue

@@ -14,7 +14,7 @@ export default {
   name: "AddPurchaseContractDrawer",
   dicts: initDicts(NewColumns),
   components: {
-    DrInputDialog: () => import("@/views/input-dialog/index.vue"),
+    DrInputDialog: () => import("@/components/input-dialog/index.vue"),
   },
 
   data() {

+ 1 - 1
src/views/purchase/purchase-order/edit/index.vue

@@ -13,7 +13,7 @@ export default {
   name: "EditPurchaseContractDrawer",
   dicts: initDicts(NewColumns),
   components: {
-    DrInputDialog: () => import("@/views/input-dialog/index.vue"),
+    DrInputDialog: () => import("@/components/input-dialog/index.vue"),
   },
   data() {
     return {

+ 0 - 151
src/views/purchase/purchase-task/add-purchase-task.vue

@@ -1,151 +0,0 @@
-<script>
-import { add } from "@/api/business/purchase/purchase-contract";
-import { arr2obj } from "@/utils/data-transform";
-import {
-  initDicts,
-  initRules,
-  initParams,
-} from "@/utils/init";
-import { initColumns } from "./config/add";
-
-export default {
-  name: "AddPurchaseTaskDrawer",
-  dicts: initDicts(initColumns()),
-  data() {
-    return {
-      visible: false,
-      columns: initColumns(),
-      rules: initRules(initColumns()),
-      params: initParams(initColumns()),
-      currentComponent: { name: "", title: "", value: "", row: {} },
-    };
-  },
-  computed: {},
-  watch: {},
-  methods: {
-    setVisible(prop) {
-      this.visible = prop;
-    },
-    //
-    openAsyncInputDialog(prop, type) {
-      try {
-        const {
-          key,
-          title,
-          config: { componentName },
-        } = prop;
-        this.currentComponent.row = prop;
-        this.currentComponent.title = title;
-        this.currentComponent.name = componentName;
-        if (type === "change") {
-          this.currentComponent.value = this.params[key];
-        }
-        if (type === "click") {
-          this.currentComponent.value = "";
-        }
-        this.$nextTick(() => {
-          const { setVisible } = this.$refs[componentName];
-          setVisible(true);
-        });
-      } catch (err) {
-        this.$notify.error({ title: "error", message: err });
-      } finally {
-      }
-    },
-    updateParams(prop) {
-      const {
-        config: { dataMapping },
-      } = this.currentComponent.row;
-      for (let key in dataMapping) {
-        this.params[key] = prop[dataMapping[key]];
-      }
-    },
-    beforeOpen() { },
-  },
-  created() {
-    console.log(this.params);
-  },
-  mounted() { },
-  destroyed() { },
-};
-</script>
-<template>
-  <el-drawer direction="btt" size="100%" :with-header="false" :visible.sync="visible" @open="beforeOpen">
-    <el-card :body-style="{
-      padding: '20px',
-      display: 'flex',
-      'flex-wrap': 'wrap',
-    }" style="margin: 10px">
-      <div slot="header" style="
-          display: flex;
-          justify-content: space-between;
-          align-items: center;
-        ">
-        <h3>新增</h3>
-        <div style="text-align: right">
-          <el-button size="mini" @click="cancel">取消</el-button>
-          <el-button size="mini" type="danger" @click="sava">保存</el-button>
-          <el-button size="mini" type="info" @click="submitSava">
-            保存并新增
-          </el-button>
-        </div>
-      </div>
-      <component v-if="currentComponent.name" :is="currentComponent.name" :ref="currentComponent.name"
-        :title="currentComponent.title" :value="currentComponent.value" @confirm="updateParams"></component>
-      <el-row>
-        <el-form size="mini" label-position="right" label-width="135px" :model="params" :rules="rules">
-          <el-col v-for="(column, index) in columns" :key="index" :span="column.span || 6">
-            <el-form-item :prop="column.key" :label="column.title">
-              <el-input v-if="column.type === 'Input'" v-model="params[column.key]" :placeholder="column.placeholder"
-                :clearable="column.clearable" :disabled="column.disabled" style="width: 100%"></el-input>
-              <el-input v-if="column.type === 'InputDialog'" v-model="params[column.key]"
-                :placeholder="column.placeholder" :clearable="column.clearable" :disabled="column.disabled"
-                style="width: 100%" @blur="openAsyncInputDialog(column, 'change')"
-                @change="openAsyncInputDialog(column, 'change')">
-                <template #suffix>
-                  <el-icon class="el-icon-s-operation" style="cursor: pointer"
-                    @click.native.stop="openAsyncInputDialog(column, 'click')"></el-icon>
-                </template>
-              </el-input>
-              <el-input v-if="column.type === 'Textarea'" v-model="params[column.key]" type="textarea"
-                :placeholder="column.placeholder" :clearable="column.clearable" :disabled="column.disabled"
-                style="width: 100%"></el-input>
-              <el-input-number v-if="column.type === 'InputNumber'" v-model="params[column.key]" :controls-position="column.config && column.config.controlsPosition
-                " :placeholder="column.placeholder" :clearable="column.clearable" :disabled="column.disabled"
-                style="width: 100%"></el-input-number>
-              <el-select v-if="column.type === 'Select'" v-model="params[column.key]" :placeholder="column.placeholder"
-                :clearable="column.clearable" :disabled="column.disabled" style="width: 100%">
-                <el-option v-for="item in dict.type[column.config.optionsName]" :key="item.value" :label="item.label"
-                  :value="item.value">
-                </el-option>
-              </el-select>
-              <el-select v-if="column.type === 'TagSelect'" v-model="params[column.key]" multiple clearable collapse-tags
-                :placeholder="column.placeholder" :clearable="column.clearable" :disabled="column.disabled"
-                style="width: 100%">
-                <template #prefix>
-                  <el-icon class="el-icon-s-operation" style="cursor: pointer" @click.stop="$message.info(234)"></el-icon>
-                </template>
-                <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
-                </el-option>
-              </el-select>
-              <el-date-picker v-if="column.type === 'DatePicker'" v-model="params[column.key]" :type="column.config.type"
-                :placeholder="column.placeholder" :clearable="column.clearable" :disabled="column.disabled"
-                :picker-options="column.pickerOptions" style="width: 100%">
-              </el-date-picker>
-              <el-upload v-if="column.type === 'Upload'" :file-list="params[column.key]" :disabled="column.disabled" drag
-                action="https://jsonplaceholder.typicode.com/posts/" multiple>
-                <i class="el-icon-upload"></i>
-                <div class="el-upload__text">
-                  将文件拖到此处,或<em>点击上传</em>
-                </div>
-                <div class="el-upload__tip" slot="tip">
-                  只能上传jpg/png文件,且不超过500kb
-                </div>
-              </el-upload>
-            </el-form-item>
-          </el-col>
-        </el-form>
-      </el-row>
-    </el-card>
-  </el-drawer>
-</template>

+ 0 - 386
src/views/purchase/purchase-task/direct-sourcing.vue

@@ -1,386 +0,0 @@
-<script>
-export default {
-  name: "DirectSourcing",
-  components: {},
-  data() {
-    const tableColumns = [
-      { title: "价格来源", key: "a" },
-      { title: "供应商", key: "b" },
-      { title: "采购组织", key: "c" },
-      { title: "客户", key: "d" },
-      { title: "价格类型", key: "e" },
-      { title: "配送价", key: "f" },
-      { title: "币种", key: "g" },
-      { title: "价格有效期", key: "h" },
-      { title: "税率", key: "i" },
-      { title: "协议单价", key: "j" },
-      {
-        title: "未执行量",
-        key: "k",
-        edit: true,
-        editConfig: { type: "InputNumber", controlsPosition: "right" },
-      },
-      {
-        title: "采购量",
-        key: "l",
-        edit: true,
-        editConfig: { type: "InputNumber", controlsPosition: "right" },
-      },
-      {
-        title: "计划到货",
-        key: "m",
-        edit: true,
-        editConfig: { type: "DatePicker", showType: "date" },
-      },
-      {
-        title: "期望到货",
-        key: "n",
-        edit: true,
-        editConfig: { type: "DatePicker", showType: "date" },
-      },
-      {
-        title: "备注",
-        key: "o",
-        edit: true,
-        editConfig: { type: "Textarea" },
-      },
-    ];
-    const initTableColumns = () => tableColumns;
-    return {
-      tableColumns: initTableColumns(),
-      data: [
-        {
-          a: 1,
-          b: 1,
-          c: 1,
-          d: 1,
-          e: 1,
-          f: 1,
-          g: 1,
-          h: 1,
-          i: 1,
-          j: 1,
-          k: 1,
-          l: 1,
-          m: 1,
-          n: 1,
-          o: 1,
-        },
-        {
-          a: 1,
-          b: 1,
-          c: 1,
-          d: 1,
-          e: 1,
-          f: 1,
-          g: 1,
-          h: 1,
-          i: 1,
-          j: 1,
-          k: 1,
-          l: 1,
-          m: 1,
-          n: 1,
-          o: 1,
-        },
-        {
-          a: 1,
-          b: 1,
-          c: 1,
-          d: 1,
-          e: 1,
-          f: 1,
-          g: 1,
-          h: 1,
-          i: 1,
-          j: 1,
-          k: 1,
-          l: 1,
-          m: 1,
-          n: 1,
-          o: 1,
-        },
-        {
-          a: 1,
-          b: 1,
-          c: 1,
-          d: 1,
-          e: 1,
-          f: 1,
-          g: 1,
-          h: 1,
-          i: 1,
-          j: 1,
-          k: 1,
-          l: 1,
-          m: 1,
-          n: 1,
-          o: 1,
-        },
-        {
-          a: 1,
-          b: 1,
-          c: 1,
-          d: 1,
-          e: 1,
-          f: 1,
-          g: 1,
-          h: 1,
-          i: 1,
-          j: 1,
-          k: 1,
-          l: 1,
-          m: 1,
-          n: 1,
-          o: 1,
-        },
-        {
-          a: 1,
-          b: 1,
-          c: 1,
-          d: 1,
-          e: 1,
-          f: 1,
-          g: 1,
-          h: 1,
-          i: 1,
-          j: 1,
-          k: 1,
-          l: 1,
-          m: 1,
-          n: 1,
-          o: 1,
-        },
-        {
-          a: 1,
-          b: 1,
-          c: 1,
-          d: 1,
-          e: 1,
-          f: 1,
-          g: 1,
-          h: 1,
-          i: 1,
-          j: 1,
-          k: 1,
-          l: 1,
-          m: 1,
-          n: 1,
-          o: 1,
-        },
-        {
-          a: 1,
-          b: 1,
-          c: 1,
-          d: 1,
-          e: 1,
-          f: 1,
-          g: 1,
-          h: 1,
-          i: 1,
-          j: 1,
-          k: 1,
-          l: 1,
-          m: 1,
-          n: 1,
-          o: 1,
-        },
-        {
-          a: 1,
-          b: 1,
-          c: 1,
-          d: 1,
-          e: 1,
-          f: 1,
-          g: 1,
-          h: 1,
-          i: 1,
-          j: 1,
-          k: 1,
-          l: 1,
-          m: 1,
-          n: 1,
-          o: 1,
-        },
-        {
-          a: 1,
-          b: 1,
-          c: 1,
-          d: 1,
-          e: 1,
-          f: 1,
-          g: 1,
-          h: 1,
-          i: 1,
-          j: 1,
-          k: 1,
-          l: 1,
-          m: 1,
-          n: 1,
-          o: 1,
-        },
-        {
-          a: 1,
-          b: 1,
-          c: 1,
-          d: 1,
-          e: 1,
-          f: 1,
-          g: 1,
-          h: 1,
-          i: 1,
-          j: 1,
-          k: 1,
-          l: 1,
-          m: 1,
-          n: 1,
-          o: 1,
-        },
-        {
-          a: 1,
-          b: 1,
-          c: 1,
-          d: 1,
-          e: 1,
-          f: 1,
-          g: 1,
-          h: 1,
-          i: 1,
-          j: 1,
-          k: 1,
-          l: 1,
-          m: 1,
-          n: 1,
-          o: 1,
-        },
-        {
-          a: 1,
-          b: 1,
-          c: 1,
-          d: 1,
-          e: 1,
-          f: 1,
-          g: 1,
-          h: 1,
-          i: 1,
-          j: 1,
-          k: 1,
-          l: 1,
-          m: 1,
-          n: 1,
-          o: 1,
-        },
-        {
-          a: 1,
-          b: 1,
-          c: 1,
-          d: 1,
-          e: 1,
-          f: 1,
-          g: 1,
-          h: 1,
-          i: 1,
-          j: 1,
-          k: 1,
-          l: 1,
-          m: 1,
-          n: 1,
-          o: 1,
-        },
-        {
-          a: 1,
-          b: 1,
-          c: 1,
-          d: 1,
-          e: 1,
-          f: 1,
-          g: 1,
-          h: 1,
-          i: 1,
-          j: 1,
-          k: 1,
-          l: 1,
-          m: 1,
-          n: 1,
-          o: 1,
-        },
-      ],
-      page: { pageNum: 1, pageSize: 25 },
-      total: 0,
-      pageSizes: [25, 50, 100],
-    };
-  },
-  computed: {},
-  watch: {
-    data: {
-      handler: function (n) {
-        console.log(n);
-      },
-      deep: true,
-    },
-  },
-  methods: {},
-  created() {},
-  mounted() {},
-  destroyed() {},
-};
-</script>
-
-<template>
-  <div class="directSourcing" style="height: 50vh">
-    <el-table :data="data" height="calc(50vh)" style="width: 100%">
-      <el-table-column
-        v-for="(column, index) in tableColumns"
-        :key="index"
-        :prop="column.key"
-        :label="column.title"
-        :width="column.width || 180"
-        :show-overflow-tooltip="column.showOverflowTooltip || true"
-      >
-        <template slot-scope="scope">
-          <el-input-number
-            v-if="column.edit && column.editConfig.type === 'InputNumber'"
-            v-model="scope.row[column.key]"
-            :controls-position="column.editConfig.controlsPosition"
-            :min="column.editConfig.min"
-            :max="column.editConfig.max"
-            :size="column.editConfig.size || 'mini'"
-            :placeholder="column.editConfig.placeholder"
-            style="width: 90%"
-          ></el-input-number>
-          <el-date-picker
-            v-else-if="column.edit && column.editConfig.type === 'DatePicker'"
-            v-model="scope.row[column.key]"
-            :type="column.editConfig.showType"
-            :picker-options="column.editConfig.pickerOptions"
-            :size="column.editConfig.size || 'mini'"
-            :placeholder="column.editConfig.placeholder"
-            style="width: 90%"
-          ></el-date-picker>
-          <el-input
-            v-else-if="column.edit && column.editConfig.type === 'Textarea'"
-            v-model="scope.row[column.key]"
-            type="textarea"
-            :autosize="column.editConfig.autosize || true"
-            :size="column.editConfig.size || 'mini'"
-            style="width: 90%"
-          ></el-input>
-          <span v-else>{{ scope.row[column.key] }}</span>
-        </template>
-      </el-table-column>
-    </el-table>
-    <el-pagination
-      @size-change="handleSizeChange"
-      @current-change="handleCurrentChange"
-      :total="total"
-      :page-sizes="pageSizes"
-      :page-size="page.pageSize"
-      :current-page="page.pageNum"
-      hide-on-single-page
-      layout="total, prev, pager, next, sizes, jumper"
-    >
-    </el-pagination>
-  </div>
-</template>
-
-<style scoped></style>

+ 0 - 598
src/views/purchase/purchase-task/index.vue

@@ -1,598 +0,0 @@
-<script>
-import { taskList } from "@/api/business/purchase/purchase-task";
-import AddPurchaseTaskDrawer from "./add-purchase-task.vue";
-import SeePurchaseTaskDrawer from "./see-purchase-task.vue";
-import DirectSourcingTable from "./direct-sourcing.vue";
-export default {
-  name: "PuchaseTask",
-  components: {
-    AddPurchaseTaskDrawer,
-    SeePurchaseTaskDrawer,
-    DirectSourcingTable,
-  },
-  data() {
-    const arr2Obj = function (data, keyName, valueName) {
-      return Object.fromEntries(
-        data.map((item) => [item[keyName], item[valueName]])
-      );
-    };
-    const searchColumns = [
-      { title: "物料分类", key: "", type: "TagSelect" },
-      { title: "物料", key: "", type: "TagSelect" },
-      { title: "物料编码", key: "material", type: "Input" },
-      { title: "物料描述", key: "materialDesc", type: "Input" },
-      { title: "需求组织", key: "", type: "TagSelect" },
-      { title: "需求日期", key: "", type: "DatePicker" },
-      { title: "计划人员", key: "", type: "TagSelect" },
-      { title: "采购组织", key: "", type: "TagSelect" },
-      { title: "创建时间", key: "", type: "DatePicker" },
-      { title: "采购员", key: "", type: "TagSelect" },
-      { title: "状态", key: "", type: "Select" },
-      {
-        title: "来源单据号",
-        key: "",
-        type: "Input",
-        placeholder: "请输入来源单据号,多个用英文逗号分割",
-      },
-      { title: "收货组织", key: "", type: "TagSelect" },
-      { title: "采购分类", key: "", type: "Input" },
-      // { title: "受理人", key: "", type: "TagSelect" },
-      { title: "项目", key: "", type: "TagSelect" },
-      { title: "需求部门", key: "", type: "TagSelect" },
-      { title: "需求人", key: "", type: "TagSelect" },
-      { title: "ERP信息", key: "", type: "Input" },
-    ];
-    const initSearchColumns = () => searchColumns;
-    const initSearchParams = () => arr2Obj(initSearchColumns(), "key", "value");
-    const tableColumns = [
-      {
-        title: "物料名称",
-        key: "materialName",
-      },
-      {
-        title: "物料编码",
-        key: "material",
-      },
-      {
-        title: "来源单据号",
-        key: "material",
-      },
-      {
-        title: "来源单据行号",
-        key: "material",
-      },
-      {
-        title: "采购数量",
-        key: "material",
-      },
-      {
-        title: "采购单位",
-        key: "material",
-      },
-      {
-        title: "采购换算率",
-        key: "material",
-      },
-      {
-        title: "主数量",
-        key: "material",
-      },
-      {
-        title: "主计量单位",
-        key: "material",
-      },
-      {
-        title: "计价单位",
-        key: "material",
-      },
-      {
-        title: "计价换算率",
-        key: "material",
-      },
-      {
-        title: "计价数量",
-        key: "material",
-      },
-      {
-        title: "未执行数量",
-        key: "material",
-      },
-      {
-        title: "主未执行数量",
-        key: "material",
-      },
-      {
-        title: "计价未执行数量",
-        key: "material",
-      },
-      {
-        title: "已执行数量",
-        key: "material",
-      },
-      {
-        title: "交易类型",
-        key: "material",
-      },
-      {
-        title: "分配日期",
-        key: "material",
-      },
-      {
-        title: "SKU编码",
-        key: "material",
-      },
-      {
-        title: "SKU名称",
-        key: "material",
-      },
-      {
-        title: "SKU规格说明",
-        key: "material",
-      },
-      {
-        title: "SKU型号",
-        key: "material",
-      },
-      {
-        title: "SKU规格",
-        key: "material",
-      },
-      {
-        title: "产品规格",
-        key: "material",
-      },
-      {
-        title: "产品型号",
-        key: "material",
-      },
-      {
-        title: "物料描述",
-        key: "material",
-      },
-      {
-        title: "品牌",
-        key: "material",
-      },
-      {
-        title: "计划价",
-        key: "material",
-      },
-      {
-        title: "需求附件",
-        key: "material",
-      },
-      {
-        title: "物料附件",
-        key: "material",
-      },
-      {
-        title: "项目",
-        key: "material",
-      },
-      {
-        title: "建议供应商",
-        key: "material",
-      },
-      {
-        title: "需求组织",
-        key: "material",
-      },
-      {
-        title: "需求部门",
-        key: "material",
-      },
-      {
-        title: "需求人",
-        key: "material",
-      },
-      {
-        title: "已下单采购数量",
-        key: "material",
-      },
-      {
-        title: "采购组织",
-        key: "material",
-      },
-      {
-        title: "采购员",
-        key: "material",
-      },
-      {
-        title: "计划员",
-        key: "material",
-      },
-      {
-        title: "计划部门",
-        key: "material",
-      },
-      {
-        title: "联系电话",
-        key: "material",
-      },
-      {
-        title: "采购分类",
-        key: "material",
-      },
-      {
-        title: "收货人",
-        key: "material",
-      },
-      {
-        title: "收货地址",
-        key: "material",
-      },
-      {
-        title: "收货人电话",
-        key: "material",
-      },
-      {
-        title: "需求时间",
-        key: "material",
-      },
-      // {
-      //   title: "受理状态",
-      //   key: "material",
-      // },
-      {
-        title: "状态",
-        key: "material",
-      },
-      // {
-      //   title: "受理人",
-      //   key: "material",
-      // },
-      {
-        title: "委托受理人",
-        key: "material",
-      },
-      {
-        title: "弹性分单条件",
-        key: "material",
-      },
-      {
-        title: "备注",
-        key: "material",
-      },
-      {
-        title: "ERP相关信息",
-        key: "material",
-      },
-      {
-        title: "创建时间",
-        key: "material",
-      },
-      {
-        title: "最新价格",
-        key: "material",
-      },
-      {
-        title: "生产厂家",
-        key: "material",
-      },
-      {
-        title: "报价供应商",
-        key: "material",
-      },
-      {
-        title: "历史最低价",
-        key: "material",
-      },
-      {
-        title: "生产订单状态",
-        key: "material",
-      },
-      // {
-      //   title: "寻源退回原因",
-      //   key: "material",
-      // },
-      {
-        title: "收货仓库档案编码",
-        key: "material",
-      },
-      {
-        title: "自定义项16",
-        key: "material",
-      },
-      {
-        title: "收货客户",
-        key: "material",
-      },
-      {
-        title: "入库仓库",
-        key: "material",
-      },
-      {
-        title: "货位",
-        key: "material",
-      },
-      {
-        title: "指定供应商",
-        key: "material",
-      },
-      {
-        title: "单位",
-        key: "material",
-      },
-      {
-        title: "自定义项15",
-        key: "material",
-      },
-      {
-        title: "收货地址",
-        key: "material",
-      },
-      {
-        title: "收货联系人",
-        key: "material",
-      },
-      {
-        title: "需求来源",
-        key: "material",
-      },
-    ];
-    const initTableColumns = () => tableColumns;
-    const initTableData = () => {
-      const data = [];
-      for (let index = 0; index < 25; index++) {
-        data.push({ materialName: index });
-      }
-      return data;
-    };
-    return {
-      loading: false,
-      isSimpleSearch: true,
-      searchColumns: initSearchColumns(),
-      searchParams: {
-        isAsc: "desc",
-        reasonable: "",
-        orderByColumn: "",
-        ...initSearchParams(),
-      },
-      tableColumns: initTableColumns(),
-      tableData: initTableData(),
-      page: { pageNum: 1, pageSize: 25 },
-      total: 0,
-      pageSizes: [25, 50, 100],
-    };
-  },
-  computed: {
-    showSearchColumns() {
-      return this.isSimpleSearch
-        ? this.searchColumns.slice(0, 4)
-        : this.searchColumns;
-    },
-  },
-  //   watch: {
-  //     $route: {
-  //       handler: function (route) {
-  //         this.redirect = route.query && route.query.redirect;
-  //       },
-  //       immediate: true,
-  //     },
-  //   },
-  created() {
-    // this.fetchTaskList();
-    console.log("Vue", this);
-  },
-  methods: {
-    async fetchTaskList() {
-      this.loading = true;
-      try {
-        const { code, msg, rows, total } = await taskList({
-          ...this.page,
-          ...this.searchParams,
-        });
-        if (code === 200) {
-          this.total = total;
-          this.tableData = rows;
-          this.$notify.success({ title: msg });
-        } else {
-          this.$notify.warning({ title: msg });
-        }
-      } catch (err) {
-        this.$notify.error({ title: "error", message: err });
-      } finally {
-        this.loading = false;
-      }
-    },
-    handleSearchChange() {
-      this.isSimpleSearch = !this.isSimpleSearch;
-      this.$notify.info({
-        title: this.isSimpleSearch ? "Simple Search" : "All Search",
-      });
-    },
-    handleSizeChange() {},
-    handleCurrentChange() {},
-    handleOpenAddDrawer() {
-      const { setVisible } = this.$refs.addDrawerFef;
-      setTimeout(() => {
-        setVisible(true);
-        this.$notify.info("Open Add Drawer");
-      }, 250);
-    },
-    handleOpenSeeDrawer() {
-      const { setVisible } = this.$refs.seeDrawerFef;
-      setVisible(true);
-      setTimeout(() => {
-        this.$notify.info("Open See Drawer");
-      }, 250);
-    },
-  },
-};
-</script>
-
-<template>
-  <el-card
-    v-loading="loading"
-    style="width: calc(100% - 24px); height: 100%; margin: 10px"
-    :body-style="{ padding: 0 }"
-  >
-    <AddPurchaseTaskDrawer ref="addDrawerFef"></AddPurchaseTaskDrawer>
-    <SeePurchaseTaskDrawer ref="seeDrawerFef"></SeePurchaseTaskDrawer>
-    <el-form
-      size="mini"
-      label-position="right"
-      label-width="85px"
-      :model="searchParams"
-      style="padding: 20px 0 0 0"
-    >
-      <el-row :gutter="24">
-        <el-col :span="22">
-          <el-row :gutter="20">
-            <el-col
-              v-for="column in showSearchColumns"
-              :key="column.title"
-              :xl="6"
-              :lg="6"
-              :md="8"
-              :sm="12"
-              :xs="24"
-            >
-              <el-form-item :prop="column.key" :label="column.title">
-                <el-input
-                  v-model="searchParams[column.key]"
-                  :placeholder="column.placeholder"
-                ></el-input>
-              </el-form-item>
-            </el-col>
-          </el-row>
-        </el-col>
-        <el-col :span="2">
-          <el-row :gutter="24">
-            <el-col :span="24">
-              <el-button type="primary" size="mini">搜索</el-button>
-            </el-col>
-            <el-col
-              v-show="!isSimpleSearch"
-              :span="24"
-              style="margin: 10px 0 0"
-            >
-              <el-button size="mini">重置</el-button>
-            </el-col>
-          </el-row>
-        </el-col>
-      </el-row>
-    </el-form>
-    <el-divider>
-      <i
-        :class="isSimpleSearch ? 'el-icon-arrow-down' : 'el-icon-arrow-up'"
-        style="cursor: pointer"
-        @click="handleSearchChange"
-      ></i>
-    </el-divider>
-    <el-row :gutter="24" style="padding: 0 20px">
-      <el-col :span="6">123</el-col>
-      <el-col :span="18" style="text-align: right">
-        <el-button
-          size="mini"
-          type="danger"
-          style="margin: 0 10px 0 0"
-          @click="handleOpenAddDrawer"
-        >
-          新增
-        </el-button>
-        <el-dropdown placement="bottom-start">
-          <el-button size="mini" style="margin: 0 10px 0 0">
-            发布
-            <i class="el-icon-arrow-down el-icon--right"></i>
-          </el-button>
-          <el-dropdown-menu slot="dropdown">
-            <el-dropdown-item>发布寻源</el-dropdown-item>
-            <el-dropdown-item>发布委托</el-dropdown-item>
-            <el-dropdown-item>采购方案</el-dropdown-item>
-          </el-dropdown-menu>
-        </el-dropdown>
-
-        <el-dropdown placement="bottom-start">
-          <el-button
-            size="mini"
-            style="border-right: 0; border-radius: 3px 0 0 3px"
-          >
-            首次协议直采
-            <i class="el-icon-arrow-down el-icon--right"></i>
-          </el-button>
-          <el-dropdown-menu slot="dropdown">
-            <el-dropdown-item>首次协议直采</el-dropdown-item>
-            <el-dropdown-item>余量协议直采</el-dropdown-item>
-          </el-dropdown-menu>
-        </el-dropdown>
-        <el-dropdown placement="bottom-start">
-          <el-button size="mini" style="border-right: 0; border-radius: 0">
-            跟单采购
-            <i class="el-icon-arrow-down el-icon--right"></i>
-          </el-button>
-          <el-dropdown-menu slot="dropdown">
-            <el-dropdown-item>按合同(普通)取价</el-dropdown-item>
-          </el-dropdown-menu>
-        </el-dropdown>
-        <el-button size="mini" style="border-right: 0; border-radius: 0">
-          Excel导出
-        </el-button>
-        <el-button
-          size="mini"
-          style="margin: 0; border-right: 0; border-radius: 0"
-        >
-          退回请购
-        </el-button>
-        <el-dropdown placement="bottom-start">
-          <el-button size="mini" style="border-right: 0; border-radius: 0">
-            清单采购
-            <i class="el-icon-arrow-down el-icon--right"></i>
-          </el-button>
-          <el-dropdown-menu slot="dropdown">
-            <el-dropdown-item>商超匹配下单</el-dropdown-item>
-          </el-dropdown-menu>
-        </el-dropdown>
-        <el-button
-          size="mini"
-          disabled
-          style="margin: 0 10px 0 0; border-radius: 0 3px 3px 0"
-        >
-          一键合同下单
-        </el-button>
-        <el-button size="mini" style="margin: 0 10px 0 0">删除</el-button>
-        <el-dropdown placement="bottom-end">
-          <el-button size="mini">
-            更多
-            <i class="el-icon-arrow-down el-icon--right"></i>
-          </el-button>
-          <el-dropdown-menu slot="dropdown">
-            <el-dropdown-item>抢单</el-dropdown-item>
-            <el-dropdown-item>批量修改收货组织</el-dropdown-item>
-            <el-dropdown-item>批量退回</el-dropdown-item>
-            <el-dropdown-item>退回需求申请</el-dropdown-item>
-            <el-dropdown-item>刷新缓存</el-dropdown-item>
-          </el-dropdown-menu>
-        </el-dropdown>
-      </el-col>
-    </el-row>
-    <el-table
-      @row-dblclick="handleOpenSeeDrawer"
-      :data="tableData"
-      size="mini"
-      style="width: 100%; margin: 20px 0 0 0"
-    >
-      <el-table-column
-        v-for="(column, index) in tableColumns"
-        :key="index"
-        :prop="column.key"
-        :label="column.title"
-        :width="column.width || 180"
-        :show-overflow-tooltip="column.showOverflowTooltip || true"
-      >
-      </el-table-column>
-    </el-table>
-    <el-pagination
-      @size-change="handleSizeChange"
-      @current-change="handleCurrentChange"
-      :total="total"
-      :page-sizes="pageSizes"
-      :page-size="page.pageSize"
-      :current-page="page.pageNum"
-      hide-on-single-page
-      layout="total, prev, pager, next, sizes, jumper"
-    >
-    </el-pagination>
-    <DirectSourcingTable></DirectSourcingTable>
-  </el-card>
-</template>

+ 0 - 158
src/views/purchase/purchase-task/see-purchase-task.vue

@@ -1,158 +0,0 @@
-<script>
-export default {
-  name: "SeePurchaseTaskDrawer",
-  data() {
-    const arr2Obj = function (data, keyName, valueName) {
-      return Object.fromEntries(
-        data.map((item) => [item[keyName], item[valueName]])
-      );
-    };
-    const columns = [
-      {
-        title: "采购组织",
-        key: "puOrg",
-        type: "TagSelect",
-        value: [],
-        required: true,
-      },
-      { title: "需求来源", key: "source", type: "Input", value: "采购创建" },
-      { title: "采购员", key: "buyer", value: [], type: "TagSelect" },
-      { title: "交易类型", key: "billYpe", value: [], type: "TagSelect" },
-      { title: "物料编码", key: "material", type: "Input", required: true },
-      {
-        title: "物料名称",
-        key: "materialName",
-        type: "TagSelect",
-        value: [],
-        required: true,
-      },
-      {
-        title: "物料/物料描述",
-        key: "materialDesc",
-        type: "TagSelect",
-        value: [],
-        required: true,
-      },
-      { title: "生产厂家", key: "manufacturer", type: "Input" },
-      { title: "收货客户", key: "customer", type: "TagSelect", value: [] },
-      {
-        title: "采购单位",
-        key: "puUnit",
-        type: "TagSelect",
-        value: [],
-        required: true,
-      },
-      {
-        title: "采购数量",
-        key: "puQty",
-        type: "InputNumber",
-        required: true,
-      },
-      {
-        title: "需求时间",
-        key: "demandDate",
-        type: "DatePicker",
-        config: { type: "date" },
-      },
-      { title: "项目名称", key: "projectName", type: "TagSelect", value: [] },
-      { title: "需求人", key: "demandPersonal", type: "TagSelect", value: [] },
-      {
-        title: "需求组织",
-        key: "demandOrg",
-        type: "TagSelect",
-        value: [],
-        require: true,
-      },
-      { title: "需求部门", key: "demandDept", type: "TagSelect", value: [] },
-      { title: "建议供应商", key: "supplier", type: "TagSelect", value: [] },
-      { title: "收货人", key: "a", type: "TagSelect", value: [] },
-      { title: "收货组织", key: "b", type: "TagSelect", value: [] },
-      { title: "收货人联系方式", key: "c", type: "Input" },
-      { title: "收货地址", key: "d", type: "Input" },
-      { title: "收货仓库", key: "e", type: "TagSelect", value: [] },
-      {
-        title: "指定供应商",
-        key: "assignSupplier",
-        type: "TagSelect",
-        value: [],
-      },
-      { title: "单位", key: "unit", type: "TagSelect", value: [] },
-      { title: "收货地址", key: "f", type: "TagSelect", value: [] },
-    ];
-    const initColumns = () => columns;
-    const initParams = () => arr2Obj(initColumns(), "key", "value");
-    return {
-      visible: false,
-      loading: false,
-      columns: initColumns(),
-      params: initParams(),
-    };
-  },
-  computed: {},
-  watch: {},
-  methods: {
-    setVisible(prop) {
-      this.visible = prop;
-    },
-    async fetchTaskItem() {
-      this.loading = true;
-      try {
-        // do something
-      } catch (err) {
-        this.$notify.error({ title: "error", message: err });
-      } finally {
-        this.loading = false;
-      }
-    },
-  },
-  created() {
-    console.log(this.params);
-  },
-  mounted() {},
-  destroyed() {},
-};
-</script>
-<template>
-  <el-drawer
-    title="我是标题"
-    direction="btt"
-    size="100%"
-    :with-header="false"
-    :visible.sync="visible"
-    :before-close="handleClose"
-  >
-    <el-card
-      :body-style="{
-        padding: '20px',
-        display: 'flex',
-        'flex-wrap': 'wrap',
-      }"
-      style="margin: 10px"
-    >
-      <el-descriptions title="采购任务详情" direction="vertical" :column="3">
-        <el-descriptions-item
-          v-for="(column, index) in columns"
-          :key="index"
-          :label="column.title"
-        >
-          {{ params[column.key] }}
-        </el-descriptions-item>
-      </el-descriptions>
-    </el-card>
-    <el-card
-      :body-style="{
-        'text-align': 'right',
-        padding: '10px 20px',
-      }"
-      style="
-        position: fixed;
-        left: 0;
-        bottom: 0;
-        margin: 10px;
-        width: calc(100% - 20px);
-      "
-    >
-      <el-button size="mini" @click="setVisible(false)">返回</el-button>
-    </el-card>
-  </el-drawer>
-</template>

+ 48 - 0
src/views/purchase/task/column.js

@@ -0,0 +1,48 @@
+export const TableColumns = [
+  { key: "id", title: "主键" },
+  { key: "material", title: "物料", search: true },
+  { key: "materialName", title: "物料名称", search: true },
+  { key: "status", title: "状态", search: true },
+  { key: "materialDesc", title: "物料/物料描述", search: true },
+  { key: "manufacturer", title: "生产厂家" },
+  { key: "manufacturerName", title: "生产厂家名称" },
+  { key: "priceType", title: "价格类型" },
+  { key: "buyer", title: "采购员" },
+  { key: "buyerName", title: "采购员名称", search: true },
+  { key: "supplier", title: "建议供应商" },
+  { key: "supplierName", title: "建议供应商名称" },
+  { key: "puOrg", title: "采购组织" },
+  { key: "puOrgName", title: "采购组织名称", search: true },
+  { key: "currency", title: "币种" },
+  { key: "currencyName", title: "币种名称" },
+  { key: "billYpe", title: "交易类型" },
+  { key: "source", title: "需求来源" },
+  { key: "customer", title: "收货客户" },
+  { key: "customerName", title: "收货客户名称" },
+  { key: "puUnit", title: "采购单位" },
+  { key: "puUnitName", title: "采购单位名称" },
+  { key: "puQty", title: "采购数量" },
+  { key: "demandDate", title: "需求时间", search: true },
+  { key: "projectName", title: "项目名称" },
+  { key: "demandPersonal", title: "需求人" },
+  { key: "demandPersonalName", title: "需求人名称", search: true },
+  { key: "demandOrg", title: "需求组织", search: true },
+  { key: "demandOrgName", title: "需求组织名称" },
+  { key: "demandDept", title: "需求部门" },
+  { key: "demandDeptName", title: "需求部门名称", search: true },
+  { key: "isBack", title: "是否退回" },
+  { key: "baskCause", title: "退回原因" },
+  { key: "backDate", title: "退回日期" },
+  { key: "assignSupplier", title: "指定供应商" },
+  { key: "assignSupplierName", title: "指定供应商名称" },
+  { key: "unit", title: "单位" },
+  { key: "unitName", title: "单位名称" },
+  { key: "demandCode", title: "采购需求单号" },
+  { key: "file", title: "附件" },
+  { key: "tenantId", title: "租户号" },
+  { key: "revision", title: "乐观锁" },
+  { key: "delFlag", title: "删除标记" },
+  { key: "materialCode", title: "物料编码" },
+];
+
+export const SearchColumns = TableColumns.filter((element) => element.search);

+ 0 - 0
src/views/purchase/purchase-task/config/add.js → src/views/purchase/task/config/add.js


+ 49 - 0
src/views/purchase/task/first-direct/column.js

@@ -0,0 +1,49 @@
+export const TableColumns = [
+  { key: "supplier", title: "供应商" },
+  { key: "supplierName", title: "供应商名称" },
+  { key: "puOrg", title: "采购组织" },
+  { key: "puOrgName", title: "采购组织名称" },
+  { key: "customer", title: "客户" },
+  { key: "customerName", title: "客户名称" },
+  { key: "priceType", title: "价格类型" },
+  { key: "isDistribution", title: "配送价" },
+  { key: "effectiveDate", title: "价格生效日期" },
+  { key: "endDate", title: "价格失效日期" },
+  { key: "tax", title: "税率" },
+  { key: "taxFreePrice", title: "无税单价" },
+  { key: "taxPrice", title: "主含税单价" },
+  {
+    key: "purchaseQuantity",
+    title: "本次采购数量",
+    type: "InputNumber",
+    width: 200,
+  },
+  {
+    key: "arrivalDatePlan",
+    title: "计划到货日期",
+    type: "DatePicker",
+    width: 200,
+  },
+  { key: "note", title: "备注", type: "Textarea", width: 200 },
+
+  // { key: "id", title: "主键" },
+  // { key: "material", title: "物料id" },
+  // { key: "manufacturer", title: "生产厂家" },
+  // { key: "materialClassify", title: "物料一级分类" },
+  // { key: "materialName", title: "物料名称" },
+  // { key: "model", title: "物料型号" },
+  // { key: "specification", title: "物料规格" },
+  // { key: "unit", title: "主单位" },
+  // { key: "unitName", title: "主单位名称" },
+  // { key: "buyer", title: "采购员" },
+  // { key: "buyerName", title: "采购员名称" },
+  // { key: "source", title: "来源单据编号" },
+  // { key: "status", title: "有效状态" },
+  // { key: "enableStatus", title: "启用状态" },
+  // { key: "convertRate", title: "换算率" },
+  // { key: "materialStatus", title: "物料启用状态" },
+  // { key: "demandCode", title: "采购需求单号" },
+  // { key: "expiryEarly", title: "效期预警" },
+
+  ,
+];

+ 167 - 0
src/views/purchase/task/first-direct/index.vue

@@ -0,0 +1,167 @@
+<script>
+import { TableColumns } from "./column";
+import { FirstDirect } from "@/api/business/purchase/task";
+import { initColumns } from "@/utils/init";
+export default {
+  name: "FirstDirectPurchaseDrawer",
+  components: {},
+  data() {
+    return {
+      size: "mini",
+      visible: false,
+      loading: false,
+
+      tableColumns: initColumns(TableColumns),
+      data: [],
+      //   page: { pageNum: 1, pageSize: 25 },
+      //   total: 0,
+      //   pageSizes: [25, 50, 100],
+    };
+  },
+  computed: {},
+  watch: {},
+  methods: {
+    setVisible(prop) {
+      this.visible = prop;
+    },
+    // 查询详细
+    async fetchItem(prop) {
+      try {
+        this.loading = true;
+        const { code, msg, data } = await FirstDirect(prop);
+        if (code === 200) {
+          this.data = data;
+          this.$notify.success({ title: msg });
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    // 取消
+    handleCancel() {
+      this.setVisible(false);
+    },
+  },
+  created() {},
+  mounted() {},
+  destroyed() {},
+};
+</script>
+
+<template>
+  <el-drawer
+    direction="btt"
+    size="100%"
+    :with-header="false"
+    :visible.sync="visible"
+  >
+    <el-card
+      :body-style="{
+        padding: '20px',
+        display: 'flex',
+        'flex-wrap': 'wrap',
+      }"
+      style="margin: 10px"
+    >
+      <div
+        slot="header"
+        style="
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+        "
+      >
+        <h3>首次协议直采</h3>
+        <div style="text-align: right">
+          <el-button :size="size" @click="handleCancel">取 消</el-button>
+        </div>
+      </div>
+      <div
+        v-for="(item, index) in data"
+        :key="index"
+        style="width: 100%; margin: 0 0 20px 0"
+      >
+        <el-descriptions border size="mini" :column="4">
+          <template #title>
+            <span style="margin-right: 10px">{{ item.materialName }}</span>
+            <span style="color: tomato">{{ item.puQty }}</span>
+            <span> {{ item.puUnitName }}</span>
+          </template>
+          <el-descriptions-item label="需求组织">
+            {{ item.demandOrgName }}
+          </el-descriptions-item>
+          <el-descriptions-item label="采购组织">
+            {{ item.puOrgName }}
+          </el-descriptions-item>
+          <el-descriptions-item label="需求时间">
+            {{ item.demandDate }}
+          </el-descriptions-item>
+        </el-descriptions>
+        <el-table
+          v-loading="loading"
+          :data="item.orderPriceVos"
+          style="width: 100%"
+        >
+          <el-table-column
+            v-for="(column, index) in tableColumns"
+            :key="index"
+            :prop="column.key"
+            :label="column.title"
+            :width="column.width || 180"
+            :show-overflow-tooltip="column.showOverflowTooltip || true"
+          >
+            <template slot-scope="scope">
+              <el-input-number
+                v-if="column.edit && column.editConfig.type === 'InputNumber'"
+                v-model="scope.row[column.key]"
+                :controls-position="column.editConfig.controlsPosition"
+                :min="column.editConfig.min"
+                :max="column.editConfig.max"
+                :size="column.editConfig.size || 'mini'"
+                :placeholder="column.editConfig.placeholder"
+                style="width: 90%"
+              ></el-input-number>
+              <el-date-picker
+                v-else-if="
+                  column.edit && column.editConfig.type === 'DatePicker'
+                "
+                v-model="scope.row[column.key]"
+                :type="column.editConfig.showType"
+                :picker-options="column.editConfig.pickerOptions"
+                :size="column.editConfig.size || 'mini'"
+                :placeholder="column.editConfig.placeholder"
+                style="width: 90%"
+              ></el-date-picker>
+              <el-input
+                v-else-if="column.edit && column.editConfig.type === 'Textarea'"
+                v-model="scope.row[column.key]"
+                type="textarea"
+                :autosize="column.editConfig.autosize || true"
+                :size="column.editConfig.size || 'mini'"
+                style="width: 90%"
+              ></el-input>
+              <span v-else>{{ scope.row[column.key] }}</span>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+      <!-- <el-pagination
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+      :total="total"
+      :page-sizes="pageSizes"
+      :page-size="page.pageSize"
+      :current-page="page.pageNum"
+      hide-on-single-page
+      layout="total, prev, pager, next, sizes, jumper"
+    >
+    </el-pagination> -->
+    </el-card>
+  </el-drawer>
+</template>
+
+<style scoped></style>

+ 262 - 0
src/views/purchase/task/index.vue

@@ -0,0 +1,262 @@
+<script>
+import { TableColumns, SearchColumns } from "./column";
+import { list } from "@/api/business/purchase/task";
+import { initPage, initLayout, initPageSizes, initParams } from "@/utils/init";
+export default {
+  name: "PuchaseTask",
+  components: {
+    SeeDrawer: () => import("./see/index.vue"),
+    FirstDirectDrawer: () => import("./first-direct/index.vue"),
+  },
+  data() {
+    return {
+      size: "mini",
+
+      loading: false,
+
+      searchColumns: SearchColumns,
+      params: {
+        isAsc: "",
+        reasonable: "",
+        orderByColumn: "",
+        ...initParams(SearchColumns),
+      },
+
+      tableData: [],
+      selectData: [],
+      tableColumns: TableColumns,
+
+      page: initPage(),
+      layout: initLayout(),
+      pageSizes: initPageSizes(),
+    };
+  },
+  computed: {},
+  created() {
+    this.handleQueryList();
+  },
+  methods: {
+    //
+    async fetchList(params, page) {
+      try {
+        this.loading = true;
+        const { pageNum, pageSize } = page;
+        const { code, msg, rows, total } = await list({
+          pageNum,
+          pageSize,
+          ...params,
+        });
+        if (code === 200) {
+          this.tableData = rows;
+          this.page.total = total;
+          this.$notify.success({ title: msg });
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    // 查询操作
+    handleQueryList() {
+      this.fetchList(this.params, this.page);
+    },
+    // 重置操作
+    handleResetList() {
+      this.page = initPage();
+      this.params = initParams(SearchColumns);
+      this.fetchList(this.params, this.page);
+    },
+    // 页大小变
+    handleSizeChange(prop) {
+      this.page.pageSize = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // 当前页变
+    handleCurrentChange(prop) {
+      this.page.pageNum = prop;
+      this.fetchList(this.params, this.page);
+    },
+    //
+    handleSelectionChange(prop) {
+      this.selectData = prop;
+    },
+    // 打开查看drawer
+    async handleOpenSeeDrawer(prop) {
+      const { id } = prop;
+      const { setVisible, fetchItem } = this.$refs.SeeDrawerFef;
+      await setVisible(true);
+      await fetchItem(id);
+    },
+    // 打开首次直采drawer
+    async handleOpenFristDirectDrawer(prop) {
+      const { setVisible, fetchItem } = this.$refs.FirstDirectDrawerRef;
+      await setVisible(true);
+      await fetchItem(prop);
+    },
+  },
+};
+</script>
+
+<template>
+  <el-card
+    v-loading="loading"
+    style="width: calc(100% - 24px); height: 100%; margin: 10px"
+    :body-style="{ padding: 0 }"
+  >
+    <see-drawer ref="SeeDrawerFef"></see-drawer>
+    <first-direct-drawer ref="FirstDirectDrawerRef"></first-direct-drawer>
+    <el-form :size="size" label-position="top" :model="params">
+      <el-row :gutter="24" style="padding: 0 20px">
+        <el-col
+          v-for="column in searchColumns"
+          :key="column.title"
+          :xl="4"
+          :lg="4"
+          :md="6"
+          :sm="12"
+          :xs="24"
+        >
+          <el-form-item :prop="column.key" :label="column.title">
+            <el-input
+              v-model="params[column.key]"
+              :placeholder="column.placeholder"
+            ></el-input>
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+    <el-row :gutter="24" style="padding: 0 20px">
+      <el-col :span="6">
+        <el-button type="primary" :size="size" @click="handleQueryList">
+          搜 索
+        </el-button>
+        <el-button :size="size" @click="handleResetList">
+          重 置
+        </el-button></el-col
+      >
+      <el-col :span="18" style="text-align: right">
+        <el-button
+          :size="size"
+          :disabled="!selectData.length"
+          @click="handleOpenFristDirectDrawer(selectData)"
+        >
+          协议直采
+        </el-button>
+        <!-- <el-button
+          size="mini"
+          type="danger"
+          style="margin: 0 10px 0 0"
+          @click="handleOpenAddDrawer"
+        >
+          新增
+        </el-button>
+        <el-dropdown placement="bottom-start">
+          <el-button size="mini" style="margin: 0 10px 0 0">
+            发布
+            <i class="el-icon-arrow-down el-icon--right"></i>
+          </el-button>
+          <el-dropdown-menu slot="dropdown">
+            <el-dropdown-item>发布寻源</el-dropdown-item>
+            <el-dropdown-item>发布委托</el-dropdown-item>
+            <el-dropdown-item>采购方案</el-dropdown-item>
+          </el-dropdown-menu>
+        </el-dropdown>
+
+        <el-dropdown placement="bottom-start">
+          <el-button
+            size="mini"
+            style="border-right: 0; border-radius: 3px 0 0 3px"
+          >
+            首次协议直采
+            <i class="el-icon-arrow-down el-icon--right"></i>
+          </el-button>
+          <el-dropdown-menu slot="dropdown">
+            <el-dropdown-item>首次协议直采</el-dropdown-item>
+            <el-dropdown-item>余量协议直采</el-dropdown-item>
+          </el-dropdown-menu>
+        </el-dropdown>
+        <el-dropdown placement="bottom-start">
+          <el-button size="mini" style="border-right: 0; border-radius: 0">
+            跟单采购
+            <i class="el-icon-arrow-down el-icon--right"></i>
+          </el-button>
+          <el-dropdown-menu slot="dropdown">
+            <el-dropdown-item>按合同(普通)取价</el-dropdown-item>
+          </el-dropdown-menu>
+        </el-dropdown>
+        <el-button size="mini" style="border-right: 0; border-radius: 0">
+          Excel导出
+        </el-button>
+        <el-button
+          size="mini"
+          style="margin: 0; border-right: 0; border-radius: 0"
+        >
+          退回请购
+        </el-button>
+        <el-dropdown placement="bottom-start">
+          <el-button size="mini" style="border-right: 0; border-radius: 0">
+            清单采购
+            <i class="el-icon-arrow-down el-icon--right"></i>
+          </el-button>
+          <el-dropdown-menu slot="dropdown">
+            <el-dropdown-item>商超匹配下单</el-dropdown-item>
+          </el-dropdown-menu>
+        </el-dropdown>
+        <el-button
+          size="mini"
+          disabled
+          style="margin: 0 10px 0 0; border-radius: 0 3px 3px 0"
+        >
+          一键合同下单
+        </el-button>
+        <el-button size="mini" style="margin: 0 10px 0 0">删除</el-button>
+        <el-dropdown placement="bottom-end">
+          <el-button size="mini">
+            更多
+            <i class="el-icon-arrow-down el-icon--right"></i>
+          </el-button>
+          <el-dropdown-menu slot="dropdown">
+            <el-dropdown-item>抢单</el-dropdown-item>
+            <el-dropdown-item>批量修改收货组织</el-dropdown-item>
+            <el-dropdown-item>批量退回</el-dropdown-item>
+            <el-dropdown-item>退回需求申请</el-dropdown-item>
+            <el-dropdown-item>刷新缓存</el-dropdown-item>
+          </el-dropdown-menu>
+        </el-dropdown> -->
+      </el-col>
+    </el-row>
+    <el-table
+      :data="tableData"
+      size="mini"
+      style="width: 100%; margin: 20px 0 0 0"
+      @row-dblclick="handleOpenSeeDrawer"
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column type="selection" width="55" align="center">
+      </el-table-column>
+      <el-table-column
+        v-for="(column, index) in tableColumns"
+        :key="index"
+        :prop="column.key"
+        :label="column.title"
+        :width="column.width || 180"
+        :show-overflow-tooltip="column.showOverflowTooltip || true"
+      >
+      </el-table-column>
+    </el-table>
+    <el-pagination
+      @size-change="handleSizeChange"
+      @current-change="handleCurrentChange"
+      :total="page.total"
+      :page-sizes="pageSizes"
+      :page-size="page.pageSize"
+      :current-page="page.pageNum"
+      hide-on-single-page
+      layout="total, prev, pager, next, sizes, jumper"
+    >
+    </el-pagination>
+  </el-card>
+</template>

+ 514 - 0
src/views/purchase/task/see/column.js

@@ -0,0 +1,514 @@
+export const Columns = [
+  {
+    key: "puOrgName",
+    title: "采购组织",
+    type: "InputDialog",
+    config: {
+      componentName: "ORG_PARAM",
+      dataMapping: {
+        puOrg: "code",
+        puOrgName: "name",
+      },
+    },
+    require: true,
+  },
+  { key: "code", title: "合同编码", type: "Input" },
+  {
+    key: "lastPuMoney",
+    title: "上年度采购额",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "buyerName",
+    title: "采购员",
+    type: "InputDialog",
+    config: {
+      componentName: "ORG_PARAM",
+      dataMapping: {
+        buyer: "userId",
+        buyerName: "userName",
+        puDept: "deptId",
+        puDeptName: "deptName",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "supplierName",
+    title: "供应商",
+    type: "InputDialog",
+    config: {
+      componentName: "SUPPLIER_PARAM",
+      dataMapping: {
+        supplier: "code",
+        supplierName: "name",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "contractType",
+    title: "合同类型",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_contract_type",
+    },
+  },
+  {
+    key: "puMoneyYear",
+    title: "本年度采购额",
+    type: "InputNumber",
+    require: true,
+  },
+  {
+    key: "puDeptName",
+    title: "采购部门",
+    type: "InputDialog",
+    config: {
+      componentName: "DEPT_PARAM",
+      dataMapping: {
+        puDept: "code",
+        puDeptName: "name",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "supplierTier",
+    title: "供应商层级",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_supplier_tier",
+    },
+  },
+  { key: "contractName", title: "合同名称", type: "Input", require: true },
+  {
+    key: "grossRateAverage",
+    title: "平均毛利率",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "approveFlow",
+    title: "审批流程",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_approve_flow",
+    },
+  },
+  {
+    key: "consumableClass",
+    title: "耗材类别",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_consumable_class",
+    },
+  },
+  {
+    key: "effectiveDate",
+    title: "合同生效日期",
+    type: "DatePicker",
+    require: true,
+  },
+  {
+    key: "brandGrossRate",
+    title: "同类品牌及毛利率",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "contractFormat",
+    title: "合同格式",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "productName",
+    title: "产品类别&名称",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "endDate",
+    title: "合同终止日期",
+    type: "DatePicker",
+    require: true,
+  },
+  {
+    key: "invoiceTax",
+    title: "发票税率",
+    type: "InputDialog",
+    config: {
+      componentName: "ORG_PARAM",
+      dataMapping: {
+        invoiceTax: "mattaxesname",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "emergencyDegree",
+    title: "紧急程度",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_emergency_degree",
+    },
+  },
+  { key: "project", title: "项目医院", type: "Input", require: true },
+  {
+    key: "signDate",
+    title: "合同签订日期",
+    type: "DatePicker",
+    require: true,
+  },
+  {
+    key: "deliveryType",
+    title: "交货方式",
+    type: "Select",
+    config: {
+      optionsName: "purchase_contract_delivery_type",
+    },
+  },
+  {
+    key: "source",
+    title: "合同来源",
+    type: "Input",
+    value: "自制",
+    disabled: true,
+  },
+  {
+    key: "contractPartycName",
+    title: "合同丙方",
+    type: "InputDialog",
+    config: {
+      componentName: "SUPPLIER_PARAM",
+      dataMapping: {
+        contractPartyc: "code",
+        contractPartycName: "name",
+      },
+    },
+  },
+  {
+    key: "guaranteePeriodEnd",
+    title: "质保期限",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "freightMethods",
+    title: "运费承担方式",
+    type: "Select",
+    config: {
+      optionsName: "purchase_contract_freight_methods",
+    },
+  },
+  {
+    key: "signDate",
+    title: "合同创建时间",
+    type: "DatePicker",
+    disabled: true,
+  },
+  {
+    key: "isTarget",
+    title: "是否有指标",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_is_target",
+    },
+  },
+  {
+    key: "contractTarget",
+    title: "合同指标",
+    type: "Input",
+    require: true,
+    placeholder: '当【是否有指标】="有"时,必填',
+  },
+  {
+    key: "exemptionPostageCondtion",
+    title: "包邮条件",
+    type: "Input",
+    placeholder:
+      "当运费承担方式为供应商有条件承担时,该字段必填,填写要求,写明什么条件下供应商承担全部,什么条件下我方承担,什么条件下分别承担",
+    span: 12,
+  },
+  {
+    key: "isRebate",
+    title: "是否有返利",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_is_rebate",
+    },
+  },
+  {
+    key: "rebatePolicy",
+    title: "返利政策",
+    type: "Input",
+    placeholder: '当【是否有返利】="有"时,必填',
+    span: 18,
+  },
+  { key: "externalContract", title: "外部合同号", type: "Input" },
+  {
+    key: "rollbackPolicy",
+    title: "退换货政策",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "contractContent",
+    title: "合同主要内容",
+    type: "Textarea",
+    require: true,
+    span: 24,
+  },
+  { key: "refusalReasons", title: "拒绝理由", type: "Input", span: 24 },
+  { key: "enquiryCode", title: "询价单号", type: "Input" },
+  { key: "externalFile", title: "对外附件", type: "Upload", span: 24 },
+  { key: "puFile", title: "采购商盖章合同附件", type: "Upload", span: 24 },
+  {
+    key: "supplierFile",
+    title: "供应商盖章合同附件",
+    type: "Upload",
+    span: 24,
+  },
+  { key: "projectCode", title: "项目编号", type: "Input" },
+  { key: "projectName", title: "项目名称", type: "Input" },
+  { key: "area", title: "区域", type: "Input" },
+  { key: "consigneePhone", title: "收货人联系方式", type: "Input" },
+  {
+    key: "paymentAgreementName",
+    title: "付款协议",
+    type: "InputDialog",
+    config: {
+      componentName: "PAYAGREEMENT_PARAM",
+      dataMapping: {
+        paymentAgreement: "code",
+        paymentAgreementName: "name",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "taxPrice",
+    title: "价税合计",
+    type: "InputNumber",
+  },
+  {
+    key: "currencyName",
+    title: "币种",
+    type: "InputDialog",
+    config: {
+      componentName: "CURRENCY_PARAM",
+      dataMapping: {
+        currency: "code",
+        currencyName: "name",
+      },
+    },
+    require: true,
+  },
+  { key: "guaranteePeriod", title: "质保期", type: "Input" },
+
+  // { key: "buyerName", title: "采购员名称" },
+  // { key: "supplierName", title: "供应商名称" },
+
+  // { key: "puDeptName", title: "采购部门名称" },
+
+  // { key: "contractPartycName", title: "合同丙方名称" },
+
+  // { key: "currencyName", title: "币种名称" },
+  // { key: "tenantId", title: "租户号" },
+  // { key: "revision", title: "乐观锁" },
+  // { key: "createByName", title: "创建人" },
+  // { key: "updateByName", title: "创建人名称" },
+  // { key: "delFlag", title: "删除标记" },
+];
+
+export const TabColumns = [
+  {
+    show: {
+      contractType: [1, 2],
+    },
+    title: "物料基本信息",
+    key: "contractItemList",
+    tableColumns: [
+      { title: "物料编码", key: "material", width: 200 },
+      {
+        title: "物料名称",
+        key: "materialName",
+        type: "InputDialog",
+        width: 200,
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      {
+        title: "规格",
+        key: "specification",
+        width: 200,
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      {
+        title: "品牌",
+        key: "brand",
+        type: "InputDialog",
+        width: 200,
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      { title: "生产厂家", key: "manufacturer", type: "Input", width: 200 },
+      {
+        title: "采购单位",
+        key: "puUnit",
+        type: "InputDialog",
+        width: 200,
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      {
+        title: "税率%",
+        key: "tax",
+        type: "InputDialog",
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+        width: 200,
+      },
+      {
+        title: "采购数量",
+        key: "qty",
+        type: "InputNumber",
+
+        width: 200,
+      },
+      {
+        title: "含税单价",
+        key: "taxPrice",
+        type: "InputNumber",
+
+        width: 200,
+      },
+      { title: "含税金额合计", key: "taxMoney", width: 200 },
+      { title: "无税单价", key: "taxFreePrice" },
+      { title: "无税金额合计", key: "taxFreeMoney", width: 200 },
+      {
+        title: "注册证号及备案凭证号",
+        key: "registration",
+        type: "Input",
+        width: 200,
+      },
+      {
+        title: "收货客户",
+        key: "customerName",
+        type: "InputDialog",
+        width: 200,
+        config: {
+          componentName: "SUPPLIER_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      { title: "备注", key: "remark", type: "Input", width: 200 },
+    ],
+  },
+  {
+    title: "合同条款",
+    key: "contractClauseList",
+    tableColumns: [
+      { title: "条款编码", key: "code", type: "Input" },
+      { title: "条款名称", key: "name", type: "Input" },
+      { title: "条款内容", key: "content", type: "Input" },
+      { title: "变量序号", key: "variableRowno" },
+      { title: "变量内容", key: "variableContent", type: "Input" },
+      { title: "备注", key: "remark", type: "Input" },
+    ],
+  },
+  {
+    title: "合同费用",
+    key: "contractExpenseList",
+    tableColumns: [
+      { title: "费用编码", key: "code", type: "Input" },
+      { title: "费用名称", key: "name", type: "Input" },
+      {
+        title: "费用金额",
+        key: "money",
+        type: "InputNumber",
+        width: 200,
+      },
+      { title: "备注", key: "remark", type: "Input" },
+    ],
+  },
+  {
+    title: "付款协议信息",
+    key: "contractAgreementList",
+    tableColumns: [
+      {
+        title: "付款阶段",
+        key: "satge",
+        type: "InputNumber",
+        width: 200,
+      },
+      {
+        title: "付款起点",
+        key: "origin",
+        type: "InputDialog",
+        width: 200,
+        config: {
+          componentName: "MATERIAL_PARAM",
+          dataMapping: {
+            material: "code",
+            materialName: "name",
+          },
+        },
+      },
+      { title: "账期天数", key: "paymetDays", type: "Input", width: 200 },
+      { title: "付款比例%", key: "ratio", type: "Input", width: 200 },
+      { title: "付款金额", key: "money", type: "Input", width: 200 },
+      { title: "是否预付款", key: "isAdvance", width: 200 },
+      { title: "是否质保金", key: "isQuality", width: 200 },
+      { title: "结算方式", key: "paymentMeans", type: "Input", width: 200 },
+      { title: "备注", key: "remark", type: "Input", width: 200 },
+      { title: "需进度确认", key: "schedule", type: "Select", width: 200 },
+    ],
+  },
+  {
+    title: "合同执行组织范围",
+    key: "contractApplyOrgList",
+    tableColumns: [
+      { title: "组织名称", key: "orgName", type: "Input" },
+      { title: "组织编码", key: "org", type: "Input" },
+    ],
+  },
+];

+ 114 - 0
src/views/purchase/task/see/index.vue

@@ -0,0 +1,114 @@
+<script>
+import { TableColumns as Columns } from "../column";
+import { item } from "@/api/business/purchase/task";
+import { initColumns, initDicts, initRules, initParams } from "@/utils/init";
+
+const NewColumns = initColumns(Columns);
+
+export default {
+  name: "SeeDrawer",
+  dicts: initDicts(NewColumns),
+  components: {
+    DrInputDialog: () => import("@/components/input-dialog/index.vue"),
+  },
+  data() {
+    return {
+      size: "mini",
+      visible: false,
+      loading: false,
+      columns: NewColumns,
+      rules: initRules(NewColumns),
+      params: initParams(NewColumns),
+    };
+  },
+  computed: {},
+  watch: {},
+  methods: {
+    setVisible(prop) {
+      this.visible = prop;
+    },
+    // 查询详细
+    async fetchItem(prop) {
+      try {
+        this.loading = true;
+        const { code, msg, data } = await item(prop);
+        if (code === 200) {
+          this.params = data;
+          this.$notify.success({ title: msg });
+        } else {
+          this.$notify.warning({ title: msg });
+        }
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.loading = false;
+      }
+    },
+    // 取消
+    handleCancel() {
+      this.setVisible(false);
+      this.params = initParams(this.columns, "key", "value");
+    },
+    // 保存
+    handleSava() {
+      this.setVisible(false);
+    },
+  },
+  created() {
+    console.log("ADD CREATED");
+  },
+  mounted() {},
+  destroyed() {},
+};
+</script>
+<template>
+  <el-drawer
+    direction="btt"
+    size="100%"
+    :with-header="false"
+    :visible.sync="visible"
+  >
+    <el-form
+      v-loading="loading"
+      :size="size"
+      label-position="right"
+      label-width="135px"
+      :model="params"
+      :rules="rules"
+    >
+      <el-card
+        :body-style="{
+          padding: '20px',
+          display: 'flex',
+          'flex-wrap': 'wrap',
+        }"
+        style="margin: 10px"
+      >
+        <div
+          slot="header"
+          style="
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+          "
+        >
+          <h3>查 看</h3>
+          <div style="text-align: right">
+            <el-button :size="size" @click="handleCancel">取 消</el-button>
+          </div>
+        </div>
+        <el-row>
+          <el-col
+            v-for="(column, index) in columns"
+            :key="index"
+            :span="column.span || 6"
+          >
+            <el-form-item :prop="column.key" :label="column.title">
+              {{ params[column.key] }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-card>
+    </el-form>
+  </el-drawer>
+</template>