xiaodai2017 2 years ago
parent
commit
1c456ae20a

+ 15 - 0
src/api/components/remoteSelect.ts

@@ -20,3 +20,18 @@ export async function httpCategorys(data: object): Promise<DataType<any>> {
     data
   });
 }
+
+// 全部卡类型
+export async function httpCardAll(data: object = {}): Promise<DataType<any>> {
+  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/cardAll`, {
+    data
+  });
+}
+// 全部企业
+export async function httpCompanyAll(
+  data: object = {}
+): Promise<DataType<any>> {
+  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/companyAll`, {
+    data
+  });
+}

+ 10 - 4
src/api/mobile/park.ts → src/api/mobile/user.ts

@@ -5,25 +5,31 @@ const { VITE_PROXY_DOMAIN_REAL } = loadEnv();
 
 //分页查询
 export async function httpList(data: object): Promise<DataType<any[]>> {
-  return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/accountlist`, {
+  return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/AccoountList`, {
     data
   });
 }
 //详情
 export async function httpDetail(data: object): Promise<DataType<any[]>> {
-  return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/accountinfo`, {
+  return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/AccoountRead`, {
     data
   });
 }
 //更新
 export async function httpUpdate(data: object): Promise<DataType<any[]>> {
-  return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/accountsave`, {
+  return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/AccoountEdit`, {
     data
   });
 }
 //添加
 export async function httpAdd(data: object): Promise<DataType<any[]>> {
-  return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/accountadd`, {
+  return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/AccountAdd`, {
+    data
+  });
+}
+// 删除
+export async function httpDelete(data: object = {}): Promise<DataType<any>> {
+  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/AccoountDelete`, {
     data
   });
 }

+ 11 - 6
src/api/operate/batchCreatUser.ts

@@ -5,13 +5,18 @@ const { VITE_PROXY_DOMAIN_REAL } = loadEnv();
 
 // 添加
 export async function httpAdd(data: object = {}): Promise<DataType<any>> {
-  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/companyAdd`, {
-    data
-  });
+  return http.request(
+    "post",
+    `${VITE_PROXY_DOMAIN_REAL}/admin/AccoountBatchAdd`,
+    {
+      data
+    }
+  );
 }
-// 列表
-export async function httpList(data: object = {}): Promise<DataType<any>> {
-  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/companylist`, {
+
+//分页查询
+export async function httpList(data: object): Promise<DataType<any[]>> {
+  return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/AccoountList`, {
     data
   });
 }

+ 9 - 7
src/components/BasicForm/src/_createDafaultData.ts

@@ -1,21 +1,19 @@
 import { FormItem } from "./types";
 
 export function createDefaultData(formItems: FormItem[]) {
-  // console.log(formItems);
+  console.log(formItems);
   const data: Record<string, any> = {};
   //创建默认值策略
   for (const item of formItems) {
     switch (item.type) {
       case "checkbox":
+      case "array":
       case "img_upload_list":
         data[item.field] = [];
         break;
       case "number":
         data[item.field] = 0;
         break;
-      case "array":
-        data[item.field] = [];
-        break;
       default:
         data[item.field] = "";
         break;
@@ -27,16 +25,20 @@ export function createDefaultData(formItems: FormItem[]) {
 
 export function transform(
   formItems: FormItem[],
-  data: Record<string, string>,
-  transform?: Record<string, string>
+  data: Record<string, any>,
+  transform?: Record<string, any>
 ) {
   const detail: Record<string, any> = {};
 
   for (let i = 0; i < formItems.length; i++) {
     let target = "";
-    const { field: source } = formItems[i];
+    const { field: source, type } = formItems[i];
+    console.log(data);
+    console.log(source);
+    console.log(type);
 
     target = transform && transform[source] ? transform[source] : source;
+    console.log(data[target]);
 
     detail[source] = data[target];
   }

+ 3 - 3
src/components/RemoteSelect/index.ts

@@ -1,8 +1,8 @@
 import RemoteSelect from "./src/remote-select";
-import Project from "./src/search/Project.vue";
+import Company from "./src/search/Company.vue";
 import Category from "./src/search/Category.vue";
 import Customer from "./src/search/Customer.vue";
-import Brand from "./src/search/Brand.vue";
+import Card from "./src/search/Card.vue";
 import Unit from "./src/search/Unit.vue";
-export { Customer, Brand, Unit, Category, Project };
+export { Customer, Card, Unit, Category, Company };
 export default RemoteSelect;

+ 5 - 4
src/components/RemoteSelect/src/search/Brand.vue → src/components/RemoteSelect/src/search/Card.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
 import { ref } from "vue";
 import { useVModel } from "@vueuse/core";
-import { httpList } from "/@/api/operate/setComGood";
+import { httpCardAll } from "/@/api/components/remoteSelect";
 import RemoteSelect from "../remote-select";
 
 const props = defineProps<{
@@ -28,12 +28,13 @@ defineExpose({
 <template>
   <RemoteSelect
     v-model="value"
-    :api="httpList"
+    :api="httpCardAll"
     :placeholder="placeholder"
     ref="remoteSelectRef"
-    response-label-prop="brand_name"
+    response-label-prop="title"
     response-val-prop="id"
-    request-prop="brand_name"
+    request-prop="title"
+    :isRoot="true"
     @change="val => emit('change', val)"
     @inital="id => (value = id)"
   />

+ 5 - 4
src/components/RemoteSelect/src/search/Project.vue → src/components/RemoteSelect/src/search/Company.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
 import { ref, watch } from "vue";
 import { useVModel } from "@vueuse/core";
-import { httpList } from "/@/api/operate/setComGood";
+import { httpCompanyAll } from "/@/api/components/remoteSelect";
 import RemoteSelect from "../remote-select";
 
 const emit = defineEmits(["update:modelValue", "change"]);
@@ -36,13 +36,14 @@ watch(
 <template>
   <RemoteSelect
     v-model="value"
-    :api="httpList"
+    :api="httpCompanyAll"
     :placeholder="placeholder"
     :disabled="disabled"
     ref="remoteSelectRef"
-    response-label-prop="project_name"
-    request-prop="project_name"
+    response-label-prop="title"
     response-val-prop="id"
+    request-prop="title"
+    :isRoot="true"
     @item-change="handleChange"
   />
 </template>

+ 3 - 3
src/components/UploadList/src/image.vue

@@ -91,10 +91,10 @@ const httpupLoad = (file, i): Promise<string> => {
         handler: () => {
           const url = baseUrl + data[0].url;
           resolve(url);
-        },
-        errorHandler: () => {
-          resolve("break");
         }
+        // errorHandler: () => {
+        //   resolve("break");
+        // }
       });
     });
   });

+ 4 - 6
src/views/mobile/user/config/content.config.ts

@@ -1,10 +1,7 @@
-import { isString } from "@pureadmin/utils";
-import { h } from "vue";
 import { ContentConfig } from "/@/components/PageContent";
-import { httpList } from "/@/api/mobile/user";
+import { httpDelete, httpList, httpUpdate } from "/@/api/mobile/user";
 import { renderStatus, timeInterval } from "/@/utils/column-helper";
 import { ACCOUNT_STATUS_OPTIONS } from "/@/config/status";
-import { ElTag } from "element-plus";
 
 const columns = [
   {
@@ -58,11 +55,12 @@ const columns = [
   }
 ];
 const contentConfig: ContentConfig = {
-  title: "视频管理",
+  title: "用户管理",
   columns,
   apis: {
+    httpDelete,
     httpList,
-    httpUpdate: true
+    httpUpdate
   },
   notPreview: false
 };

+ 42 - 27
src/views/mobile/user/index.vue

@@ -1,47 +1,62 @@
 <script setup lang="ts">
-import { usePageSearch } from "/@/components/PageSearch";
+import { ref } from "vue";
+import { PageSearch, usePageSearch } from "/@/components/PageSearch";
 import searchConfig from "./config/search.config";
 import contentConfig from "./config/content.config";
 import PageAuth from "/@/components/PageAuth";
 import { PageModal, usePageModal } from "/@/components/PageModal";
 import modalConfig from "./config/modal.config";
-import { useRouter } from "vue-router";
-import PageContainer, {
-  type Events,
-  type Hooks
-} from "/@/components/PageContainer";
+import { PageContent } from "/@/components/PageContent";
+import type { PageContentInstance } from "/@/components/PageContent";
+import { useResponseHandle } from "/@/hooks/useAsync";
+import { httpDetail } from "/@/api/mobile/user";
+const pageContentRef = ref<PageContentInstance | null>(null);
 
-const pageName = "user";
-const basePath = "/sellOut/projectDetail";
-// , handleResetClick, handleSearchClick
-const { pageContentRef } = usePageSearch();
-const { push } = useRouter();
-const hooks: Hooks = {
-  pageSearchHook: () => usePageSearch(undefined, undefined, searchConfig)
-};
 const {
   pageModalRef,
-  // handleUpdateData,
-  // handleCreateData,
+  handleUpdateData,
+  handleCreateData,
   handlePreviewData,
   handleConfrim,
   defaultInfo
-} = usePageModal({ pageContentRef });
-const events: Events = {
-  content: {
-    preview: row => handlePreviewData(row),
-    create: () => push(basePath)
-  }
-};
+} = usePageModal({
+  pageContentRef
+});
+const { handleResetClick, handleSearchClick } = usePageSearch();
+const responseHandle = useResponseHandle();
+async function handleDetailData(row, type) {
+  const { id } = row;
+  //
+  const { code, data, message } = await httpDetail({ id: id });
+
+  responseHandle({
+    code,
+    message,
+    handler: () => {
+      if (type === "preview") {
+        handlePreviewData(data);
+      }
+      if (type === "update") {
+        handleUpdateData(data);
+      }
+    }
+  });
+}
 </script>
 
 <template>
   <!-- <PageAuth :pageName="pageName"> -->
-  <PageContainer
-    :hooks="hooks"
-    :events="events"
-    :search-config="searchConfig"
+  <PageSearch
+    :form-config="searchConfig"
+    @search-btn-click="handleSearchClick"
+    @reset-btn-click="handleResetClick"
+  />
+  <PageContent
+    ref="pageContentRef"
     :content-config="contentConfig"
+    @create-btn-click="handleCreateData"
+    @preview-btn-click="row => handleDetailData(row, 'preview')"
+    @update-btn-click="row => handleDetailData(row, 'update')"
   />
   <PageModal
     ref="pageModalRef"

+ 483 - 0
src/views/operate/batchCreatUser/config/_details.ts

@@ -0,0 +1,483 @@
+/* eslint-disable prettier/prettier */
+import { h } from "vue";
+import { ElImage, ElTag } from "element-plus";
+import { DescriptionColumns } from "/@/components/BasicDescriptions";
+import { FormConfig } from "/@/components/PageSearch";
+import { createTooltip } from "/@/utils/tooltip";
+import { GOOD_OPTIONS } from "/@/config/status";
+// import { payWayOptions, sendWayOptions, supplyAreaOptions } from "./_options";
+
+export const projectFormConfig: FormConfig = {
+  labelWidth: "85px",
+  formItems: [
+    {
+      label: "公司",
+      field: "company_id",
+      placeholder: "公司",
+      span: 12,
+      slot: "company_id"
+    },
+    {
+      label: "卡类型",
+      field: "card_id",
+      placeholder: "卡类型",
+      span: 12,
+      slot: "card_id"
+    },
+    {
+      label: "前缀",
+      field: "headname",
+      slot: "headname",
+      placeholder: "前缀",
+      span: 6
+    },
+    {
+      label: "字母段",
+      field: "username_prefix",
+      type: "input",
+      placeholder: "字母段",
+      span: 6
+    },
+    {
+      label: "年份段",
+      field: "username_year",
+      type: "number",
+      placeholder: "年份段",
+      span: 6
+    },
+
+    {
+      label: "数字段",
+      field: "suffix",
+      slot: "suffix",
+      placeholder: "数字段",
+      span: 6
+    },
+
+    {
+      label: "有效时间",
+      field: "time",
+      type: "date_picker",
+      otherOptions: {
+        type: "daterange",
+        startProp: "start",
+        endProp: "end",
+        startPlaceholder: "开始时间",
+        endPlaceholder: "结束时间",
+        format: "YYYY-MM-DD"
+      },
+      placeholder: "有效时间",
+      span: 12
+    }
+  ]
+};
+
+//平台商品详情字段
+export const platformGoodColumns: DescriptionColumns = [
+  {
+    field: "good_name",
+    label: "商品名称",
+    span: 24,
+    render: (goodname, { skuCode, speclist }) => {
+      const goodName = speclist
+        ? speclist
+            .map(({ spec_name, spec_value }) => `${spec_name}[${spec_value}]`)
+            .join("_")
+        : "";
+
+      return createTooltip(
+        goodname + "_" + goodName,
+        "商品编号: " + skuCode,
+        360
+      );
+    }
+  },
+  {
+    field: "good_img",
+    label: "商品主图",
+    span: 12,
+    render: good_img => {
+      const previewSrcList = good_img ? good_img.split(",") : [];
+      return previewSrcList.map(src =>
+        h(ElImage, {
+          previewSrcList: [src],
+          src,
+          previewTeleported: true,
+          style: {
+            height: "20px",
+            width: "20px"
+          }
+        })
+      );
+    }
+  },
+  {
+    field: "good_info_img",
+    label: "商品详情图",
+    span: 12,
+    render: good_info_img => {
+      return h(ElImage, {
+        previewSrcList: [good_info_img],
+        src: good_info_img,
+        previewTeleported: true,
+        style: {
+          height: "20px",
+          width: "20px"
+        }
+      });
+    }
+  },
+  {
+    field: "company",
+    label: "业务企业名称",
+    span: 8,
+    render: (company, { companyNo }) =>
+      createTooltip(company, "业务企业编号: " + companyNo, 360)
+  },
+  {
+    field: "platform_name",
+    label: "所属平台",
+    span: 8
+  },
+  {
+    field: "brand_name",
+    label: "品牌",
+    span: 8
+  },
+  {
+    field: "cat_info",
+    label: "分类",
+    span: 8,
+    render(cat_info) {
+      return cat_info ? cat_info.map(({ name }) => name).join("_") : "";
+    }
+  },
+  {
+    field: "unit",
+    span: 8,
+    label: "单位"
+  },
+  {
+    field: "is_stock",
+    label: "是否库存品",
+    span: 6,
+    render(is_stock) {
+      return h(ElTag, null, {
+        default: () => (is_stock !== "0" ? "库存品" : "非库存品")
+      });
+    }
+  },
+  // {
+  //   field: "supply_area",
+  //   label: "供货区域",
+  //   span: 6,
+  //   render(supply_area) {
+  //     return h(ElTag, null, {
+  //       default: () =>
+  //         supplyAreaOptions.find(({ id }) => supply_area === id)?.label || "--"
+  //     });
+  //   }
+  // },
+  {
+    field: "good_type",
+    label: "是否定制",
+    span: 8,
+    render(good_type) {
+      return h(ElTag, null, {
+        default: () => (good_type !== "0" ? "是" : "否")
+      });
+    }
+  },
+  {
+    field: "tax",
+    label: "税点",
+    append: "%",
+    span: 4
+  },
+  {
+    field: "delivery_day",
+    label: "物流时间",
+    append: "天",
+    span: 4
+  },
+  {
+    field: "lead_time",
+    label: "供货周期",
+    append: "天",
+    span: 4
+  },
+  {
+    field: "sample_day",
+    label: "调样周期",
+    append: "天",
+    span: 4
+  },
+  {
+    field: "exclusive",
+    label: "专属类型",
+    span: 6,
+    render(exclusive) {
+      return exclusive ? exclusive.map(({ name }) => name).join("/") : "";
+    }
+  },
+  {
+    field: "weight",
+    label: "商品总克重",
+    append: "g",
+    span: 6
+  },
+  {
+    field: "noble",
+    label: "贵金属信息",
+    render(
+      _,
+      {
+        noble_weight,
+        noble_metal,
+        noble_name,
+        gold_price,
+        is_gold_price,
+        is_diff,
+        config,
+        other_config
+      }
+    ) {
+      if (!noble_metal) {
+        return "";
+      }
+
+      const weight = noble_weight ? `${noble_weight}g-${noble_name}` : "";
+
+      const price = gold_price ? gold_price : "0";
+
+      const isGoldPrice = is_gold_price === "0" ? "不" : "";
+
+      const diff = is_diff === "1" ? "有" : "无";
+
+      return `${weight}${price}元/g-${isGoldPrice}启用实时金价-${diff}工差-${config}-${other_config}`;
+    }
+  },
+  {
+    field: "delivery_place_cn",
+    label: "发货地",
+    span: 8
+  },
+  {
+    field: "customized",
+    label: "工期",
+    span: 8
+  },
+  {
+    field: "cgder",
+    label: "供应商负责人",
+    span: 4
+  },
+  {
+    field: "good_creater",
+    label: "商品创建人",
+    span: 4
+  },
+  {
+    field: "after_sales",
+    label: "售后说明",
+    span: 24
+  },
+  {
+    field: "good_remark",
+    label: "商品备注",
+    span: 24
+  },
+
+  {
+    field: "craft_desc",
+    label: "工艺说明",
+    span: 24
+  }
+];
+
+//采反商品详情字段
+export const commodityFeedbackColumns: DescriptionColumns = [
+  {
+    field: "good_name",
+    label: "商品名称",
+    span: 24,
+    render: (goodname, { spuCode, speclist }) => {
+      const goodName = speclist
+        ? speclist
+            .map(({ spec_name, spec_value }) => `${spec_name}[${spec_value}]`)
+            .join("_")
+        : "";
+
+      return createTooltip(
+        goodname + "_" + goodName,
+        "上线商品编号: " + spuCode,
+        360
+      );
+    }
+  },
+
+  {
+    field: "cat_info",
+    label: "分类",
+    span: 8,
+    render(cat_info) {
+      return cat_info ? cat_info.map(({ name }) => name).join("_") : "";
+    }
+  },
+
+  {
+    field: "brand_name",
+    label: "品牌",
+    span: 8
+  },
+
+  // {
+  //   field: "send_way",
+  //   label: "发货方式",
+  //   span: 8,
+  //   render(send_way) {
+  //     return h(ElTag, null, {
+  //       default: () =>
+  //         sendWayOptions.find(({ id }) => send_way === id)?.label || "--"
+  //     });
+  //   }
+  // },
+  {
+    field: "unit",
+    label: "单位",
+    span: 4
+  },
+  {
+    field: "tax",
+    label: "税点",
+    append: "%",
+    span: 4
+  },
+  // {
+  //   field: "pay_way",
+  //   label: "付款方式",
+  //   span: 4,
+  //   render(pay_way) {
+  //     return h(ElTag, null, {
+  //       default: () =>
+  //         payWayOptions.find(({ id }) => pay_way === id)?.label || "--"
+  //     });
+  //   }
+  // },
+
+  {
+    field: "weight",
+    label: "商品总克重",
+    append: "g",
+    span: 6
+  },
+
+  {
+    field: "addtime",
+    label: "反馈时间",
+    span: 6
+  },
+  {
+    field: "expire_day",
+    label: "竞价有效期",
+    append: "天",
+    span: 4
+  },
+
+  {
+    field: "delivery_day",
+    label: "物流时间",
+    append: "天",
+    span: 4
+  },
+  {
+    field: "work_day",
+    label: "生产工期",
+    append: "天",
+    span: 4
+  },
+  {
+    field: "cgder",
+    label: "供应商负责人",
+    span: 4
+  },
+  {
+    field: "creater",
+    label: "商品创建人",
+    span: 4
+  },
+  {
+    field: "supply_area",
+    label: "供货区域",
+    span: 4,
+    render(supply_area) {
+      return h(ElTag, null, {
+        default: () =>
+          supplyAreaOptions.find(({ id }) => supply_area === id)?.label || "--"
+      });
+    }
+  },
+
+  {
+    field: "good_img",
+    label: "商品图片",
+    span: 24,
+    render: good_img => {
+      const previewSrcList = good_img ? good_img.split(",") : [];
+      return previewSrcList.map(src =>
+        h(ElImage, {
+          previewSrcList: [src],
+          src,
+          previewTeleported: true,
+          style: {
+            height: "20px",
+            width: "20px"
+          }
+        })
+      );
+    }
+  },
+  {
+    field: "noble",
+    label: "贵金属信息",
+    span: 24,
+    render(
+      _,
+      {
+        noble_weight,
+        noble_metal,
+        noble_name,
+        gold_price,
+        is_gold_price,
+        is_diff,
+        config,
+        other_config
+      }
+    ) {
+      if (!noble_metal) {
+        return "--";
+      }
+
+      const weight = noble_weight ? `${noble_weight}g-${noble_name}` : "";
+
+      const price = gold_price ? gold_price : "0";
+
+      const isGoldPrice = is_gold_price === "0" ? "不" : "";
+
+      const diff = is_diff === "1" ? "有" : "无";
+
+      return `${weight}${price}元/g-${isGoldPrice}启用实时金价-${diff}工差-${config}-${other_config}`;
+    }
+  },
+
+  {
+    field: "cost_desc",
+    label: "工艺说明",
+    span: 24
+  },
+  {
+    field: "remark",
+    label: "采返备注",
+    span: 24
+  }
+];

+ 61 - 0
src/views/operate/batchCreatUser/config/_rules.ts

@@ -0,0 +1,61 @@
+import { FormRules } from "element-plus";
+import { isArray, validUpperCase } from "/@/utils/validate";
+export const ladderFormRules: FormRules = {
+  key: {
+    trigger: "change",
+    required: true,
+    message: "请选择商品类型"
+  },
+  value: {
+    trigger: "change",
+    required: true,
+    message: "请选择单位"
+  }
+};
+
+export const projectFormRules: FormRules = {
+  company_id: {
+    trigger: "change",
+    required: true,
+    message: "请选择公司"
+  },
+  card_id: {
+    trigger: "change",
+    required: true,
+    message: "请选择卡类型"
+  },
+  headname: {
+    trigger: "change",
+    required: false,
+    message: "请选择账号固定前缀"
+  },
+  username_prefix: {
+    trigger: "change",
+    required: true,
+    validator(_, value) {
+      if (value === "") return new Error("请输入字母段");
+      if (!validUpperCase(value)) return new Error("字母段必须为大写字母!");
+      return true;
+    }
+  },
+  username_year: {
+    trigger: "change",
+    required: true,
+    validator(_, value) {
+      if (typeof value != "number") return new Error("请输入年份段");
+      const num = Number(value + "");
+      if (num < 0) return new Error("年份段不能低于0");
+      return true;
+    }
+  },
+  time: {
+    trigger: "change",
+    required: true,
+    validator(_, value) {
+      if (!isArray(value)) return new Error("请选择有效时间");
+      const length = value.length;
+      if (length === 0) return new Error("请选择有效时间");
+      return true;
+    }
+  }
+};

+ 0 - 46
src/views/operate/batchCreatUser/config/modal.config.ts

@@ -1,46 +0,0 @@
-import { ModalConfig } from "/@/components/PageModal/src/types";
-import { httpList as httpCompanylist } from "/@/api/parameter/company";
-import { httpList as httpCardlist } from "/@/api/parameter/card";
-const modalConfig: ModalConfig = {
-  title: "企业商品",
-  colLayout: { span: 24 },
-  itemStyle: {},
-  contact: "batchCreatUser",
-  labelWidth: "85px",
-  formItems: [
-    {
-      field: "name",
-      type: "remote-select",
-      label: "业务企业",
-      placeholder: "业务企业",
-      otherOptions: {
-        api: httpCompanylist,
-        responseLabelProp: "title",
-        responseValPro: "id",
-        requesetProp: "",
-        isRoot: false,
-        prop: "list"
-      },
-      span: 24,
-      rules: [{ required: true, trigger: "change", message: "请选择业务企业" }]
-    },
-    {
-      field: "name2",
-      type: "remote-select",
-      label: "卡类型",
-      placeholder: "卡类型",
-      otherOptions: {
-        api: httpCardlist,
-        responseLabelProp: "title",
-        responseValPro: "id",
-        requesetProp: "",
-        isRoot: false,
-        prop: "list"
-      },
-      span: 24,
-      rules: [{ required: true, trigger: "change", message: "请选择卡类型" }]
-    }
-  ]
-};
-
-export default modalConfig;

+ 81 - 0
src/views/operate/batchCreatUser/cpns/ladder-modal.vue

@@ -0,0 +1,81 @@
+<script setup lang="ts">
+import { ref, unref, computed } from "vue";
+import { ElForm } from "element-plus";
+import { ladderFormRules } from "../config/_rules";
+
+const emit = defineEmits(["push", "update"]);
+
+const defaultData = {
+  key: "",
+  value: ""
+};
+
+const isUpdate = ref(false);
+const visible = ref(false);
+const formRef = ref<InstanceType<typeof ElForm> | null>(null);
+const updateIndex = ref("0");
+
+const formData = ref<Record<string, any>>({ ...defaultData });
+
+const title = computed(() => {
+  return isUpdate.value ? "修改商品要求" : "添加商品要求";
+});
+
+function handleConfirm() {
+  formRef.value.validate(isValid => {
+    if (!isValid) return;
+
+    emit(
+      isUpdate.value ? "update" : "push",
+      unref(formData),
+      unref(updateIndex)
+    );
+
+    visible.value = false;
+  });
+}
+
+defineExpose({
+  onDisplay: (data?: Record<string, any>, index = "0") => {
+    if (data) {
+      data.cat_info = [];
+      formData.value = data;
+      updateIndex.value = index;
+    }
+
+    visible.value = true;
+    isUpdate.value = !!data;
+  }
+});
+</script>
+
+<template>
+  <ElDialog
+    center
+    :title="title"
+    v-model="visible"
+    @close="() => (formData = { ...defaultData })"
+  >
+    <ElForm
+      ref="formRef"
+      :model="formData"
+      width="500px"
+      :rules="ladderFormRules"
+      label-width="100px"
+    >
+      <ElFormItem label="类型" prop="key">
+        <ElInput placeholder="类型" v-model="formData.key" />
+      </ElFormItem>
+
+      <ElFormItem label="类型值" prop="value">
+        <ElInput placeholder="类型值" v-model="formData.value" />
+      </ElFormItem>
+      <ElFormItem>
+        <div class="w-full flex justify-end">
+          <ElButton type="primary" @click="handleConfirm">保存</ElButton>
+          <ElButton @click="() => (visible = false)">取消</ElButton>
+        </div>
+      </ElFormItem>
+    </ElForm>
+  </ElDialog>
+</template>

+ 55 - 0
src/views/operate/batchCreatUser/cpns/ladder-table.vue

@@ -0,0 +1,55 @@
+<script setup lang="ts">
+import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
+
+const emit = defineEmits(["choose", "delete", "update"]);
+
+defineProps<{
+  ladder: Record<string, any>[];
+  readonly: boolean;
+}>();
+</script>
+
+<template>
+  <ElTable size="small" border :data="ladder">
+    <ElTableColumn prop="name" label="顺序">
+      <template #="{ $index }">
+        {{ $index + 1 }}
+      </template>
+    </ElTableColumn>
+    <ElTableColumn prop="key" label="类型" />
+    <ElTableColumn prop="value" label="类型值" />
+    <ElTableColumn v-if="!readonly">
+      <template #header>
+        <div class="w-full flex justify-between">
+          <p>操作</p>
+
+          <ElTooltip content="添加阶梯" placement="top">
+            <ElButton
+              link
+              :icon="useRenderIcon('add')"
+              @click="() => emit('choose')"
+            />
+          </ElTooltip>
+        </div>
+      </template>
+
+      <template #="{ $index, row }">
+        <ElButton
+          text
+          type="primary"
+          size="small"
+          @click="() => emit('update', { data: row, index: $index })"
+          >编辑</ElButton
+        >
+
+        <ElButton
+          text
+          type="primary"
+          size="small"
+          @click="() => emit('delete', $index)"
+          >删除</ElButton
+        >
+      </template>
+    </ElTableColumn>
+  </ElTable>
+</template>

+ 107 - 0
src/views/operate/batchCreatUser/cpns/project-form.vue

@@ -0,0 +1,107 @@
+<script setup lang="ts">
+import { ref, watchEffect, unref } from "vue";
+import { ElForm, ElMessage } from "element-plus";
+import { projectFormConfig } from "../config/_details";
+import { projectFormRules } from "../config/_rules";
+import { BasicForm } from "/@/components/BasicForm";
+import LadderModal from "./ladder-modal.vue";
+import LadderTable from "./ladder-table.vue";
+import dayjs from "dayjs";
+// import SearchTerrace from "/@/components/SearchTerrace";
+import { Company, Card } from "/@/components/RemoteSelect";
+
+import { transform, createDefaultData } from "/@/components/BasicForm";
+import { useResponseHandle } from "/@/hooks/useAsync";
+
+const emit = defineEmits(["create"]);
+
+const props = defineProps<{
+  data: Record<string, string>;
+  readonly: boolean;
+  id?: string;
+}>();
+
+const loading = ref(false);
+const { formItems } = projectFormConfig;
+
+const responseHandle = useResponseHandle();
+const basicFormRef = ref<InstanceType<typeof ElForm>>(null);
+const formData = ref<Record<string, any>>(createDefaultData(formItems));
+const ladderModalRef = ref<InstanceType<typeof LadderModal>>(null);
+
+async function handlePush(_ladder) {
+  formData.value.good_param.push(unref(_ladder));
+}
+
+async function handleUpdate(_ladder, index) {
+  formData.value.good_param[index] = _ladder;
+}
+
+function handleCreate() {
+  basicFormRef.value.validate(isValid => {
+    if (!isValid) return;
+    const params = unref(formData);
+    const { time } = params;
+    params.starttime = time[0] ? dayjs(time[0]).format("YYYY-MM-DD") : "";
+    params.expiretime = time[1] ? dayjs(time[1]).format("YYYY-MM-DD") : "";
+    emit("create", params);
+  });
+}
+
+watchEffect(() => {
+  const { readonly, data } = props;
+  if (readonly && !data) {
+    return;
+  }
+  if (readonly) {
+    formData.value = transform(formItems, data, {});
+  }
+});
+</script>
+
+<template>
+  <ElScrollbar>
+    <BasicForm
+      ref="basicFormRef"
+      v-bind="projectFormConfig"
+      :form-data="formData"
+      :rules="projectFormRules"
+      :disabled="readonly"
+      label-width="120px"
+    >
+      <template #company_id>
+        <Company v-model="formData.company_id" placeholder="公司" />
+      </template>
+      <template #card_id>
+        <Card v-model="formData.card_id" placeholder="卡类型" />
+      </template>
+      <template #headname>
+        <span>CJ1745</span>
+      </template>
+      <template #suffix>
+        <span>0000~9999</span>
+      </template>
+      <template #good_param>
+        <LadderTable
+          :readonly="readonly"
+          :ladder="formData.good_param"
+          @choose="() => ladderModalRef.onDisplay()"
+          @update="({ data, index }) => ladderModalRef.onDisplay(data, index)"
+          @delete="index => formData.good_param.splice(index, 1)"
+        />
+      </template>
+
+      <template #footer>
+        <div class="w-full flex justify-end" v-if="!readonly">
+          <ElButton type="primary" @click="handleCreate">保存</ElButton>
+        </div>
+      </template>
+    </BasicForm>
+
+    <LadderModal
+      ref="ladderModalRef"
+      @update="handleUpdate"
+      @push="handlePush"
+    />
+  </ElScrollbar>
+</template>

+ 80 - 0
src/views/operate/batchCreatUser/detail.vue

@@ -0,0 +1,80 @@
+<script setup lang="ts">
+// import CommodityFeedback from "./cpns/commodity-feedback.vue";
+// import ApprovalRecord from "/@/components/ApprovalRecord";
+import PgaeDetail from "/@/components/PageDetail";
+// import SchemePlans from "./cpns/scheme-plan.vue";
+import ProjectForm from "./cpns/project-form.vue";
+import { useAsync } from "/@/hooks/useAsync";
+import { useDetail } from "/@/hooks/useDetail";
+import { useRouter } from "vue-router";
+
+import {
+  httpDetail,
+  httpAdd
+  // httpCommodityFeedback
+} from "/@/api/operate/batchCreatUser";
+import { unref } from "vue";
+
+//方案制作状态
+// const schemeStatus = ["3", "4", "5", "6"];
+
+const { push } = useRouter();
+
+const { isDetail, collapses, label, id } = useDetail({
+  baseName: "商品",
+  collapseLen: 2
+});
+
+const {
+  data: projectData,
+  run: project,
+  loading: projectLoading
+} = useAsync<Record<string, string>>({
+  initalData: {}
+});
+
+// const {
+//   data: feedbackData,
+//   run: feedback,
+//   loading: feedbackLoading
+// } = useAsync({
+//   initalData: {},
+//   isList: true
+// });
+
+const { run: create } = useAsync({
+  success: () => push("/parameter/good")
+});
+
+const handleCreate = data => create(httpAdd(data));
+
+function initalData() {
+  if (!id.value) {
+    return;
+  }
+
+  project(httpDetail({ id: id.value }));
+  console.log(projectData);
+  // feedback(httpCommodityFeedback({ projectNo: id.value }));
+}
+
+initalData();
+</script>
+
+<template>
+  <PgaeDetail>
+    <ElTabs>
+      <ElTabPane :label="label">
+        <ElCollapse v-model="collapses">
+          <ElCollapseItem :title="label" name="1" v-loading="projectLoading">
+            <ProjectForm
+              :readonly="isDetail"
+              :data="projectData"
+              @create="handleCreate"
+            />
+          </ElCollapseItem>
+        </ElCollapse>
+      </ElTabPane>
+    </ElTabs>
+  </PgaeDetail>
+</template>

+ 27 - 34
src/views/operate/batchCreatUser/index.vue

@@ -1,47 +1,40 @@
 <script setup lang="ts">
-import { ref } from "vue";
-import { PageSearch, usePageSearch } from "/@/components/PageSearch";
+import { usePageSearch } from "/@/components/PageSearch";
 import searchConfig from "./config/search.config";
 import contentConfig from "./config/content.config";
-import modalConfig from "./config/modal.config";
-import { PageModal, usePageModal } from "/@/components/PageModal";
-import { PageContent } from "/@/components/PageContent";
+import PageAuth from "/@/components/PageAuth";
+import { useRouter } from "vue-router";
+
+import PageContainer, {
+  type Events,
+  type Hooks
+} from "/@/components/PageContainer";
 
-import type { PageContentInstance } from "/@/components/PageContent";
-const pageContentRef = ref<PageContentInstance | null>(null);
 const pageName = "batchCreatUser";
-const {
-  pageModalRef,
-  handleUpdateData,
-  handleCreateData,
-  handlePreviewData,
-  handleConfrim,
-  defaultInfo
-} = usePageModal({
-  pageContentRef
-});
-const { handleResetClick, handleSearchClick } = usePageSearch();
+
+const basePath = "/operate/batchCreatUserDetail";
+
+const { push } = useRouter();
+
+const hooks: Hooks = {
+  pageSearchHook: () => usePageSearch(undefined, undefined, searchConfig)
+};
+
+const events: Events = {
+  content: {
+    preview: ({ id }) => push(`${basePath}?id=${id}`),
+    create: () => push(basePath)
+  }
+};
 </script>
 
 <template>
   <!-- <PageAuth :pageName="pageName"> -->
-  <PageSearch
-    :form-config="searchConfig"
-    @search-btn-click="handleSearchClick"
-    @reset-btn-click="handleResetClick"
-  />
-  <PageContent
-    ref="pageContentRef"
+  <PageContainer
+    :hooks="hooks"
+    :events="events"
+    :search-config="searchConfig"
     :content-config="contentConfig"
-    @create-btn-click="handleCreateData"
-    @preview-btn-click="row => handlePreviewData(row)"
-    @update-btn-click="row => handleUpdateData(row)"
-  />
-  <PageModal
-    ref="pageModalRef"
-    :modal-config="modalConfig"
-    :default-info="defaultInfo"
-    @confirm-btn-click="handleConfrim"
   />
   <!-- </PageAuth> -->
 </template>

+ 0 - 103
src/views/parameter/good/cpns/commodity-feedback.vue

@@ -1,103 +0,0 @@
-<script setup lang="ts">
-import { ref } from "vue";
-import { goodTypeOptions } from "../config/_options";
-import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
-import CommodityModal from "./commodity-modal.vue";
-
-defineProps<{
-  feedback: Record<string, any>;
-}>();
-
-const commodityModalRef = ref<InstanceType<typeof CommodityModal> | null>(null);
-</script>
-
-<template>
-  <div class="flex flex-col gap-5">
-    <ElCard v-for="(item, index) in feedback" :key="item.id">
-      <h1 class="mb-2">商品要求 {{ index + 1 }}</h1>
-      <ElTable border class="mb-2" :data="[item]" size="small">
-        <ElTableColumn prop="good_type" label="商品类型">
-          <template #="{ row }">
-            <ElTag>
-              {{
-                goodTypeOptions.find(({ id }) => id === row.good_type)?.label ||
-                "--"
-              }}
-            </ElTag>
-          </template>
-        </ElTableColumn>
-        <ElTableColumn prop="budget_price" label="预算单价" />
-        <ElTableColumn prop="num" label="购买数量" />
-        <ElTableColumn prop="cat_name" label="商品分类" width="220">
-          <template #="{ row }">
-            {{ row.can.map(({ name }) => name).join("_") }}
-          </template>
-        </ElTableColumn>
-        <ElTableColumn label="图片">
-          <template #="{ row }">
-            <ElImage
-              v-if="row.good_info_img"
-              style="width: 30px; height: 30px"
-              :preview-src-list="[row.good_info_img]"
-              preview-teleported
-            />
-          </template>
-        </ElTableColumn>
-        <ElTableColumn prop="good_name" label="商品名称" />
-      </ElTable>
-      <h1 class="mb-2">商品反馈情况</h1>
-      <ElTable border :data="[item]">
-        <ElTableColumn prop="pgNo" label="商品要求编码" min-width="180" />
-        <ElTableColumn prop="sale_price" label="销售单价" min-width="120" />
-        <ElTableColumn prop="num" label="购买数量" min-width="120" />
-        <ElTableColumn prop="" label="商品图片" min-width="120">
-          <template #="{ row }">
-            <ElImage
-              v-if="row.good_info_img"
-              :src="row.good_info_img"
-              style="width: 30px; height: 30px"
-              :preview-src-list="[row.good_info_img]"
-              preview-teleported
-            />
-          </template>
-        </ElTableColumn>
-        <ElTableColumn prop="good_name" label="商品名称" min-width="180" />
-        <ElTableColumn prop="class_cat" label="商品分类" min-width="220">
-          <template #="{ row }">
-            <ElTag>
-              {{
-                goodTypeOptions.find(({ id }) => id === row.good_type)?.label ||
-                "--"
-              }}
-            </ElTag>
-          </template>
-        </ElTableColumn>
-        <ElTableColumn prop="source" label="商品来源" min-width="120">
-          <template #="{ row }">
-            <ElTag>
-              {{ row.data_source === "1" ? "平台商品" : "采反商品" }}
-            </ElTag>
-          </template>
-        </ElTableColumn>
-        <ElTableColumn prop="expire_day" label="信息有效期" min-width="140" />
-        <ElTableColumn prop="work_day" label="制作工期" min-width="120" />
-        <ElTableColumn prop="delivery_day" label="物流时间" min-width="120" />
-        <ElTableColumn prop="creater" label="负责人" min-width="80" />
-        <ElTableColumn fixed="right" label="操作" width="80">
-          <template #="{ row }">
-            <ElTooltip placement="top" content="详情">
-              <ElButton
-                @click="() => commodityModalRef.onDisplay(row)"
-                type="primary"
-                :icon="useRenderIcon('eye-view')"
-                link
-              />
-            </ElTooltip>
-          </template>
-        </ElTableColumn>
-      </ElTable>
-    </ElCard>
-
-    <CommodityModal ref="commodityModalRef" />
-  </div>
-</template>

+ 0 - 70
src/views/parameter/good/cpns/commodity-modal.vue

@@ -1,70 +0,0 @@
-<script setup lang="ts">
-// import { ref, computed } from "vue";
-// import BasicDescriptions from "/@/components/BasicDescriptions";
-// import { useAsync } from "/@/hooks/useAsync";
-
-// import {
-//   platformGoodColumns,
-//   commodityFeedbackColumns
-// } from "./../config/_details";
-
-// import {
-//   httpPlatformGoodDetail,
-//   httpCommodityGoodDetail
-// } from "/@/api/sellOut/project";
-
-// const visible = ref(false);
-// const isPlatform = ref(false);
-
-// const title = computed(() =>
-//   isPlatform.value ? "平台商品详情" : "采反商品详情"
-// );
-
-// const columns = computed(() =>
-//   isPlatform.value ? platformGoodColumns : commodityFeedbackColumns
-// );
-
-// const {
-//   data,
-//   setData,
-//   loading,
-//   run: detail
-// } = useAsync<Record<string, any>>({
-//   initalData: {}
-// });
-
-// function onDisplay(data) {
-//   const { data_source, skuCode, spuCode } = data;
-//   isPlatform.value = data_source === "1";
-
-//   visible.value = true;
-
-//   detail(
-//     isPlatform.value
-//       ? httpPlatformGoodDetail({ skuCode })
-//       : httpCommodityGoodDetail({ spuCode })
-//   );
-// }
-
-// defineExpose({
-//   onDisplay
-// });
-</script>
-
-<template>
-  11
-  <!-- <ElDialog
-    center
-    v-model="visible"
-    :title="title"
-    width="1024px"
-    @close="() => setData({})"
-  >
-    <BasicDescriptions
-      labelWidth="100"
-      :columns="columns"
-      v-loading="loading"
-      :data="data"
-    />
-  </ElDialog> -->
-</template>

+ 4 - 2
src/views/parameter/good/cpns/project-form.vue

@@ -3,7 +3,6 @@ import { ref, watchEffect, unref } from "vue";
 import { ElForm, ElMessage } from "element-plus";
 import { projectFormConfig } from "../config/_details";
 import { projectFormRules } from "../config/_rules";
-import { httpDetail } from "/@/api/parameter/good";
 import { BasicForm } from "/@/components/BasicForm";
 import LadderModal from "./ladder-modal.vue";
 import LadderTable from "./ladder-table.vue";
@@ -43,12 +42,15 @@ function handleCreate() {
     emit("create", params);
   });
 }
+
 watchEffect(() => {
   const { readonly, data } = props;
   if (readonly && !data) {
     return;
   }
-  formData.value = transform(formItems, data, {});
+  if (readonly) {
+    formData.value = transform(formItems, data, {});
+  }
 });
 </script>
 

+ 3 - 2
src/views/parameter/video/config/content.config.ts

@@ -3,7 +3,8 @@ import {
   httpAdd,
   httpDelete,
   httpStatus,
-  httpList
+  httpList,
+  httpUpdate
 } from "/@/api/parameter/video";
 import { renderStatus } from "/@/utils/column-helper";
 import { STATUS_OPTIONS } from "/@/config/status";
@@ -49,7 +50,7 @@ const contentConfig: ContentConfig = {
     httpDelete,
     httpStatus,
     httpList,
-    httpUpdate: true
+    httpUpdate,
   },
   notPreview: false
 };