Forráskód Böngészése

Merge branch 'purchaseDev' into 'dev'

Purchase dev

See merge request new-business/drp-web!37
黄梓星 2 éve
szülő
commit
54020284c5

+ 9 - 2
src/api/business/purchase/purchase-contract.js

@@ -1,10 +1,17 @@
 import request from "@/utils/request";
 
-// 查询任务列表
-export function taskList(params) {
+export function list(params) {
   return request({
     url: "/pu/contract/list",
     method: "get",
     params: params,
   });
 }
+
+export function add(data) {
+  return request({
+    url: "/pu/contract/add",
+    method: "post",
+    data: data,
+  });
+}

+ 29 - 0
src/api/purchase/DemandSummary.js

@@ -22,4 +22,33 @@ export function auditSummary(id) {
     url: `/pu/demand/audit/${id}`,
     method: 'get',
   })
+}
+// 采购需求汇总确认
+export function confirmSummary(data) {
+  return request({
+    url: `/pu/demand/item/summary/confirm`,
+    method: 'post',
+    data: data
+  })
+}
+// 采购需求汇总取消
+export function cancelSummary(id) {
+  return request({
+    url: `/pu/demand/item/summary/cancel/${id}`,
+    method: 'get',
+  })
+}
+// 采购需求汇总弃审
+export function cancelAuditSummary(id) {
+  return request({
+    url: `/pu/demand/item/summary/cancel/audit/${id}`,
+    method: 'get',
+  })
+}
+// 采购需求汇总明细行关闭
+export function shutDownSummary(id) {
+  return request({
+    url: `/pu/demand/item/summary/shutDown/${id}`,
+    method: 'get',
+  })
 }

+ 1 - 1
src/api/purchase/basic.js

@@ -41,7 +41,7 @@ export function delDivision(ids) {
 // 参照统一接口
 export function getRefer(data) {
   return request({
-    url: '/refer/query',
+    url: `/refer/query?pageSize=${data.pageSize}&pageNum=${data.pageNo}`,
     method: 'post',
     data: data
   })

+ 2 - 0
src/utils/data-transform.js

@@ -0,0 +1,2 @@
+export const arr2obj = (data, keyName, valueName) =>
+  Object.fromEntries(data.map((item) => [item[keyName], item[valueName]]));

+ 39 - 0
src/utils/init-something.js

@@ -0,0 +1,39 @@
+import { arr2obj } from "./data-transform";
+import Components from "@/views/common-dialog";
+
+export const initParams = (arr) => arr2obj(arr, "key", "value");
+
+export const initDicts = (arr) =>
+  arr
+    .filter((column) => column.type === "Select")
+    .map((column) => column.config.optionsName);
+
+export const initRules = (arr) => {
+  const rules = {};
+  arr
+    .filter((column) => column.require)
+    .forEach((column) => {
+      const message = `${column.title}不能为空`;
+      rules[column.key] = [
+        { required: true, message: message, trigger: "change" },
+      ];
+    });
+  return rules;
+};
+
+export const initComponents = (arr) => {
+  const c = {};
+  try {
+    arr
+      .filter((element) => element.type === "InputDialog")
+      .map((element) => element.config.componentName)
+      .forEach((element) => {
+        c[element] = Components[element];
+      });
+
+    return c;
+  } catch (err) {
+    return c;
+  } finally {
+  }
+};

+ 17 - 0
src/views/common-dialog/api/index.js

@@ -0,0 +1,17 @@
+import request from "@/utils/request";
+
+export function list(url, params) {
+  return request({
+    url: `/pu/contract/${url}/list`,
+    method: "get",
+    params: params,
+  });
+}
+
+export function refer(data) {
+  return request({
+    url: `/refer/query`,
+    method: "POST",
+    data: data,
+  });
+}

+ 214 - 0
src/views/common-dialog/currency.vue

@@ -0,0 +1,214 @@
+<script>
+import { initParams } from "./utils/init-something";
+import { list } from "./api/index";
+
+export default {
+  name: "CurrencyInputDialog",
+  props: ["title", "value"],
+  components: {},
+  data() {
+    const columns = [
+      {
+        key: "name",
+        title: "币种",
+        type: "Input",
+        search: true,
+      },
+      {
+        key: "code",
+        title: "币种简称",
+        type: "Input",
+        search: true,
+      },
+      {
+        key: "",
+        title: "单价精度",
+      },
+      {
+        key: "",
+        title: "单价舍入规则",
+      },
+      {
+        key: "",
+        title: "金额精度",
+      },
+      {
+        key: "",
+        title: "金额舍入规则",
+      },
+    ];
+    const initTableColumns = () => columns.filter((column) => column.key);
+    const initSearchColumns = () => columns.filter((column) => column.search);
+    return {
+      // global
+      size: "mini",
+      width: "50%",
+      page: { pageNum: 1, pageSize: 25, total: 0 },
+      pageSizes: [25, 50],
+      layout: "prev, pager, next, jumper",
+      api: "puCurrType",
+      showKey: "name",
+      // dialog
+      visible: false,
+      loading: false,
+      // search
+      searchColumns: initSearchColumns(),
+      params: initParams(initSearchColumns()),
+      // table
+      tableColumns: initTableColumns(),
+      data: [],
+      currentData: null,
+    };
+  },
+  computed: {},
+  watch: {},
+  methods: {
+    // set dialog visible
+    setVisible(prop) {
+      this.visible = prop;
+    },
+    // do something before dialog open
+    beforeOpen() {
+      const { value } = this.$props;
+      this.params[this.showKey] = value;
+      this.fetchList(this.params, this.page);
+    },
+    // fetch table data
+    async fetchList(prop, page) {
+      try {
+        this.loading = true;
+        const { pageNum, pageSize } = page;
+        const { code, msg, rows, total } = await list(this.api, {
+          ...prop,
+          pageNum,
+          pageSize,
+        });
+        if (code === 200) {
+          this.data = 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;
+        this.setCurrentData(
+          this.data.find(
+            (column) => column[this.showKey] === this.currentData[this.showKey]
+          )
+        );
+      }
+    },
+    // setting up to fetch table data
+    queryList() {
+      this.fetchList(this.params, this.page);
+    },
+    // reset to fetch table data
+    resetList() {
+      this.page.pageNum = 1;
+      this.params = initParams(this.searchColumns);
+      this.fetchList(this.params, this.page);
+    },
+    // size change to fetch table data
+    pageSizeChange(prop) {
+      this.page.pageSize = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // number change to fetch table data
+    pageNumberChange(prop) {
+      this.page.pageNum = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // select row data
+    selectCurrentData(row) {
+      this.currentData = row;
+    },
+    // set row data highlight
+    setCurrentData(row) {
+      this.$refs.singleTable.setCurrentRow(row);
+    },
+    //
+    confirm() {
+      if (this.currentData) {
+        this.$emit("confirm", this.currentData);
+      }
+      this.setVisible(false);
+    },
+  },
+  created() {},
+  mounted() {},
+  destroyed() {},
+};
+</script>
+<template>
+  <el-dialog
+    :title="title"
+    :visible.sync="visible"
+    :width="width"
+    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-item>
+      <el-form-item>
+        <el-button icon="el-icon-refresh" @click="resetList"></el-button>
+      </el-form-item>
+    </el-form>
+    <el-table
+      v-loading="loading"
+      :data="data"
+      :size="size"
+      ref="singleTable"
+      height="45vh"
+      highlight-current-row
+      style="width: 100%; margin-bottom: 20px"
+      @row-click="selectCurrentData"
+    >
+      <el-table-column
+        v-for="(column, index) in tableColumns"
+        :key="index"
+        :prop="column.key"
+        :label="column.title"
+        :width="column.width"
+        show-overflow-tooltip
+      >
+      </el-table-column>
+    </el-table>
+    <div
+      style="display: flex; justify-content: space-between; align-items: center"
+    >
+      <p>
+        <span style="font-size: 12px">已选择 :</span>
+        <el-tag v-if="currentData" :size="size">{{
+          currentData[showKey]
+        }}</el-tag>
+        <span v-else>无</span>
+      </p>
+      <el-pagination
+        :layout="layout"
+        :total="page.total"
+        :page-sizes="pageSizes"
+        :page-size="page.pageSize"
+        :current-page="page.pageNum"
+        :small="size === 'mini'"
+        background
+        @size-change="pageSizeChange"
+        @current-change="pageNumberChange"
+      >
+      </el-pagination>
+    </div>
+    <div style="margin-top: 20px; text-align: right">
+      <el-button :size="size" @click="visible = false">取 消</el-button>
+      <el-button :size="size" type="primary" @click="confirm">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+<style scoped></style>

+ 198 - 0
src/views/common-dialog/department.vue

@@ -0,0 +1,198 @@
+<script>
+import { initParams } from "./utils/init-something";
+import { list } from "./api/index";
+
+export default {
+  name: "DepartmentInputDialog",
+  props: ["title", "value"],
+  components: {},
+  data() {
+    const columns = [
+      {
+        key: "deptId",
+        title: "组织编码",
+        type: "Input",
+        search: true,
+      },
+      {
+        key: "deptName",
+        title: "组织名称",
+        type: "Input",
+        search: true,
+      },
+    ];
+    const initTableColumns = () => columns.filter((column) => column.key);
+    const initSearchColumns = () => columns.filter((column) => column.search);
+    return {
+      // global
+      size: "mini",
+      width: "50%",
+      page: { pageNum: 1, pageSize: 25, total: 0 },
+      pageSizes: [25, 50],
+      layout: "prev, pager, next, jumper",
+      api: "puDept",
+      showKey: "deptName",
+      // dialog
+      visible: false,
+      loading: false,
+      // search
+      searchColumns: initSearchColumns(),
+      params: initParams(initSearchColumns()),
+      // table
+      tableColumns: initTableColumns(),
+      data: [],
+      currentData: null,
+    };
+  },
+  computed: {},
+  watch: {},
+  methods: {
+    // set dialog visible
+    setVisible(prop) {
+      this.visible = prop;
+    },
+    // do something before dialog open
+    beforeOpen() {
+      const { value } = this.$props;
+      this.params[this.showKey] = value;
+      this.fetchList(this.params, this.page);
+    },
+    // fetch table data
+    async fetchList(prop, page) {
+      try {
+        this.loading = true;
+        const { pageNum, pageSize } = page;
+        const { code, msg, rows, total } = await list(this.api, {
+          ...prop,
+          pageNum,
+          pageSize,
+        });
+        if (code === 200) {
+          this.data = 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;
+        this.setCurrentData(
+          this.data.find(
+            (column) => column[this.showKey] === this.currentData[this.showKey]
+          )
+        );
+      }
+    },
+    // setting up to fetch table data
+    queryList() {
+      this.fetchList(this.params, this.page);
+    },
+    // reset to fetch table data
+    resetList() {
+      this.page.pageNum = 1;
+      this.params = initParams(this.searchColumns);
+      this.fetchList(this.params, this.page);
+    },
+    // size change to fetch table data
+    pageSizeChange(prop) {
+      this.page.pageSize = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // number change to fetch table data
+    pageNumberChange(prop) {
+      this.page.pageNum = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // select row data
+    selectCurrentData(row) {
+      this.currentData = row;
+    },
+    // set row data highlight
+    setCurrentData(row) {
+      this.$refs.singleTable.setCurrentRow(row);
+    },
+    //
+    confirm() {
+      if (this.currentData) {
+        this.$emit("confirm", this.currentData);
+      }
+      this.setVisible(false);
+    },
+  },
+  created() {},
+  mounted() {},
+  destroyed() {},
+};
+</script>
+<template>
+  <el-dialog
+    :title="title"
+    :visible.sync="visible"
+    :width="width"
+    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-item>
+      <el-form-item>
+        <el-button icon="el-icon-refresh" @click="resetList"></el-button>
+      </el-form-item>
+    </el-form>
+    <el-table
+      v-loading="loading"
+      :data="data"
+      :size="size"
+      ref="singleTable"
+      height="45vh"
+      highlight-current-row
+      style="width: 100%; margin-bottom: 20px"
+      @row-click="selectCurrentData"
+    >
+      <el-table-column
+        v-for="(column, index) in tableColumns"
+        :key="index"
+        :prop="column.key"
+        :label="column.title"
+        :width="column.width"
+        show-overflow-tooltip
+      >
+      </el-table-column>
+    </el-table>
+    <div
+      style="display: flex; justify-content: space-between; align-items: center"
+    >
+      <p>
+        <span style="font-size: 12px">已选择 :</span>
+        <el-tag v-if="currentData" :size="size">{{
+          currentData[showKey]
+        }}</el-tag>
+        <span v-else>无</span>
+      </p>
+      <el-pagination
+        :layout="layout"
+        :total="page.total"
+        :page-sizes="pageSizes"
+        :page-size="page.pageSize"
+        :current-page="page.pageNum"
+        :small="size === 'mini'"
+        background
+        @size-change="pageSizeChange"
+        @current-change="pageNumberChange"
+      >
+      </el-pagination>
+    </div>
+    <div style="margin-top: 20px; text-align: right">
+      <el-button :size="size" @click="visible = false">取 消</el-button>
+      <el-button :size="size" type="primary" @click="confirm">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+<style scoped></style>

+ 20 - 0
src/views/common-dialog/index.js

@@ -0,0 +1,20 @@
+// 员工
+import user from "./user.vue";
+// 组织
+import organization from "./organization.vue";
+// 部门
+import department from "./department.vue";
+// 供应商
+import supplier from "./supplier.vue";
+// 税率
+import tax from "./tax.vue";
+// 币种
+import currency from "./currency.vue";
+
+export const User = user;
+export const Organization = organization;
+export const Department = department;
+export const Supplier = supplier;
+export const Tax = tax;
+export const Currency = currency;
+export default { Tax, User, Supplier, Currency, Department, Organization };

+ 204 - 0
src/views/common-dialog/organization.vue

@@ -0,0 +1,204 @@
+<script>
+import { list, refer } from "./api/index";
+import { initParams } from "@/utils/init-something";
+
+export default {
+  name: "OrganizationInputDialog",
+  props: ["title", "value"],
+  components: {},
+  data() {
+    const columns = [
+      {
+        key: "deptId",
+        title: "组织编码",
+        type: "Input",
+        search: true,
+      },
+      {
+        key: "deptName",
+        title: "组织名称",
+        type: "Input",
+        search: true,
+      },
+    ];
+    const initTableColumns = () => columns.filter((column) => column.key);
+    const initSearchColumns = () => columns.filter((column) => column.search);
+    return {
+      // global
+      size: "mini",
+      width: "50%",
+      page: { pageNum: 1, pageSize: 25, total: 0 },
+      pageSizes: [25, 50],
+      layout: "prev, pager, next, jumper",
+      api: "puOrg",
+      showKey: "deptName",
+      // dialog
+      visible: false,
+      loading: false,
+      // search
+      searchColumns: initSearchColumns(),
+      params: initParams(initSearchColumns()),
+      // table
+      tableColumns: initTableColumns(),
+      data: [],
+      currentData: null,
+    };
+  },
+  computed: {},
+  watch: {},
+  methods: {
+    // set dialog visible
+    setVisible(prop) {
+      this.visible = prop;
+    },
+    // do something before dialog open
+    beforeOpen() {
+      const { value } = this.$props;
+      this.params[this.showKey] = value;
+      this.fetchList(this.params, this.page);
+    },
+    // fetch table data
+    async fetchList(prop, page) {
+      try {
+        this.loading = true;
+        const { pageNum, pageSize } = page;
+        // const { code, msg, rows, total } = await refer({
+        //   pageNum,
+        //   pageSize,
+        //   isPage: true,
+        //   type: "ORG_PARAM",
+        // });
+        const { code, msg, rows, total } = await list(this.api, {
+          ...prop,
+          pageNum,
+          pageSize,
+        });
+        if (code === 200) {
+          this.data = 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;
+        this.setCurrentData(
+          this.data.find(
+            (column) => column[this.showKey] === this.currentData[this.showKey]
+          )
+        );
+      }
+    },
+    // setting up to fetch table data
+    queryList() {
+      this.fetchList(this.params, this.page);
+    },
+    // reset to fetch table data
+    resetList() {
+      this.page.pageNum = 1;
+      this.params = initParams(this.searchColumns);
+      this.fetchList(this.params, this.page);
+    },
+    // size change to fetch table data
+    pageSizeChange(prop) {
+      this.page.pageSize = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // number change to fetch table data
+    pageNumberChange(prop) {
+      this.page.pageNum = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // select row data
+    selectCurrentData(row) {
+      this.currentData = row;
+    },
+    // set row data highlight
+    setCurrentData(row) {
+      this.$refs.singleTable.setCurrentRow(row);
+    },
+    //
+    confirm() {
+      if (this.currentData) {
+        this.$emit("confirm", this.currentData);
+      }
+      this.setVisible(false);
+    },
+  },
+  created() {},
+  mounted() {},
+  destroyed() {},
+};
+</script>
+<template>
+  <el-dialog
+    :title="title"
+    :visible.sync="visible"
+    :width="width"
+    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-item>
+      <el-form-item>
+        <el-button icon="el-icon-refresh" @click="resetList"></el-button>
+      </el-form-item>
+    </el-form>
+    <el-table
+      v-loading="loading"
+      :data="data"
+      :size="size"
+      ref="singleTable"
+      height="45vh"
+      highlight-current-row
+      style="width: 100%; margin-bottom: 20px"
+      @row-click="selectCurrentData"
+    >
+      <el-table-column
+        v-for="(column, index) in tableColumns"
+        :key="index"
+        :prop="column.key"
+        :label="column.title"
+        :width="column.width"
+        show-overflow-tooltip
+      >
+      </el-table-column>
+    </el-table>
+    <div
+      style="display: flex; justify-content: space-between; align-items: center"
+    >
+      <p>
+        <span style="font-size: 12px">已选择 :</span>
+        <el-tag v-if="currentData" :size="size">{{
+          currentData[showKey]
+        }}</el-tag>
+        <span v-else>无</span>
+      </p>
+      <el-pagination
+        :layout="layout"
+        :total="page.total"
+        :page-sizes="pageSizes"
+        :page-size="page.pageSize"
+        :current-page="page.pageNum"
+        :small="size === 'mini'"
+        background
+        @size-change="pageSizeChange"
+        @current-change="pageNumberChange"
+      >
+      </el-pagination>
+    </div>
+    <div style="margin-top: 20px; text-align: right">
+      <el-button :size="size" @click="visible = false">取 消</el-button>
+      <el-button :size="size" type="primary" @click="confirm">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+<style scoped></style>

+ 203 - 0
src/views/common-dialog/payment-plan.vue

@@ -0,0 +1,203 @@
+<script>
+import { initParams } from "./utils/init-something";
+import { list } from "./api/index";
+
+export default {
+  name: "PaymentPlanInputDialog",
+  props: ["title", "value"],
+  components: {},
+  data() {
+    const columns = [
+      {
+        key: "",
+        title: "付款协议名称",
+        type: "Input",
+        search: true,
+      },
+      {
+        key: "",
+        title: "付款协议编码",
+        type: "Input",
+        search: true,
+      },
+      {
+        key: "",
+        title: "管理组织",
+      },
+      {
+        key: "",
+        title: "有效期开始时间",
+      },
+      {
+        key: "",
+        title: "有效期结束时间",
+      },
+      {
+        key: "",
+        title: "说明",
+      },
+    ];
+    const initTableColumns = () => columns.filter((column) => column.key);
+    const initSearchColumns = () => columns.filter((column) => column.search);
+    return {
+      // global
+      size: "mini",
+      width: "50%",
+      page: { pageNum: 1, pageSize: 25, total: 0 },
+      pageSizes: [25, 50],
+      layout: "prev, pager, next, jumper",
+      api: "puTaxRate",
+      showKey: "mattaxesname",
+      // dialog
+      visible: false,
+      loading: false,
+      // search
+      searchColumns: initSearchColumns(),
+      params: initParams(initSearchColumns()),
+      // table
+      tableColumns: initTableColumns(),
+      data: [],
+      currentData: null,
+    };
+  },
+  computed: {},
+  watch: {},
+  methods: {
+    // set dialog visible
+    setVisible(prop) {
+      this.visible = prop;
+    },
+    // do something before dialog open
+    beforeOpen() {
+      const { value } = this.$props;
+      this.params.deptName = value;
+      this.fetchList(this.params, this.page);
+    },
+    // fetch table data
+    async fetchList(prop, page) {
+      try {
+        this.loading = true;
+        const { pageNum, pageSize } = page;
+        const { code, msg, rows, total } = await list(this.api, {
+          ...prop,
+          pageNum,
+          pageSize,
+        });
+        if (code === 200) {
+          this.data = 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;
+      }
+    },
+    // setting up to fetch table data
+    queryList() {
+      this.fetchList(this.params, this.page);
+    },
+    // reset to fetch table data
+    resetList() {
+      this.page.pageNum = 1;
+      this.params = initParams(this.searchColumns);
+      this.fetchList(this.params, this.page);
+    },
+    // size change to fetch table data
+    pageSizeChange(prop) {
+      this.page.pageSize = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // number change to fetch table data
+    pageNumberChange(prop) {
+      this.page.pageNum = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // select row data
+    selectCurrentData(row) {
+      this.currentData = row;
+    },
+    //
+    confirm() {
+      if (this.currentData) {
+        this.$emit("confirm", this.currentData);
+      }
+      this.setVisible(false);
+    },
+  },
+  created() {},
+  mounted() {},
+  destroyed() {},
+};
+</script>
+<template>
+  <el-dialog
+    :title="title"
+    :visible.sync="visible"
+    :width="width"
+    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-item>
+      <el-form-item>
+        <el-button icon="el-icon-refresh" @click="resetList"></el-button>
+      </el-form-item>
+    </el-form>
+    <el-table
+      v-loading="loading"
+      :data="data"
+      :size="size"
+      height="45vh"
+      style="width: 100%; margin-bottom: 20px"
+      @row-click="selectCurrentData"
+    >
+      <el-table-column
+        v-for="(column, index) in tableColumns"
+        :key="index"
+        :prop="column.key"
+        :label="column.title"
+        :width="column.width"
+        show-overflow-tooltip
+      >
+      </el-table-column>
+    </el-table>
+    <div
+      style="display: flex; justify-content: space-between; align-items: center"
+    >
+      <p>
+        <span style="font-size: 12px">已选择 :</span>
+        <el-tag v-if="currentData" :size="size">{{
+          currentData[showKey]
+        }}</el-tag>
+        <span v-else>无</span>
+      </p>
+      <el-pagination
+        :layout="layout"
+        :total="page.total"
+        :page-sizes="pageSizes"
+        :page-size="page.pageSize"
+        :current-page="page.pageNum"
+        :small="size === 'mini'"
+        background
+        @size-change="pageSizeChange"
+        @current-change="pageNumberChange"
+      >
+      </el-pagination>
+    </div>
+    <div style="margin-top: 20px; text-align: right">
+      <el-button :size="size" @click="visible = false">取 消</el-button>
+      <el-button :size="size" type="primary" @click="confirm">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+<style scoped></style>

+ 198 - 0
src/views/common-dialog/supplier.vue

@@ -0,0 +1,198 @@
+<script>
+import { initParams } from "./utils/init-something";
+import { list } from "./api/index";
+
+export default {
+  name: "SupplierInputDialog",
+  props: ["title", "value"],
+  components: {},
+  data() {
+    const columns = [
+      {
+        key: "code",
+        title: "供应商编码",
+        type: "Input",
+        search: true,
+      },
+      {
+        key: "name",
+        title: "供应商名称",
+        type: "Input",
+        search: true,
+      },
+    ];
+    const initTableColumns = () => columns.filter((column) => column.key);
+    const initSearchColumns = () => columns.filter((column) => column.search);
+    return {
+      // global
+      size: "mini",
+      width: "50%",
+      page: { pageNum: 1, pageSize: 25, total: 0 },
+      pageSizes: [25, 50],
+      layout: "prev, pager, next, jumper",
+      api: "puSupplier",
+      showKey: "name",
+      // dialog
+      visible: false,
+      loading: false,
+      // search
+      searchColumns: initSearchColumns(),
+      params: initParams(initSearchColumns()),
+      // table
+      tableColumns: initTableColumns(),
+      data: [],
+      currentData: null,
+    };
+  },
+  computed: {},
+  watch: {},
+  methods: {
+    // set dialog visible
+    setVisible(prop) {
+      this.visible = prop;
+    },
+    // do something before dialog open
+    beforeOpen() {
+      const { value } = this.$props;
+      this.params[this.showKey] = value;
+      this.fetchList(this.params, this.page);
+    },
+    // fetch table data
+    async fetchList(prop, page) {
+      try {
+        this.loading = true;
+        const { pageNum, pageSize } = page;
+        const { code, msg, rows, total } = await list(this.api, {
+          ...prop,
+          pageNum,
+          pageSize,
+        });
+        if (code === 200) {
+          this.data = 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;
+        this.setCurrentData(
+          this.data.find(
+            (column) => column[this.showKey] === this.currentData[this.showKey]
+          )
+        );
+      }
+    },
+    // setting up to fetch table data
+    queryList() {
+      this.fetchList(this.params, this.page);
+    },
+    // reset to fetch table data
+    resetList() {
+      this.page.pageNum = 1;
+      this.params = initParams(this.searchColumns);
+      this.fetchList(this.params, this.page);
+    },
+    // size change to fetch table data
+    pageSizeChange(prop) {
+      this.page.pageSize = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // number change to fetch table data
+    pageNumberChange(prop) {
+      this.page.pageNum = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // select row data
+    selectCurrentData(row) {
+      this.currentData = row;
+    },
+    // set row data highlight
+    setCurrentData(row) {
+      this.$refs.singleTable.setCurrentRow(row);
+    },
+    //
+    confirm() {
+      if (this.currentData) {
+        this.$emit("confirm", this.currentData);
+      }
+      this.setVisible(false);
+    },
+  },
+  created() {},
+  mounted() {},
+  destroyed() {},
+};
+</script>
+<template>
+  <el-dialog
+    :title="title"
+    :visible.sync="visible"
+    :width="width"
+    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-item>
+      <el-form-item>
+        <el-button icon="el-icon-refresh" @click="resetList"></el-button>
+      </el-form-item>
+    </el-form>
+    <el-table
+      v-loading="loading"
+      :data="data"
+      :size="size"
+      ref="singleTable"
+      height="45vh"
+      highlight-current-row
+      style="width: 100%; margin-bottom: 20px"
+      @row-click="selectCurrentData"
+    >
+      <el-table-column
+        v-for="(column, index) in tableColumns"
+        :key="index"
+        :prop="column.key"
+        :label="column.title"
+        :width="column.width"
+        show-overflow-tooltip
+      >
+      </el-table-column>
+    </el-table>
+    <div
+      style="display: flex; justify-content: space-between; align-items: center"
+    >
+      <p>
+        <span style="font-size: 12px">已选择 :</span>
+        <el-tag v-if="currentData" :size="size">{{
+          currentData[showKey]
+        }}</el-tag>
+        <span v-else>无</span>
+      </p>
+      <el-pagination
+        :layout="layout"
+        :total="page.total"
+        :page-sizes="pageSizes"
+        :page-size="page.pageSize"
+        :current-page="page.pageNum"
+        :small="size === 'mini'"
+        background
+        @size-change="pageSizeChange"
+        @current-change="pageNumberChange"
+      >
+      </el-pagination>
+    </div>
+    <div style="margin-top: 20px; text-align: right">
+      <el-button :size="size" @click="visible = false">取 消</el-button>
+      <el-button :size="size" type="primary" @click="confirm">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+<style scoped></style>

+ 198 - 0
src/views/common-dialog/tax.vue

@@ -0,0 +1,198 @@
+<script>
+import { initParams } from "./utils/init-something";
+import { list } from "./api/index";
+
+export default {
+  name: "TaxInputDialog",
+  props: ["title", "value"],
+  components: {},
+  data() {
+    const columns = [
+      {
+        key: "mattaxesname",
+        title: "税目税率名称",
+        type: "Input",
+        search: true,
+      },
+      {
+        key: "mattaxescode",
+        title: "税目税率编码",
+        type: "Input",
+        search: true,
+      },
+    ];
+    const initTableColumns = () => columns.filter((column) => column.key);
+    const initSearchColumns = () => columns.filter((column) => column.search);
+    return {
+      // global
+      size: "mini",
+      width: "50%",
+      page: { pageNum: 1, pageSize: 25, total: 0 },
+      pageSizes: [25, 50],
+      layout: "prev, pager, next, jumper",
+      api: "puTaxRate",
+      showKey: "mattaxesname",
+      // dialog
+      visible: false,
+      loading: false,
+      // search
+      searchColumns: initSearchColumns(),
+      params: initParams(initSearchColumns()),
+      // table
+      tableColumns: initTableColumns(),
+      data: [],
+      currentData: null,
+    };
+  },
+  computed: {},
+  watch: {},
+  methods: {
+    // set dialog visible
+    setVisible(prop) {
+      this.visible = prop;
+    },
+    // do something before dialog open
+    beforeOpen() {
+      const { value } = this.$props;
+      this.params[this.showKey] = value;
+      this.fetchList(this.params, this.page);
+    },
+    // fetch table data
+    async fetchList(prop, page) {
+      try {
+        this.loading = true;
+        const { pageNum, pageSize } = page;
+        const { code, msg, rows, total } = await list(this.api, {
+          ...prop,
+          pageNum,
+          pageSize,
+        });
+        if (code === 200) {
+          this.data = 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;
+        this.setCurrentData(
+          this.data.find(
+            (column) => column[this.showKey] === this.currentData[this.showKey]
+          )
+        );
+      }
+    },
+    // setting up to fetch table data
+    queryList() {
+      this.fetchList(this.params, this.page);
+    },
+    // reset to fetch table data
+    resetList() {
+      this.page.pageNum = 1;
+      this.params = initParams(this.searchColumns);
+      this.fetchList(this.params, this.page);
+    },
+    // size change to fetch table data
+    pageSizeChange(prop) {
+      this.page.pageSize = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // number change to fetch table data
+    pageNumberChange(prop) {
+      this.page.pageNum = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // select row data
+    selectCurrentData(row) {
+      this.currentData = row;
+    },
+    // set row data highlight
+    setCurrentData(row) {
+      this.$refs.singleTable.setCurrentRow(row);
+    },
+    //
+    confirm() {
+      if (this.currentData) {
+        this.$emit("confirm", this.currentData);
+      }
+      this.setVisible(false);
+    },
+  },
+  created() {},
+  mounted() {},
+  destroyed() {},
+};
+</script>
+<template>
+  <el-dialog
+    :title="title"
+    :visible.sync="visible"
+    :width="width"
+    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-item>
+      <el-form-item>
+        <el-button icon="el-icon-refresh" @click="resetList"></el-button>
+      </el-form-item>
+    </el-form>
+    <el-table
+      v-loading="loading"
+      :data="data"
+      :size="size"
+      ref="singleTable"
+      height="45vh"
+      highlight-current-row
+      style="width: 100%; margin-bottom: 20px"
+      @row-click="selectCurrentData"
+    >
+      <el-table-column
+        v-for="(column, index) in tableColumns"
+        :key="index"
+        :prop="column.key"
+        :label="column.title"
+        :width="column.width"
+        show-overflow-tooltip
+      >
+      </el-table-column>
+    </el-table>
+    <div
+      style="display: flex; justify-content: space-between; align-items: center"
+    >
+      <p>
+        <span style="font-size: 12px">已选择 :</span>
+        <el-tag v-if="currentData" :size="size">{{
+          currentData[showKey]
+        }}</el-tag>
+        <span v-else>无</span>
+      </p>
+      <el-pagination
+        :layout="layout"
+        :total="page.total"
+        :page-sizes="pageSizes"
+        :page-size="page.pageSize"
+        :current-page="page.pageNum"
+        :small="size === 'mini'"
+        background
+        @size-change="pageSizeChange"
+        @current-change="pageNumberChange"
+      >
+      </el-pagination>
+    </div>
+    <div style="margin-top: 20px; text-align: right">
+      <el-button :size="size" @click="visible = false">取 消</el-button>
+      <el-button :size="size" type="primary" @click="confirm">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+<style scoped></style>

+ 226 - 0
src/views/common-dialog/user.vue

@@ -0,0 +1,226 @@
+<script>
+import { initParams } from "./utils/init-something";
+import { list } from "./api/index";
+
+export default {
+  name: "UserInputDialog",
+  props: ["title"],
+  components: {},
+  data() {
+    const columns = [
+      {
+        key: "userName",
+        title: "员工姓名",
+        type: "Input",
+        search: true,
+      },
+      {
+        key: "userId",
+        title: "员工编码",
+        type: "Input",
+        search: true,
+      },
+      {
+        key: "orgName",
+        title: "任职(兼职)组织",
+        type: "Input",
+        width: 200,
+      },
+      {
+        key: "deptName",
+        title: "部门",
+        type: "Input",
+        width: 200,
+      },
+      {
+        key: "",
+        title: "岗位",
+        type: "Input",
+      },
+      {
+        key: "email",
+        title: "邮箱",
+        type: "Input",
+        width: 200,
+      },
+      {
+        key: "",
+        title: "职位",
+        type: "Input",
+      },
+    ];
+    const initTableColumns = () => columns.filter((column) => column.key);
+    const initSearchColumns = () => columns.filter((column) => column.search);
+    return {
+      // global
+      size: "mini",
+      width: "50%",
+      page: { pageNum: 1, pageSize: 25, total: 0 },
+      pageSizes: [25, 50],
+      layout: "prev, pager, next, jumper",
+      api: "puPersonnel",
+      showKey: "userName",
+      // dialog
+      visible: false,
+      loading: false,
+      // search
+      searchColumns: initSearchColumns(),
+      params: initParams(initSearchColumns()),
+      // table
+      tableColumns: initTableColumns(),
+      data: [],
+      currentData: null,
+    };
+  },
+  computed: {},
+  watch: {},
+  methods: {
+    // set dialog visible
+    setVisible(prop) {
+      this.visible = prop;
+    },
+    // do something before dialog open
+    beforeOpen() {
+      const { value } = this.$props;
+      this.params[this.showKey] = value;
+      this.fetchList(this.params, this.page);
+    },
+    // fetch table data
+    async fetchList(prop, page) {
+      try {
+        this.loading = true;
+        const { pageNum, pageSize } = page;
+        const { code, msg, rows, total } = await list(this.api, {
+          ...prop,
+          pageNum,
+          pageSize,
+        });
+        if (code === 200) {
+          this.data = 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;
+        this.setCurrentData(
+          this.data.find(
+            (column) => column[this.showKey] === this.currentData[this.showKey]
+          )
+        );
+      }
+    },
+    // setting up to fetch table data
+    queryList() {
+      this.fetchList(this.params, this.page);
+    },
+    // reset to fetch table data
+    resetList() {
+      this.page.pageNum = 1;
+      this.params = initParams(this.searchColumns);
+      this.fetchList(this.params, this.page);
+    },
+    // size change to fetch table data
+    pageSizeChange(prop) {
+      this.page.pageSize = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // number change to fetch table data
+    pageNumberChange(prop) {
+      this.page.pageNum = prop;
+      this.fetchList(this.params, this.page);
+    },
+    // select row data
+    selectCurrentData(row) {
+      this.currentData = row;
+    },
+    // set row data highlight
+    setCurrentData(row) {
+      this.$refs.singleTable.setCurrentRow(row);
+    },
+    //
+    confirm() {
+      if (this.currentData) {
+        this.$emit("confirm", this.currentData);
+      }
+      this.setVisible(false);
+    },
+  },
+  created() {},
+  mounted() {},
+  destroyed() {},
+};
+</script>
+<template>
+  <el-dialog
+    :title="title"
+    :visible.sync="visible"
+    :width="width"
+    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-item>
+      <el-form-item>
+        <el-button icon="el-icon-refresh" @click="resetList"></el-button>
+      </el-form-item>
+    </el-form>
+    <el-table
+      v-loading="loading"
+      :data="data"
+      :size="size"
+      ref="singleTable"
+      height="45vh"
+      highlight-current-row
+      style="width: 100%; margin-bottom: 20px"
+      @row-click="selectCurrentData"
+    >
+      <el-table-column
+        v-for="(column, index) in tableColumns"
+        :key="index"
+        :prop="column.key"
+        :label="column.title"
+        :width="column.width"
+        show-overflow-tooltip
+      >
+      </el-table-column>
+    </el-table>
+    <div
+      style="display: flex; justify-content: space-between; align-items: center"
+    >
+      <p>
+        <span style="font-size: 12px">已选择 :</span>
+        <el-tag v-if="currentData" :size="size">{{
+          currentData[showKey]
+        }}</el-tag>
+        <span v-else>无</span>
+      </p>
+      <el-pagination
+        :layout="layout"
+        :total="page.total"
+        :page-sizes="pageSizes"
+        :page-size="page.pageSize"
+        :current-page="page.pageNum"
+        :small="size === 'mini'"
+        background
+        @size-change="pageSizeChange"
+        @current-change="pageNumberChange"
+      >
+      </el-pagination>
+    </div>
+    <div style="margin-top: 20px; text-align: right">
+      <el-button :size="size" @click="visible = false">取 消</el-button>
+      <el-button :size="size" type="primary" @click="confirm">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+<style scoped></style>

+ 3 - 0
src/views/common-dialog/utils/init-something.js

@@ -0,0 +1,3 @@
+import { arr2obj } from "@/utils/data-transform";
+
+export const initParams = (arr) => arr2obj(arr, "key", "value");

+ 27 - 8
src/views/purchase/DemandSummary/add.vue

@@ -5,7 +5,7 @@
       <div class="btn_grooup">
         <el-button type="primary" size="small">编辑</el-button>
         <el-button type="primary" size="small">确定</el-button>
-        <el-button type="primary" size="small">行关闭</el-button>
+        <el-button type="primary" size="small" @click="closeLine">行关闭</el-button>
         <el-button type="primary" size="small">重取批量</el-button>
       </div>
 
@@ -16,13 +16,13 @@
           @selection-change="handleSelectionChange"
         >
         <el-table-column type="selection" width="55" />
-        <el-table-column label="序号" align="center" prop="code"/>
-        <el-table-column label="行号" align="center" prop="code"/>
+        <el-table-column label="序号" align="center" prop="index"/>
+        <el-table-column label="行号" align="center" prop="rowNo"/>
         <el-table-column label="物料编码" align="center" prop="code"/>
         <el-table-column label="品名" align="center" prop="code"/>
         <el-table-column label="规格" align="center" prop="code"/>
         <el-table-column label="单位" align="center" prop="code"/>
-        <el-table-column label="生产厂家/代理人" align="center" prop="code"/>
+        <el-table-column label="生产厂家/代理人" align="center" prop="manufacturer"/>
         <el-table-column label="末级供应仓库库存量" align="center" prop="code"/>
         <el-table-column label="月销量" align="center" prop="code"/>
         <el-table-column label="采购周期" align="center" prop="code"/>
@@ -84,7 +84,7 @@
 </template>
 
 <script>
-import {getSummaryDetail} from '@/api/purchase/DemandSummary.js'
+import {getSummaryDetail, shutDownSummary } from '@/api/purchase/DemandSummary.js'
 export default {
   name: 'checkDemandSummary',
   props: ['pageStu','row', 'disable'],
@@ -94,7 +94,8 @@ export default {
   },
   data() {
     return{
-      tableList: []
+      tableList: [],
+      ids: []
     }
   },
   created() {
@@ -106,7 +107,11 @@ export default {
     }
   },
   methods: {
-    handleSelectionChange() {},
+    handleSelectionChange(selection) {
+      console.log('选中', selection)
+      this.ids = selection.map(item => item.demandItemId)
+      console.log('选中数组', this.ids.join())
+    },
     back() {
       this.$emit('jugislist', true)
       let queryParams = {
@@ -119,10 +124,24 @@ export default {
     getDetails(row) {
       getSummaryDetail(row).then(res => {
         if (res.code === 200) {
-
+          this.tableList = res.data
         }
       })
     },
+    // 行关闭
+    closeLine() {
+      if (this.ids.length == 0) {
+        this.$modal.msgWarning("请选中至少一条数据");
+      } else {
+        let param = this.ids.join()
+        shutDownSummary(param).then(res => {
+          if (res.code === 200) {
+            this.$modal.msgSuccess("取消成功");
+            this.getDetails(this.row)
+          }
+        })
+      }
+    },
   }
 }
 </script>

+ 45 - 7
src/views/purchase/DemandSummary/index.vue

@@ -284,10 +284,10 @@
         <div class="btn_grooup">
           <el-button type="primary" size="small">编辑</el-button>
           <el-button type="primary" size="small">保存</el-button>
-          <el-button type="primary" size="small">确认</el-button>
-          <el-button type="primary" size="small">取消</el-button>
+          <el-button type="primary" size="small" @click="confirms">确认</el-button>
+          <el-button type="primary" size="small" @click="cancels">取消</el-button>
           <el-button type="primary" size="small" @click="audits">审核</el-button>
-          <el-button type="primary" size="small">弃审</el-button>
+          <el-button type="primary" size="small" @click="cancelAudits">弃审</el-button>
 
           <el-dropdown size="small" @command="handleCommand">
             <el-button size="small" type="primary" style="margin: 0 10px;">
@@ -391,7 +391,7 @@
 <script>
 import Add from './add.vue'
 import CollapseTransition from '@/components/MyCollapse/collapse.vue'
-import {getSummaryList, auditSummary} from '@/api/purchase/DemandSummary.js'
+import {getSummaryList, auditSummary, confirmSummary , cancelSummary , cancelAuditSummary } from '@/api/purchase/DemandSummary.js'
 export default {
   name: 'demandSummary',
   components: {
@@ -422,15 +422,16 @@ export default {
         pageSize: 10
       },
       options: [{
-        value: '1', label: '是',
+        value: '0', label: '是',
       }, {
-        value: '0', label: '否'
+        value: '2', label: '否'
       }],
       tableList: [],
       total: 0,
       rowDetail: {},
       disable: false,
-      ids: []
+      ids: [],
+      allSelection: [],
     }
   },
   created() {
@@ -447,6 +448,7 @@ export default {
     },
     handleSelectionChange(selection) {
       console.log('选中', selection)
+      this.allSelection = selection
       this.ids = selection.map(item => item.demandItemId)
       console.log('选中数组', this.ids.join())
     },
@@ -472,6 +474,29 @@ export default {
     drop() {
       this.expanded = !this.expanded
     },
+    confirms() {
+      if (this.ids.length == 0) {
+        this.$modal.msgWarning("请选中至少一条数据");
+      } else {
+        confirmSummary(this.allSelection).then(res => {
+          this.$modal.msgSuccess("确认成功");
+          this.getList(this.queryParams)
+        })
+      }
+    },
+    cancels() {
+      if (this.ids.length == 0) {
+        this.$modal.msgWarning("请选中至少一条数据");
+      } else {
+        let param = this.ids.join()
+        cancelSummary(param).then(res => {
+          if (res.code === 200) {
+            this.$modal.msgSuccess("取消成功");
+            this.getList(this.queryParams)
+          }
+        })
+      }
+    },
     audits() {
       if(this.ids.length == 0) {
         this.$modal.msgWarning("请选中至少一条数据");
@@ -485,6 +510,19 @@ export default {
         })
       }
     },
+    cancelAudits() {
+      if (this.ids.length == 0) {
+        this.$modal.msgWarning("请选中至少一条数据");
+      } else {
+        let param = this.ids.join()
+        cancelAuditSummary(param).then(res => {
+          if (res.code === 200) {
+            this.$modal.msgSuccess("操作成功");
+            this.getList(this.queryParams)
+          }
+        })
+      } 
+    },
   }
 }
 </script>

+ 113 - 91
src/views/purchase/PurchaseDemandList/add.vue

@@ -17,20 +17,16 @@
 
         <el-col :span="1.5">
             <el-form-item label="组织">
-              <el-input v-model="basicForm.org" size="small" style="width: 200px">
-               <el-button slot="append" icon="el-icon-more" @click="chooseOrg"></el-button>
-              </el-input>
+              <el-select size="small" v-model="basicForm.org" :disabled="disable" @focus="chooseOrg" style="width: 200px">
+                <el-option v-for="item in orgOptions" :key="item.id" :label="item.name" :value="item.id" />
+              </el-select>
             </el-form-item>
          </el-col>
 
          <el-col :span="1.5">
             <el-form-item label="需求处理方式">
-              <el-select v-model="basicForm.demandBusinessType" size="small" style="width: 200px" clearable placeholder="请选择">
-                <el-option
-                  v-for="item in options"
-                  :key="item.value"
-                  :label="item.label"
-                  :value="item.value">
+              <el-select v-model="basicForm.demandBusinessType" size="small" style="width: 200px">
+                <el-option v-for="dict in dict.type.sys_processing_mode" :key="dict.value" :label="dict.label" :value="dict.value">
                 </el-option>
               </el-select>
             </el-form-item>
@@ -39,11 +35,7 @@
          <el-col :span="1.5">
             <el-form-item label="单据状态">
               <el-select v-model="basicForm.status" size="small" style="width: 200px" clearable placeholder="请选择">
-                <el-option
-                  v-for="item in options"
-                  :key="item.value"
-                  :label="item.label"
-                  :value="item.value">
+                <el-option v-for="dict in dict.type.sys_status" :key="dict.value" :label="dict.label" :value="dict.value">
                 </el-option>
               </el-select>
             </el-form-item>
@@ -51,53 +43,29 @@
 
          <el-col :span="1.5">
             <el-form-item label="需求客户">
-              <el-select v-model="basicForm.customer" size="small" style="width: 200px" clearable placeholder="请选择">
-                <el-option
-                  v-for="item in options"
-                  :key="item.value"
-                  :label="item.label"
-                  :value="item.value">
-                </el-option>
+              <el-select size="small" v-model="basicForm.customer" :disabled="disable" @focus="chooseCustomer" style="width: 200px">
+                <el-option v-for="item in customerOptions" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
           </el-col>
 
          <el-col :span="1.5">
             <el-form-item label="需求客户名称">
-              <el-select v-model="basicForm.customerName" size="small" style="width: 200px" clearable placeholder="请选择">
-                <el-option
-                  v-for="item in options"
-                  :key="item.value"
-                  :label="item.label"
-                  :value="item.value">
-                </el-option>
-              </el-select>
+              <el-input v-model="basicForm.customerName" size="small" style="width: 200px"></el-input>
             </el-form-item>
           </el-col>
 
          <el-col :span="1.5">
             <el-form-item label="客户负责人">
-              <el-select v-model="basicForm.customerPrincipal" size="small" style="width: 200px" clearable placeholder="请选择">
-                <el-option
-                  v-for="item in options"
-                  :key="item.value"
-                  :label="item.label"
-                  :value="item.value">
-                </el-option>
-              </el-select>
+              <el-input v-model="basicForm.customerPrincipal" size="small" style="width: 200px"></el-input>
             </el-form-item>
           </el-col>
 
          <el-col :span="1.5">
             <el-form-item label="需求人员">
-              <el-select v-model="basicForm.demandPersonal" size="small" style="width: 200px" clearable placeholder="请选择">
-                <el-option
-                  v-for="item in options"
-                  :key="item.value"
-                  :label="item.label"
-                  :value="item.value">
-                </el-option>
-              </el-select>
+                <el-select size="small" v-model="basicForm.demandPersonal" :disabled="disable" @focus="choosePerson" style="width: 200px">
+                  <el-option v-for="item in personOptions" :key="item.id" :label="item.name" :value="item.id" />
+                </el-select>
             </el-form-item>
           </el-col>
 
@@ -116,61 +84,46 @@
 
           <el-col :span="1.5">
             <el-form-item label="需求日期">
-              <el-input
+              <el-date-picker
                 v-model="basicForm.demandDate"
+                type="date"
+                value-format="yyyy-MM-dd"
                 size="small"
-                placeholder=""
-                clearable
                 style="width: 200px"
-              />
+              >
+              </el-date-picker>
             </el-form-item>
          </el-col>
 
           <el-col :span="1.5">
             <el-form-item label="单据来源">
-              <el-input
-                v-model="basicForm.source"
-                size="small"
-                placeholder=""
-                clearable
-                style="width: 200px"
-              />
+              <el-select v-model="basicForm.source" size="small" style="width: 200px">
+                <el-option v-for="dict in dict.type.sys_bill_source" :key="dict.value" :label="dict.label" :value="dict.value">
+                </el-option>
+              </el-select>
             </el-form-item>
          </el-col>
 
           <el-col :span="1.5">
             <el-form-item label="供应仓库">
-              <el-input
-                v-model="basicForm.warehouse"
-                size="small"
-                placeholder=""
-                clearable
-                style="width: 200px"
-              />
+              <el-select size="small" v-model="basicForm.warehouse" :disabled="disable" @focus="chooseHouse" style="width: 200px">
+                <el-option v-for="item in houseOptions" :key="item.id" :label="item.name" :value="item.id" />
+              </el-select>
             </el-form-item>
          </el-col>
 
          <el-col :span="1.5">
             <el-form-item label="供应货位">
-              <el-select v-model="basicForm.goodsAllocation" size="small" style="width: 200px" clearable placeholder="请选择">
-                <el-option
-                  v-for="item in options"
-                  :key="item.value"
-                  :label="item.label"
-                  :value="item.value">
-                </el-option>
+              <el-select size="small" v-model="basicForm.goodsAllocation" :disabled="disable" @focus="chooseGoods" style="width: 200px">
+                <el-option v-for="item in goodsOptions" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
           </el-col>
 
          <el-col :span="1.5">
             <el-form-item label="业务类型">
-              <el-select v-model="basicForm.billType" size="small" style="width: 200px" clearable placeholder="请选择">
-                <el-option
-                  v-for="item in options"
-                  :key="item.value"
-                  :label="item.label"
-                  :value="item.value">
+              <el-select v-model="basicForm.billType" size="small" style="width: 200px">
+                <el-option v-for=" dict in dict.type.sys_business" :key="dict.value" :label="dict.label" :value="dict.value">
                 </el-option>
               </el-select>
             </el-form-item>
@@ -178,13 +131,10 @@
 
           <el-col :span="1.5">
             <el-form-item label="是否客户指定">
-              <el-input
-                v-model="basicForm.isSpeical"
-                size="small"
-                placeholder=""
-                clearable
-                style="width: 200px"
-              />
+              <el-select v-model="basicForm.isSpeical" size="small" style="width: 200px">
+                <el-option v-for=" item in options" :key="item.value" :label="item.label" :value="item.value">
+                </el-option>
+              </el-select>
             </el-form-item>
          </el-col>
 
@@ -499,19 +449,25 @@
       </el-col>
 
       <Reserved v-if="dialog.config" :isVisible="dialog.config" :info="row" @updateReserved="updateReserved"/>
+
+      <Refers ref="refer" @doSubmit="selectionsToInput" :single="true"/>
     </div>
   </div>
 </template>
 
 <script>
 import Reserved from './reserved.vue'
+import Refers from './refers.vue'
 import {addDemand,getDemandDetail, getDemandSonDetail, editDemand} from '@/api/purchase/purchaseDemand.js'
+// 用于回显参照框数据
 import {getRefer} from '@/api/purchase/basic.js'
 export default {
   name: 'addDemandList',
   props: ['pageStu','row', 'disable'],
+  dicts: ['sys_processing_mode', 'sys_status', 'sys_bill_source', 'sys_business'],
   components: {
-    Reserved
+    Reserved,
+    Refers
   },
   model: {
     prop: 'isList',
@@ -544,12 +500,23 @@ export default {
         puDemandItemList: []
       },
       options: [{
-        value: '1', label: '是',
+        value: '0', label: '是',
       }, {
-        value: '0', label: '否'
+        value: '2', label: '否'
       }],
       basicRules: {},
-      tableList: []
+      tableList: [],
+      referCondition: {
+        type: 'ORG_PARAM',
+        search: '',
+        isPage: true,
+        title: '选择组织'
+      },
+      orgOptions: [],
+      personOptions: [],
+      customerOptions: [],
+      houseOptions: [],
+      goodsOptions: []
     }
   },
   created() {
@@ -706,6 +673,7 @@ export default {
               reciveForm.puDemandItemList = res.rows
               console.log('reciveForm',reciveForm)
               this.basicForm = reciveForm
+              this.reBackRefer({type: 'ORG_PARAM', search: this.basicForm.org, isPage: false})
             }
           })
         }
@@ -720,12 +688,66 @@ export default {
 	  updateReserved (val) {
       this.dialog.config = val
     },
-    chooseOrg() {
-      getRefer({type:'ORG_PARAM', search:'BB国际'}).then(res => {
-        console.log("🚀 ~ file: add.vue:725 ~ getRefer ~ res:", res)
-        
+    // 回显参照框
+    reBackRefer(val) {
+      getRefer(val).then(res => {
+        console.log("🚀 ~ file: add.vue:706 ~ getRefer ~ res:", res)
       })
     },
+    chooseOrg() {
+      this.referCondition.type = 'ORG_PARAM'
+      this.referCondition.search = ''
+      this.referCondition.isPage = true
+      this.referCondition.title = '选择组织'
+      this.$refs.refer.init(this.referCondition)
+    },
+    chooseCustomer () {
+      this.referCondition.type = ''
+      this.referCondition.search = ''
+      this.referCondition.isPage = true
+      this.referCondition.title = '选择客户'
+      this.$refs.refer.init(this.referCondition)
+    },
+    choosePerson() {
+      this.referCondition.type = 'CONTACTS_PARAM'
+      this.referCondition.search = ''
+      this.referCondition.isPage = true
+      this.referCondition.title = '需求人员'
+      this.$refs.refer.init(this.referCondition)
+    },
+    chooseHouse() {
+      this.referCondition.type = 'WAREHOUSE_PARAM'
+      this.referCondition.search = ''
+      this.referCondition.isPage = true
+      this.referCondition.title = '供应仓库'
+      this.$refs.refer.init(this.referCondition)
+    },
+    chooseGoods() {
+      this.referCondition.type = 'ALLOCATION_PARAM'
+      this.referCondition.search = ''
+      this.referCondition.isPage = true
+      this.referCondition.title = '供应货位'
+      this.$refs.refer.init(this.referCondition)
+    },
+    selectionsToInput(selection) {
+      console.log("🚀 ~ file: add.vue:732 ~ selectionsToInput ~ selection:", selection)
+      if(this.referCondition.type == 'ORG_PARAM') {
+        this.orgOptions = selection
+        this.basicForm.org = selection[0].id
+      }
+      if(this.referCondition.type == 'CONTACTS_PARAM') {
+        this.personOptions = selection
+        this.basicForm.demandPersonal = selection[0].id
+      }
+      if(this.referCondition.type == 'WAREHOUSE_PARAM') {
+        this.houseOptions = selection
+        this.basicForm.warehouse = selection[0].id
+      }
+      if(this.referCondition.type == 'ALLOCATION_PARAM') {
+        this.goodsOptions = selection
+        this.basicForm.goodsAllocation = selection[0].id
+      }
+    }
   }
 }
 </script>

+ 170 - 0
src/views/purchase/PurchaseDemandList/refers.vue

@@ -0,0 +1,170 @@
+<template>
+  <div>
+    <el-dialog :title="reciveForm.title" width="1000px" :close-on-click-modal="false" :append-to-body="true" v-dialogDrag
+      class="userDialog" :visible.sync="visible">
+      <el-container style="height: 500px">
+        <el-container>
+          <el-header style="text-align: left; font-size: 12px; height: 30px">
+            <el-form size="small" :inline="true" ref="searchForm" :model="searchForm" @keyup.enter.native="refreshList()"
+              @submit.native.prevent>
+              <el-form-item prop="param" label="名称/编号">
+                <el-input size="small" v-model="searchForm.param" placeholder="输入名称/编号查询" clearable></el-input>
+              </el-form-item>
+              <el-form-item>
+                <el-button type="primary" @click="refreshList()" size="small" icon="el-icon-search">查询</el-button>
+                <el-button @click="resetSearch()" size="small" icon="el-icon-refresh-right">重置</el-button>
+              </el-form-item>
+            </el-form>
+          </el-header>
+          <el-main>
+            <el-table :data="dataList" v-loading="loading" size="small" border ref="contractTable"
+              @select="handleSelectionChange" @row-click="rowSelect" height="calc(100% - 40px)" style="width: 100%">
+              <el-table-column type="selection" header-align="center" align="center" width="50">
+              </el-table-column>
+              <el-table-column prop="id" header-align="center" align="center" sortable="custom" min-width="90" label="id">
+              </el-table-column>
+              <el-table-column prop="name" header-align="center" align="center" sortable="custom" min-width="90"
+                label="名称">
+              </el-table-column>
+            </el-table>
+            <el-pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle"
+              :current-page="searchForm.pageNo" :page-sizes="[5, 10, 15, 20]" :page-size="searchForm.pageSize"
+              :total="total" layout="total, sizes, prev, pager, next, jumper">
+            </el-pagination>
+          </el-main>
+        </el-container>
+      </el-container>
+      <span slot="footer" class="dialog-footer">
+        <el-button size="small" @click="visible = false" icon="el-icon-circle-close">关闭</el-button>
+        <el-button size="small" type="primary" icon="el-icon-circle-check" @click="doSubmit()">确定</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getRefer } from '@/api/purchase/basic'
+export default {
+  data() {
+    return {
+      searchForm: {
+        param: '',
+        pageNo: 1,
+        pageSize: 10,
+      },
+      reciveForm: {},
+      dataListAllSelections: [], // 所有选中的数据包含跨页数据
+      idKey: "id", // 标识列表数据中每一行的唯一键的名称(需要按自己的数据改一下)
+      dataList: [],
+      total: 0,
+      orders: [],
+      loading: false,
+      visible: false,
+    };
+  },
+  props: {
+    selectData: {
+      type: Array,
+      default: () => {
+        return [];
+      },
+    },
+    // 是否启用单选
+    single: {
+      type: Boolean,
+      default: false
+    }
+  },
+  methods: {
+    init(val) {
+      this.visible = true;
+      console.log("🚀 ~ file: refers.vue:79 ~ init ~ init(val):", val)
+      this.reciveForm = val
+      this.$nextTick(() => {
+        this.dataListAllSelections = JSON.parse(JSON.stringify(this.selectData));
+        this.resetSearch();
+      });
+    },
+    // 获取数据列表
+    refreshList() {
+      this.loading = true;
+      let params = {...this.searchForm, ...this.reciveForm}
+      getRefer(params).then(res => {
+        console.log('res', res)
+        this.dataList = res.rows;
+        this.total = res.total
+        this.loading = false;
+        this.$nextTick(() => {
+          this.setSelectRow();
+        });
+      });
+    },
+    // 每页数
+    sizeChangeHandle(val) {
+      this.searchForm.pageSize = val;
+      this.refreshList();
+    },
+    // 当前页
+    currentChangeHandle(val) {
+      this.searchForm.pageNo = val;
+      this.refreshList();
+    },
+    // 排序
+    resetSearch() {
+      this.$refs['searchForm'].resetFields();
+      this.searchForm.pageNo = 1;
+      this.refreshList();
+    },
+    // 表格选中数据
+    rowSelect(row, column, event) {
+      this.$refs.contractTable.clearSelection();
+      this.$refs.contractTable.toggleRowSelection(row);
+      this.dataListAllSelections = this.single ? [row] : selection
+    },
+    // 选中数据
+    handleSelectionChange(selection, row) {
+      if (this.single && selection.length > 1) {
+        this.$refs.contractTable.clearSelection();
+        this.$refs.contractTable.toggleRowSelection(row);
+      }
+      this.dataListAllSelections = this.single ? [row] : selection
+    },
+    // 设置选中的方法
+    setSelectRow() {
+      this.$refs.contractTable.clearSelection();
+      if (!this.dataListAllSelections || this.dataListAllSelections.length <= 0) {
+        return;
+      }
+      for (let i = 0; i < this.dataList.length; i++) {
+        if (this.dataListAllSelections.some(item => item[this.idKey] == this.dataList[i][this.idKey])) {
+          // 设置选中,记住table组件需要使用ref="table"
+          this.$refs.contractTable.toggleRowSelection(this.dataList[i], true);
+        }
+      }
+    },
+    doSubmit() {
+      this.visible = false;
+      console.log('选择的数据?', this.dataListAllSelections)
+      this.$emit("doSubmit", this.dataListAllSelections);
+    },
+  },
+};
+</script>
+<style lang="scss">
+.userDialog {
+  .el-dialog__body {
+    padding: 10px 0px 0px 10px;
+    color: #606266;
+    font-size: 14px;
+    word-break: break-all;
+  }
+
+  .el-main {
+    padding: 20px 20px 5px 20px;
+
+    .el-pagination {
+      margin-top: 5px;
+    }
+  }
+}
+</style>

+ 139 - 229
src/views/purchase/purchase-contract/add-purchase-contract.vue

@@ -1,215 +1,24 @@
 <script>
+import { add } from "@/api/business/purchase/purchase-contract";
+import { arr2obj } from "@/utils/data-transform";
+import {
+  initDicts,
+  initRules,
+  initParams,
+  initComponents,
+} from "@/utils/init-something";
+import { initColumns } from "./config/add";
+
 export default {
   name: "AddPurchaseContractDrawer",
+  components: initComponents(initColumns()),
+  dicts: initDicts(initColumns()),
   data() {
-    const arr2Obj = function (data, keyName, valueName) {
-      return Object.fromEntries(
-        data.map((item) => [item[keyName], item[valueName]])
-      );
-    };
-    const columns = [
-      { key: "puOrg", title: "采购组织", type: "TagSelect", require: true },
-      { key: "code", title: "合同编码", type: "Input" },
-      { key: "contractName", title: "合同名称", type: "Input", require: true },
-      { key: "supplier", title: "供应商", type: "TagSelect", require: true },
-      { key: "contractType", title: "合同类型", type: "Select", require: true },
-      { key: "puDept", title: "采购部门", type: "TagSelect", require: true },
-      { key: "buyer", title: "采购员", type: "TagSelect" },
-      { key: "source", title: "合同来源", type: "Select" },
-      {
-        key: "signDate",
-        title: "合同签订日期",
-        type: "DatePicker",
-        require: true,
-      },
-      {
-        key: "effectiveDate",
-        title: "合同生效日期",
-        type: "DatePicker",
-        require: true,
-      },
-      { key: "endDate", title: "合同终止日期", type: "DatePicker" },
-      { key: "externalContract", title: "外部合同号", type: "Input" },
-      { key: "refusalReasons", title: "拒绝理由", type: "Input" },
-      { 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: "projectName", title: "项目名称", type: "TagSelect" },
-      { key: "projectCode", title: "项目编号", type: "Input" },
-      { key: "area", title: "区域", type: "Input" },
-      { key: "consigneePhone", title: "收货人联系方式", type: "Input" },
-      { key: "paymentAgreement", title: "付款协议", type: "TagSelect" },
-      { key: "currency", title: "币种", type: "TagSelect", require: true },
-      { key: "taxPrice", title: "价税合计", type: "InputNumber" },
-      { key: "guaranteePeriod", title: "质保期", type: "Input" },
-
-      // { key: "lastPuMoney", title: "上年度采购额" },
-      // { key: "buyerName", title: "采购员名称" },
-      // { key: "supplierName", title: "供应商名称" },
-      // { key: "puMoneyYear", title: "本年度采购额" },
-      // { key: "puDeptName", title: "采购部门名称" },
-      // { key: "supplierTier", title: "供应商层级" },
-      // { key: "grossRateAverage", title: "平均毛利率" },
-      // { key: "approveFlow", title: "审批流程" },
-      // { key: "consumableClass", title: "耗材类别" },
-      // { key: "brandGrossRate", title: "同类品牌及毛利率" },
-      // { key: "contractFormat", title: "合同格式" },
-      // { key: "productName", title: "产品类别&名称" },
-      // { key: "invoiceTax", title: "发票税率" },
-      // { key: "emergencyDegree", title: "紧急程度" },
-      // { key: "project", title: "项目医院" },
-      // { key: "deliveryType", title: "交货方式" },
-      // { key: "contractPartyc", title: "合同丙方" },
-      // { key: "contractPartycName", title: "合同丙方名称" },
-      // { key: "guaranteePeriodEnd", title: "质保期限" },
-      // { key: "freightMethods", title: "运费承担方式" },
-      // { key: "isTarget", title: "是否有指标" },
-      // { key: "contractTarget", title: "合同指标" },
-      // { key: "exemptionPostageCondtion", title: "包邮条件" },
-      // { key: "isRebate", title: "是否有返利" },
-      // { key: "rebatePolicy", title: "返利政策" },
-      // { key: "rollbackPolicy", title: "退换货政策" },
-      // { key: "contractContent", title: "合同主要内容" },
-      // { key: "currencyName", title: "币种名称" },
-      // { key: "tenantId", title: "租户号" },
-      // { key: "revision", title: "乐观锁" },
-      // { key: "createByName", title: "创建人" },
-      // { key: "updateByName", title: "创建人名称" },
-      // { key: "delFlag", title: "删除标记" },
-    ];
-    const initColumns = () =>
-      columns.map((column) => {
-        const clearable = column.clearable || true;
-        if (column.type === "InputNumber") {
-          return {
-            ...column,
-            clearable,
-            config: { controlsPosition: "right" },
-          };
-        }
-        if (column.type === "DatePicker") {
-          return {
-            ...column,
-            clearable,
-            config: { type: "date" },
-          };
-        }
-        return {
-          ...column,
-          clearable,
-        };
-      });
-    const initParams = () => arr2Obj(initColumns(), "key", "value");
-    const tabColumns = [
-      {
-        title: "物料基本信息",
-        key: "first",
-        tableColumns: [
-          { title: "序号", key: "" },
-          { title: "赠品", key: "" },
-          { title: "物料编码", key: "" },
-          { title: "物料名称", key: "" },
-          { title: "规格", key: "" },
-          { title: "生产厂家", key: "" },
-          { title: "收货客户", key: "" },
-          { title: "品牌", key: "" },
-          { title: "采购数量", key: "" },
-          { title: "采购单位", key: "" },
-          { title: "计价数量", key: "" },
-          { title: "税率%", key: "" },
-          { title: "含税单价", key: "" },
-          { title: "含税金额合计", key: "" },
-          { title: "价格有效期(起)", key: "" },
-          { title: "计划到货日期", key: "" },
-          { title: "来源类型", key: "" },
-          { title: "来源单号", key: "" },
-          { title: "需求单号", key: "" },
-          { title: "备注", key: "" },
-        ],
-      },
-      {
-        title: "合同条款",
-        key: "second",
-        tableColumns: [
-          { title: "序号", key: "" },
-          { title: "条款编码", key: "" },
-          { title: "条款名称", key: "" },
-          { title: "条款内容", key: "" },
-          { title: "变量序号", key: "" },
-          { title: "变量内容", key: "" },
-          { title: "备注", key: "" },
-        ],
-      },
-      {
-        title: "合同费用",
-        key: "third",
-        tableColumns: [
-          { title: "序号", key: "" },
-          { title: "费用编码", key: "" },
-          { title: "费用名称", key: "" },
-          { title: "费用金额", key: "" },
-          { title: "备注", key: "" },
-        ],
-      },
-      {
-        title: "付款协议信息",
-        key: "fourth",
-        tableColumns: [
-          { title: "序号", key: "" },
-          { title: "付款阶段", key: "" },
-          { title: "是否预付款", key: "" },
-          { title: "是否质保金", key: "" },
-          { title: "结算方式", key: "" },
-          { title: "付款起点", key: "" },
-          { title: "付款金额", key: "" },
-          { title: "付款比例%", key: "" },
-          { title: "账期天数", key: "" },
-          { title: "备注", key: "" },
-        ],
-      },
-      {
-        title: "合同执行组织范围",
-        key: "fifth",
-        tableColumns: [
-          { title: "序号", key: "" },
-          { title: "组织名称", key: "" },
-          { title: "组织编码", key: "" },
-        ],
-      },
-    ];
-    const initTabColumns = () => tabColumns;
     return {
-      visible: false,
+      visible: true,
       columns: initColumns(),
-      params: initParams(),
-      options: [
-        {
-          value: "选项1",
-          label: "黄金糕",
-        },
-        {
-          value: "选项2",
-          label: "双皮奶",
-        },
-        {
-          value: "选项3",
-          label: "蚵仔煎",
-        },
-        {
-          value: "选项4",
-          label: "龙须面",
-        },
-        {
-          value: "选项5",
-          label: "北京烤鸭",
-        },
-      ],
+      rules: initRules(initColumns()),
+      params: initParams(initColumns()),
       tabColumns: initTabColumns(),
       tabName: "first",
       tabTableDatas: {
@@ -219,17 +28,78 @@ export default {
         fourth: [],
         fifth: [],
       },
+      currentComponent: { name: "", title: "", value: "", row: {} },
     };
   },
   computed: {},
   watch: {},
   methods: {
+    beforeOpen() {
+      const { deptName, nickName, orgName } = this.$store.state.user;
+      this.params.puOrg = orgName;
+      this.params.buyer = nickName;
+      this.params.puDept = deptName;
+    },
     setVisible(prop) {
       this.visible = prop;
     },
+    addTableRow() {},
+    cancel() {
+      this.setVisible(false);
+      this.params = arr2obj(this.columns, "key", "value");
+    },
+    sava() {
+      this.setVisible(false);
+    },
+    async submitSava() {
+      console.log(this.params);
+      return;
+      try {
+        const res = await add(this.params);
+        console.log("res", res);
+      } catch (err) {
+        this.$notify.error({ title: "error", message: err });
+      } finally {
+        this.setVisible(false);
+      }
+    },
+    //
+    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]];
+      }
+    },
   },
   created() {
-    console.log(this.params, this.columns);
+    // console.log("this,", initComponents(initColumns()));
   },
   mounted() {},
   destroyed() {},
@@ -237,12 +107,11 @@ export default {
 </script>
 <template>
   <el-drawer
-    title="我是标题"
     direction="btt"
     size="100%"
     :with-header="false"
     :visible.sync="visible"
-    :before-close="handleClose"
+    @open="beforeOpen"
   >
     <el-card
       :body-style="{
@@ -262,38 +131,69 @@ export default {
       >
         <h3>新增</h3>
         <div style="text-align: right">
-          <el-button size="mini" @click="setVisible(false)">取消</el-button>
-          <el-button size="mini" type="info" @click="setVisible(false)"
-            >保存并新增</el-button
-          >
-          <el-button size="mini" type="danger" @click="setVisible(false)"
-            >保存</el-button
-          >
+          <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="150px"
+          label-width="135px"
           :model="params"
+          :rules="rules"
         >
           <el-col
             v-for="(column, index) in columns"
             :key="index"
-            :span="column.span || 8"
+            :span="column.span || 6"
           >
-            <el-form-item
-              :prop="column.key"
-              :label="column.title"
-              :required="column.required"
-            >
+            <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"
-                style="width: 90%"
+                :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'"
@@ -301,17 +201,19 @@ export default {
                 :controls-position="column.config.controlsPosition"
                 :placeholder="column.placeholder"
                 :clearable="column.clearable"
-                style="width: 90%"
+                :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"
-                style="width: 90%"
+                :disabled="column.disabled"
+                style="width: 100%"
               >
                 <el-option
-                  v-for="item in options"
+                  v-for="item in dict.type[column.config.optionsName]"
                   :key="item.value"
                   :label="item.label"
                   :value="item.value"
@@ -326,7 +228,8 @@ export default {
                 collapse-tags
                 :placeholder="column.placeholder"
                 :clearable="column.clearable"
-                style="width: 90%"
+                :disabled="column.disabled"
+                style="width: 100%"
               >
                 <template #prefix>
                   <el-icon
@@ -349,13 +252,15 @@ export default {
                 :type="column.config.type"
                 :placeholder="column.placeholder"
                 :clearable="column.clearable"
+                :disabled="column.disabled"
                 :picker-options="column.pickerOptions"
-                style="width: 90%"
+                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
@@ -378,6 +283,7 @@ export default {
         padding: '20px',
         display: 'flex',
         'flex-wrap': 'wrap',
+        position: 'relative',
       }"
       style="margin: 10px"
     >
@@ -394,11 +300,15 @@ export default {
               :key="cIndex"
               :prop="cColumn.key"
               :label="cColumn.title"
+              :width="cColumn.width"
             >
             </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">增行</el-button>
+      </el-row>
     </el-card>
   </el-drawer>
 </template>

+ 401 - 0
src/views/purchase/purchase-contract/config/add.js

@@ -0,0 +1,401 @@
+const columns = [
+  {
+    key: "puOrg",
+    title: "采购组织",
+    type: "InputDialog",
+    config: {
+      componentName: "Organization",
+      dataMapping: { puOrg: "deptName" },
+    },
+    require: true,
+  },
+  { key: "code", title: "合同编码", type: "Input" },
+  {
+    key: "lastPuMoney",
+    title: "上年度采购额",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "buyer",
+    title: "采购员",
+    type: "InputDialog",
+    config: {
+      componentName: "User",
+      dataMapping: {
+        buyer: "userName",
+        puDept: "deptName",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "supplier",
+    title: "供应商",
+    type: "InputDialog",
+    config: {
+      componentName: "Supplier",
+      dataMapping: { supplier: "name" },
+    },
+    require: true,
+  },
+  {
+    key: "contractType",
+    title: "合同类型",
+    type: "Select",
+    require: true,
+    config: {
+      optionsName: "purchase_contract_contract_type",
+    },
+  },
+  {
+    key: "puMoneyYear",
+    title: "本年度采购额",
+    type: "Input",
+    require: true,
+  },
+  {
+    key: "puDept",
+    title: "采购部门",
+    type: "InputDialog",
+    config: { componentName: "Department" },
+    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,
+    config: { type: "date" },
+  },
+  {
+    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,
+    config: { type: "date" },
+  },
+  {
+    key: "invoiceTax",
+    title: "发票税率",
+    type: "InputDialog",
+    config: {
+      componentName: "Tax",
+      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,
+    config: { type: "date" },
+  },
+  {
+    key: "deliveryType",
+    title: "交货方式",
+    type: "Select",
+    config: {
+      optionsName: "purchase_contract_delivery_type",
+    },
+  },
+  {
+    key: "source",
+    title: "合同来源",
+    type: "Input",
+    value: "自制",
+    disabled: true,
+  },
+  {
+    key: "contractPartyc",
+    title: "合同丙方",
+    type: "InputDialog",
+    config: {
+      componentName: "Supplier",
+      dataMapping: {
+        contractPartyc: "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,
+    config: { type: "date" },
+  },
+  {
+    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: "paymentAgreement",
+    title: "付款协议",
+    type: "InputDialog",
+    config: {
+      componentName: "PaymentPlan",
+      dataMapping: {
+        buyer: "userName",
+        puDept: "deptName",
+      },
+    },
+    require: true,
+  },
+  {
+    key: "taxPrice",
+    title: "价税合计",
+    type: "InputNumber",
+    config: { controlsPosition: "right" },
+  },
+  {
+    key: "currency",
+    title: "币种",
+    type: "InputDialog",
+    config: {
+      componentName: "Currency",
+      dataMapping: {
+        currency: "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 initColumns = () => columns;
+
+const tabColumns = [
+  {
+    title: "物料基本信息",
+    key: "first",
+    tableColumns: [
+      { title: "序号", key: "" },
+      { title: "赠品", key: "" },
+      { title: "物料编码", key: "" },
+      { title: "物料名称", key: "" },
+      { title: "规格", key: "" },
+      { title: "生产厂家", key: "" },
+      { title: "收货客户", key: "" },
+      { title: "品牌", key: "" },
+      { title: "采购数量", key: "" },
+      { title: "采购单位", key: "" },
+      { title: "计价数量", key: "" },
+      { title: "税率%", key: "" },
+      { title: "含税单价", key: "" },
+      { title: "含税金额合计", key: "", width: 150 },
+      { title: "价格有效期(起)", key: "", width: 150 },
+      { title: "计划到货日期", key: "", width: 150 },
+      { title: "来源类型", key: "" },
+      { title: "来源单号", key: "" },
+      { title: "需求单号", key: "" },
+      { title: "备注", key: "" },
+    ],
+  },
+  {
+    title: "合同条款",
+    key: "second",
+    tableColumns: [
+      { title: "序号", key: "" },
+      { title: "条款编码", key: "" },
+      { title: "条款名称", key: "" },
+      { title: "条款内容", key: "" },
+      { title: "变量序号", key: "" },
+      { title: "变量内容", key: "" },
+      { title: "备注", key: "" },
+    ],
+  },
+  {
+    title: "合同费用",
+    key: "third",
+    tableColumns: [
+      { title: "序号", key: "" },
+      { title: "费用编码", key: "" },
+      { title: "费用名称", key: "" },
+      { title: "费用金额", key: "" },
+      { title: "备注", key: "" },
+    ],
+  },
+  {
+    title: "付款协议信息",
+    key: "fourth",
+    tableColumns: [
+      { title: "序号", key: "" },
+      { title: "付款阶段", key: "" },
+      { title: "是否预付款", key: "" },
+      { title: "是否质保金", key: "" },
+      { title: "结算方式", key: "" },
+      { title: "付款起点", key: "" },
+      { title: "付款金额", key: "" },
+      { title: "付款比例%", key: "" },
+      { title: "账期天数", key: "" },
+      { title: "备注", key: "" },
+    ],
+  },
+  {
+    title: "合同执行组织范围",
+    key: "fifth",
+    tableColumns: [
+      { title: "序号", key: "" },
+      { title: "组织名称", key: "" },
+      { title: "组织编码", key: "" },
+    ],
+  },
+];
+export const initTabColumns = () => tabColumns;

+ 2 - 2
src/views/purchase/purchase-contract/index.vue

@@ -1,5 +1,5 @@
 <script>
-import { taskList } from "@/api/business/purchase/purchase-contract";
+import { list } from "@/api/business/purchase/purchase-contract";
 import AddPurchaseContractDrawer from "./add-purchase-contract.vue";
 import SeePurchaseContractDrawer from "./see-purchase-contract.vue";
 // import DirectSourcingTable from "./direct-sourcing.vue";
@@ -124,7 +124,7 @@ export default {
     async fetchTaskList() {
       this.loading = true;
       try {
-        const { code, msg, rows, total } = await taskList({
+        const { code, msg, rows, total } = await list({
           ...this.page,
           ...this.searchParams,
         });

+ 212 - 220
src/views/purchase/purchase-task/add-purchase-task.vue

@@ -1,141 +1,25 @@
 <script>
+import { add } from "@/api/business/purchase/purchase-contract";
+import { arr2obj } from "@/utils/data-transform";
+import {
+  initDicts,
+  initRules,
+  initParams,
+  initComponents,
+} from "@/utils/init-something";
+import { initColumns } from "./config/add";
+
 export default {
   name: "AddPurchaseTaskDrawer",
+  // components: initComponents(initColumns()),
+  dicts: initDicts(initColumns()),
   data() {
-    const arr2Obj = function (data, keyName, valueName) {
-      return Object.fromEntries(
-        data.map((item) => [item[keyName], item[valueName]])
-      );
-    };
-    const pickerOptions = {
-      disabledDate(time) {
-        return time.getTime() > Date.now();
-      },
-      shortcuts: [
-        {
-          text: "今天",
-          onClick(picker) {
-            picker.$emit("pick", new Date());
-          },
-        },
-        {
-          text: "昨天",
-          onClick(picker) {
-            const date = new Date();
-            date.setTime(date.getTime() - 3600 * 1000 * 24);
-            picker.$emit("pick", date);
-          },
-        },
-        {
-          text: "一周前",
-          onClick(picker) {
-            const date = new Date();
-            date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
-            picker.$emit("pick", date);
-          },
-        },
-      ],
-    };
-    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", pickerOptions: pickerOptions },
-      },
-      { 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,
       columns: initColumns(),
-      params: initParams(),
-      options: [
-        {
-          value: "选项1",
-          label: "黄金糕",
-        },
-        {
-          value: "选项2",
-          label: "双皮奶",
-        },
-        {
-          value: "选项3",
-          label: "蚵仔煎",
-        },
-        {
-          value: "选项4",
-          label: "龙须面",
-        },
-        {
-          value: "选项5",
-          label: "北京烤鸭",
-        },
-      ],
+      rules: initRules(initColumns()),
+      params: initParams(initColumns()),
+      currentComponent: { name: "", title: "", value: "", row: {} },
     };
   },
   computed: {},
@@ -144,6 +28,40 @@ export default {
     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]];
+      }
+    },
   },
   created() {
     console.log(this.params);
@@ -154,104 +72,178 @@ export default {
 </script>
 <template>
   <el-drawer
-    title="我是标题"
     direction="btt"
     size="100%"
     :with-header="false"
     :visible.sync="visible"
-    :before-close="handleClose"
+    @open="beforeOpen"
   >
-    <el-form
-      size="mini"
-      label-position="right"
-      label-width="125px"
-      :model="params"
+    <el-card
+      :body-style="{
+        padding: '20px',
+        display: 'flex',
+        'flex-wrap': 'wrap',
+      }"
+      style="margin: 10px"
     >
-      <el-card
-        :body-style="{
-          padding: '20px',
-          display: 'flex',
-          'flex-wrap': 'wrap',
-        }"
-        style="margin: 10px"
-      >
-        <el-form-item
-          v-for="(column, index) in columns"
-          :key="index"
-          :prop="column.key"
-          :label="column.title"
-          :required="column.required"
-          style="width: 33%"
-        >
-          <el-input
-            v-if="column.type === 'Input'"
-            v-model="params[column.key]"
-            :placeholder="column.placeholder"
-            style="width: 90%"
-          ></el-input>
-          <el-input-number
-            v-if="column.type === 'InputNumber'"
-            v-model="params[column.key]"
-            controls-position="right"
-            :placeholder="column.placeholder"
-            style="width: 90%"
-          ></el-input-number>
-          <el-select
-            v-if="column.type === 'TagSelect'"
-            v-model="params[column.key]"
-            multiple
-            clearable
-            collapse-tags
-            :placeholder="column.placeholder"
-            style="width: 90%"
-          >
-            <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"
-            :picker-options="column.pickerOptions"
-            style="width: 90%"
-          >
-          </el-date-picker>
-        </el-form-item>
-      </el-card>
-      <el-card
-        :body-style="{
-          'text-align': 'right',
-          padding: '10px 20px',
-        }"
+      <div
+        slot="header"
         style="
-          position: fixed;
-          left: 0;
-          bottom: 0;
-          margin: 10px;
-          width: calc(100% - 20px);
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
         "
       >
-        <el-button size="mini" @click="setVisible(false)">取消</el-button>
-        <el-button size="mini" type="info" @click="setVisible(false)"
-          >保存并新增</el-button
+        <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-button size="mini" type="danger" @click="setVisible(false)"
-          >保存</el-button
-        >
-      </el-card>
-    </el-form>
+          <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>

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

@@ -0,0 +1,105 @@
+const pickerOptions = {
+  disabledDate(time) {
+    return time.getTime() > Date.now();
+  },
+  shortcuts: [
+    {
+      text: "今天",
+      onClick(picker) {
+        picker.$emit("pick", new Date());
+      },
+    },
+    {
+      text: "昨天",
+      onClick(picker) {
+        const date = new Date();
+        date.setTime(date.getTime() - 3600 * 1000 * 24);
+        picker.$emit("pick", date);
+      },
+    },
+    {
+      text: "一周前",
+      onClick(picker) {
+        const date = new Date();
+        date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
+        picker.$emit("pick", date);
+      },
+    },
+  ],
+};
+
+const columns = [
+  {
+    title: "采购组织",
+    key: "puOrg",
+    type: "InputDialog",
+    value: [],
+    required: true,
+  },
+  { title: "需求来源", key: "source", type: "Input", value: "采购创建" },
+  { title: "采购员", key: "buyer", value: [], type: "InputDialog" },
+  { title: "交易类型", key: "billYpe", value: [], type: "InputDialog" },
+  { title: "物料编码", key: "material", type: "Input", required: true },
+  {
+    title: "物料名称",
+    key: "materialName",
+    type: "InputDialog",
+    value: [],
+    required: true,
+  },
+  {
+    title: "物料/物料描述",
+    key: "materialDesc",
+    type: "InputDialog",
+    value: [],
+    required: true,
+  },
+  { title: "生产厂家", key: "manufacturer", type: "Input" },
+  { title: "收货客户", key: "customer", type: "InputDialog", value: [] },
+  {
+    title: "采购单位",
+    key: "puUnit",
+    type: "InputDialog",
+    value: [],
+    required: true,
+  },
+  {
+    title: "采购数量",
+    key: "puQty",
+    type: "InputNumber",
+    required: true,
+  },
+  {
+    title: "需求时间",
+    key: "demandDate",
+    type: "DatePicker",
+    config: { type: "date", pickerOptions: pickerOptions },
+  },
+  { title: "项目名称", key: "projectName", type: "InputDialog", value: [] },
+  { title: "需求人", key: "demandPersonal", type: "InputDialog", value: [] },
+  {
+    title: "需求组织",
+    key: "demandOrg",
+    type: "InputDialog",
+    value: [],
+    require: true,
+  },
+  { title: "需求部门", key: "demandDept", type: "InputDialog", value: [] },
+  { title: "建议供应商", key: "supplier", type: "InputDialog", value: [] },
+  { title: "收货人", key: "a", type: "InputDialog", value: [] },
+  { title: "收货组织", key: "b", type: "InputDialog", value: [] },
+  { title: "收货人联系方式", key: "c", type: "Input" },
+  { title: "收货地址", key: "d", type: "Input" },
+  { title: "收货仓库", key: "e", type: "InputDialog", value: [] },
+  {
+    title: "指定供应商",
+    key: "assignSupplier",
+    type: "InputDialog",
+    value: [],
+  },
+  { title: "单位", key: "unit", type: "InputDialog", value: [] },
+  { title: "收货地址", key: "f", type: "InputDialog", value: [] },
+];
+
+export const initColumns = () => columns;
+

+ 81 - 20
src/views/purchase/purchase-task/index.vue

@@ -401,12 +401,12 @@ export default {
         title: this.isSimpleSearch ? "Simple Search" : "All Search",
       });
     },
-    handleSizeChange() { },
-    handleCurrentChange() { },
+    handleSizeChange() {},
+    handleCurrentChange() {},
     handleOpenAddDrawer() {
       const { setVisible } = this.$refs.addDrawerFef;
-      setVisible(true);
       setTimeout(() => {
+        setVisible(true);
         this.$notify.info("Open Add Drawer");
       }, 250);
     },
@@ -422,16 +422,37 @@ export default {
 </script>
 
 <template>
-  <el-card v-loading="loading" style="width: calc(100% - 24px); height: 100%; margin: 10px" :body-style="{ padding: 0 }">
+  <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-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-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-input
+                  v-model="searchParams[column.key]"
+                  :placeholder="column.placeholder"
+                ></el-input>
               </el-form-item>
             </el-col>
           </el-row>
@@ -441,7 +462,11 @@ export default {
             <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-col
+              v-show="!isSimpleSearch"
+              :span="24"
+              style="margin: 10px 0 0"
+            >
               <el-button size="mini">重置</el-button>
             </el-col>
           </el-row>
@@ -449,13 +474,21 @@ export default {
       </el-row>
     </el-form>
     <el-divider>
-      <i :class="isSimpleSearch ? 'el-icon-arrow-down' : 'el-icon-arrow-up'" style="cursor: pointer"
-        @click="handleSearchChange"></i>
+      <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
+          size="mini"
+          type="danger"
+          style="margin: 0 10px 0 0"
+          @click="handleOpenAddDrawer"
+        >
           新增
         </el-button>
         <el-dropdown placement="bottom-start">
@@ -471,7 +504,10 @@ export default {
         </el-dropdown>
 
         <el-dropdown placement="bottom-start">
-          <el-button size="mini" style="border-right: 0; border-radius: 3px 0 0 3px">
+          <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>
@@ -492,7 +528,10 @@ export default {
         <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
+          size="mini"
+          style="margin: 0; border-right: 0; border-radius: 0"
+        >
           退回请购
         </el-button>
         <el-dropdown placement="bottom-start">
@@ -504,7 +543,11 @@ export default {
             <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
+          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>
@@ -523,14 +566,32 @@ export default {
         </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
+      @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
+      @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>

+ 3 - 3
vue.config.js

@@ -37,15 +37,15 @@ module.exports = {
       // detail: https://cli.vuejs.org/config/#devserver-proxy
       [process.env.VUE_APP_BASE_API]: {
         // target: `http://172.16.100.107:8080/drp-admin`, //测试
-        // target: `http://test-sy.derom.com/drp-admin`, //测试
-        target: `http://release-sy.derom.com/drp-admin`, //预发
+        target: `http://test-sy.derom.com/drp-admin`, //测试
+        // target: `http://release-sy.derom.com/drp-admin`, //预发
         // target: `http://sy.derom.com/drp-admin`, //生产
         // target: `http://172.16.63.202:8000/drp-admin`, // D本地
         // target: `http://172.16.62.241:8000/drp-admin`, //笑寒本地
         // target: `http://172.16.13.152:8000/drp-admin`, //豪哥本地
         // target: `http://172.16.13.47:8000/drp-admin`, //石杨本地
         // target: `http://172.16.13.113:8000/drp-admin`, //DWT本地
-        // target: `http://172.16.13.77:8000/drp-admin`, //DWT本地
+        // target: `http://172.16.13.77:8000/drp-admin`, //TQ本地
         changeOrigin: true,
         pathRewrite: {
           ["^" + process.env.VUE_APP_BASE_API]: "",