xiaodai2017 2 år sedan
förälder
incheckning
cec149bfbb
36 ändrade filer med 779 tillägg och 1205 borttagningar
  1. 2 8
      src/api/components/remoteSelect.ts
  2. 7 27
      src/api/operate/batchCreatUser.ts
  3. 15 11
      src/components/BasicForm/src/_createDafaultData.ts
  4. 22 0
      src/components/PageContent/src/actions/action-changePwd.tsx
  5. 22 0
      src/components/PageContent/src/actions/action-resetPwd.tsx
  6. 5 2
      src/components/PageContent/src/actions/index.ts
  7. 8 1
      src/components/PageContent/src/types.ts
  8. 5 1
      src/components/PageModal/src/page-modal.vue
  9. 5 0
      src/components/PageModalShell/index.ts
  10. 15 0
      src/components/PageModalShell/src/description.vue
  11. 71 0
      src/components/PageModalShell/src/hooks/use-page-modal.ts
  12. 54 0
      src/components/PageModalShell/src/page-modal.vue
  13. 47 0
      src/components/PageModalShell/src/types.ts
  14. 11 0
      src/components/PageModalShell/src/utils/create-basic-title.ts
  15. 3 3
      src/components/RemoteSelect/index.ts
  16. 0 52
      src/components/RemoteSelect/src/search/Customer.vue
  17. 8 7
      src/components/RemoteSelect/src/search/Video.vue
  18. 7 0
      src/config/status.ts
  19. 13 7
      src/utils/column-helper.ts
  20. 94 0
      src/views/mobile/user/config/_details.ts
  21. 52 0
      src/views/mobile/user/config/_rules.ts
  22. 9 5
      src/views/mobile/user/config/content.config.ts
  23. 37 76
      src/views/mobile/user/config/modal.config.ts
  24. 130 7
      src/views/mobile/user/index.vue
  25. 7 424
      src/views/operate/batchCreatUser/config/_details.ts
  26. 0 13
      src/views/operate/batchCreatUser/config/_rules.ts
  27. 31 25
      src/views/operate/batchCreatUser/config/content.config.ts
  28. 14 0
      src/views/operate/batchCreatUser/config/modal.config.ts
  29. 4 13
      src/views/operate/batchCreatUser/config/search.config.ts
  30. 0 81
      src/views/operate/batchCreatUser/cpns/ladder-modal.vue
  31. 0 55
      src/views/operate/batchCreatUser/cpns/ladder-table.vue
  32. 0 107
      src/views/operate/batchCreatUser/cpns/project-form.vue
  33. 0 80
      src/views/operate/batchCreatUser/detail.vue
  34. 81 27
      src/views/operate/batchCreatUser/index.vue
  35. 0 103
      src/views/operate/setComGood/cpns/commodity-feedback.vue
  36. 0 70
      src/views/operate/setComGood/cpns/commodity-modal.vue

+ 2 - 8
src/api/components/remoteSelect.ts

@@ -3,8 +3,8 @@ import { http } from "/@/utils/http";
 
 const { VITE_PROXY_DOMAIN_REAL } = loadEnv();
 
-export async function httpBrandList(data: object): Promise<DataType<any>> {
-  return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/brandlist`, {
+export async function httpVideoList(data: object): Promise<DataType<any>> {
+  return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/videoList`, {
     data
   });
 }
@@ -15,12 +15,6 @@ export async function httpUnitList(data: object): Promise<DataType<any>> {
   });
 }
 
-export async function httpCategorys(data: object): Promise<DataType<any>> {
-  return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/catwlist`, {
-    data
-  });
-}
-
 // 全部卡类型
 export async function httpCardAll(data: object = {}): Promise<DataType<any>> {
   return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/cardAll`, {

+ 7 - 27
src/api/operate/batchCreatUser.ts

@@ -16,31 +16,11 @@ export async function httpAdd(data: object = {}): Promise<DataType<any>> {
 
 //分页查询
 export async function httpList(data: object): Promise<DataType<any[]>> {
-  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/companyRead`, {
-    data
-  });
-}
-// 更新
-export async function httpUpdate(data: object = {}): Promise<DataType<any>> {
-  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/companyEdit`, {
-    data
-  });
-}
-// 状态
-export async function httpStatus(data: object = {}): Promise<DataType<any>> {
-  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/companyChange`, {
-    data
-  });
-}
-// 删除
-export async function httpDelete(data: object = {}): Promise<DataType<any>> {
-  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/companyDelete`, {
-    data
-  });
+  return http.request(
+    `post`,
+    `${VITE_PROXY_DOMAIN_REAL}admin/accoountBatchLog`,
+    {
+      data
+    }
+  );
 }

+ 15 - 11
src/components/BasicForm/src/_createDafaultData.ts

@@ -1,5 +1,5 @@
 import { FormItem } from "./types";
-
+import { isArray } from "/@/utils/validate";
 export function createDefaultData(formItems: FormItem[]) {
   console.log(formItems);
   const data: Record<string, any> = {};
@@ -29,18 +29,22 @@ export function transform(
   transform?: Record<string, any>
 ) {
   const detail: Record<string, any> = {};
-
   for (let i = 0; i < formItems.length; i++) {
-    let target = "";
     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];
+    switch (type) {
+      case "checkbox":
+      case "array":
+      case "img_upload_list":
+        detail[source] = data[transform[source]] || data[source] || [];
+        break;
+      case "number":
+        detail[source] =
+          Number(data[transform[source]]) || Number(data[source]) || 0;
+        break;
+      default:
+        detail[source] = data[transform[source]] || data[source] || "";
+        break;
+    }
   }
 
   return detail;

+ 22 - 0
src/components/PageContent/src/actions/action-changePwd.tsx

@@ -0,0 +1,22 @@
+import { defineComponent } from "vue";
+import { actionProps } from "../types";
+import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
+
+const ActionUpdate = defineComponent({
+  name: "ActionUpdate",
+  props: actionProps,
+  emits: ["update"],
+  setup(_, { emit }) {
+    return () => (
+      <el-button
+        class="reset-margin"
+        onClick={() => emit("changePwd")}
+        link
+        type="primary"
+        icon={useRenderIcon("edits")}
+      />
+    );
+  }
+});
+
+export default ActionUpdate;

+ 22 - 0
src/components/PageContent/src/actions/action-resetPwd.tsx

@@ -0,0 +1,22 @@
+import { defineComponent } from "vue";
+import { actionProps } from "../types";
+import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
+
+const ActionUpdate = defineComponent({
+  name: "ActionUpdate",
+  props: actionProps,
+  emits: ["update"],
+  setup(_, { emit }) {
+    return () => (
+      <el-button
+        class="reset-margin"
+        onClick={() => emit("resetPwd")}
+        link
+        type="primary"
+        icon={useRenderIcon("edits")}
+      />
+    );
+  }
+});
+
+export default ActionUpdate;

+ 5 - 2
src/components/PageContent/src/actions/index.ts

@@ -3,13 +3,16 @@ import Delete from "./action-delete";
 import Update from "./action-update";
 import Preview from "./action-preview";
 import Status from "./action-status";
-
+import ResetPwd from "./action-resetPwd";
+import ChangePwds from "./action-changePwd";
 const Operation = {
   Create,
   Update,
   Delete,
   Preview,
-  Status
+  Status,
+  ResetPwd,
+  ChangePwds
 };
 
 export { Operation };

+ 8 - 1
src/components/PageContent/src/types.ts

@@ -45,7 +45,14 @@ interface ContentApiResponse {
 
 type API = (data: any) => Promise<ContentApiResponse>;
 
-export type ActionType = "update" | "delete" | "create" | "preview" | "status";
+export type ActionType =
+  | "update"
+  | "delete"
+  | "create"
+  | "preview"
+  | "status"
+  | "resetPwd"
+  | "changePwd";
 
 export interface ContentApis {
   httpAdd?: API;

+ 5 - 1
src/components/PageModal/src/page-modal.vue

@@ -107,7 +107,11 @@ defineExpose({
       v-if="prviewDescription"
       :config="modalConfig"
       :default-info="defaultInfo"
-    />
+    >
+      <template>
+        <slot />
+      </template>
+    </Description>
 
     <!-- 保存/重置 -->
     <div class="flex justify-end" v-if="!isPreview">

+ 5 - 0
src/components/PageModalShell/index.ts

@@ -0,0 +1,5 @@
+import PageModal from "./src/page-modal.vue";
+
+export { usePageModal } from "./src/hooks/use-page-modal";
+
+export { PageModal };

+ 15 - 0
src/components/PageModalShell/src/description.vue

@@ -0,0 +1,15 @@
+<script setup lang="ts">
+import { descritonProps } from "./types";
+
+defineProps(descritonProps);
+</script>
+
+<template>
+  <el-descriptions :column="1" border>
+    <template v-for="(item, index) in config.formItems" :key="index">
+      <el-descriptions-item :label="item.label" align="center">{{
+        defaultInfo[item.field]
+      }}</el-descriptions-item>
+    </template>
+  </el-descriptions>
+</template>

+ 71 - 0
src/components/PageModalShell/src/hooks/use-page-modal.ts

@@ -0,0 +1,71 @@
+import { Ref, ref } from "vue";
+import { PageModalInstance } from "../types";
+import {
+  ActionType,
+  PageContentInstance
+} from "/@/components/PageContent/src/types";
+
+type CallbackType = () => any;
+
+type Config = {
+  createCallback?: CallbackType;
+  updateCallback?: CallbackType;
+  previewCallback?: CallbackType;
+  confirmCallback?: (data: any) => any;
+  pageContentRef: Ref<PageContentInstance>;
+};
+
+export function usePageModal({
+  createCallback,
+  updateCallback,
+  confirmCallback,
+  previewCallback,
+  pageContentRef
+}: Config) {
+  const pageModalRef = ref<PageModalInstance>(null);
+  const defaultInfo = ref<Record<string, string>>({});
+
+  function handleCreateData() {
+    defaultInfo.value = {};
+    pageModalRef.value.type = "create";
+    createCallback && createCallback();
+    pageModalRef.value.dialogVisible = true;
+  }
+
+  function handleUpdateData(item: any) {
+    defaultInfo.value = { ...item };
+    pageModalRef.value.type = "update";
+    updateCallback && updateCallback();
+    pageModalRef.value.dialogVisible = true;
+  }
+
+  function handlePreviewData(item: any) {
+    defaultInfo.value = { ...item };
+    pageModalRef.value.type = "preview";
+    previewCallback && previewCallback();
+    pageModalRef.value.dialogVisible = true;
+  }
+
+  function handleConfrim(type: ActionType, data: any) {
+    const result = confirmCallback ? confirmCallback(data) : {};
+    pageModalRef.value.confirmLoading = true;
+    const params = {
+      ...(type === "update" ? { id: defaultInfo.value.id } : {}),
+      ...(result ? result : {}),
+      ...data
+    };
+    pageContentRef.value.onBeforeAction(type, params, () => {
+      pageModalRef.value.confirmLoading = false;
+      pageModalRef.value.dialogVisible = false;
+    });
+  }
+
+  return {
+    handleCreateData,
+    handleUpdateData,
+    handlePreviewData,
+    handleConfrim,
+    defaultInfo,
+    pageModalRef
+  };
+}

+ 54 - 0
src/components/PageModalShell/src/page-modal.vue

@@ -0,0 +1,54 @@
+<script setup lang="ts">
+import { computed, ref } from "vue";
+import Description from "./description.vue";
+import { ActionType } from "/@/components/PageContent";
+import { createBasicTitle } from "./utils/create-basic-title";
+import { modalProps } from "./types";
+
+const props = defineProps(modalProps);
+// const emit = defineEmits(["confirmBtnClick"]);
+
+const type = ref<ActionType>("preview");
+const dialogVisible = ref(false);
+const confirmLoading = ref(false);
+
+//状态是否处于预览详情
+const isPreview = computed(() => type.value === "preview");
+
+const title = computed(() => {
+  const basicTitle = createBasicTitle(type.value);
+  return type.value === "preview"
+    ? props.modalConfig.title + basicTitle
+    : basicTitle + props.modalConfig.title;
+});
+
+const width = computed(() => {
+  return props.modalConfig.width;
+});
+
+defineExpose({
+  dialogVisible,
+  confirmLoading,
+  type
+});
+</script>
+
+<template>
+  <el-dialog
+    :title="title"
+    v-model="dialogVisible"
+    center
+    destroy-on-close
+    :width="width ? width : '1024px'"
+  >
+    <!--插槽  -->
+    <template v-if="!isPreview">
+      <slot />
+    </template>
+    <Description
+      v-if="isPreview"
+      :config="modalConfig"
+      :default-info="defaultInfo"
+    />
+  </el-dialog>
+</template>

+ 47 - 0
src/components/PageModalShell/src/types.ts

@@ -0,0 +1,47 @@
+import { ActionType } from "../../PageContent";
+import { FormGorup, FormItem } from "../../BasicForm";
+import pageModal from "./page-modal.vue";
+
+export type PageModalInstance = typeof pageModal & {
+  dialogVisible: boolean;
+  confirmLoading: boolean;
+  type: ActionType;
+};
+
+export interface ModalConfig {
+  title: string;
+  width?: string;
+  formItems?: Array<FormItem>;
+  formGroup?: Array<FormGorup>;
+  colLayout?: any;
+  itemStyle?: Record<string, string>;
+  labelWidth?: string;
+  contact?: string;
+  divider?: boolean;
+}
+
+export const modalProps = {
+  modalConfig: {
+    type: Object as PropType<ModalConfig>,
+    required: true
+  },
+  prviewDescription: {
+    type: Boolean,
+    default: false
+  },
+  defaultInfo: {
+    type: Object,
+    required: true
+  }
+};
+
+export const descritonProps = {
+  config: {
+    type: Object as PropType<ModalConfig>,
+    required: true
+  },
+  defaultInfo: {
+    type: Object,
+    required: true
+  }
+};

+ 11 - 0
src/components/PageModalShell/src/utils/create-basic-title.ts

@@ -0,0 +1,11 @@
+import { ActionType } from "/@/components/PageContent";
+
+const mapActionToBasicTitle = {
+  update: "编辑",
+  create: "新增",
+  preview: "详情"
+};
+
+export function createBasicTitle(type: ActionType) {
+  return mapActionToBasicTitle[type];
+}

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

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

+ 0 - 52
src/components/RemoteSelect/src/search/Customer.vue

@@ -1,52 +0,0 @@
-<script setup lang="ts">
-import { ref, watch } from "vue";
-import { useVModel } from "@vueuse/core";
-import { httpCustomerlist } from "/@/api/other";
-import RemoteSelect from "../remote-select";
-
-const props = defineProps<{
-  placeholder?: string;
-  modelValue?: string;
-  companyNo?: string;
-  disabled?: boolean;
-}>();
-
-const remoteSelectRef = ref<any>(null);
-
-defineEmits(["update:modelValue"]);
-
-const value = useVModel(props, "modelValue");
-
-function initalData(companyNo) {
-  remoteSelectRef.value.initalData({ companyNo });
-}
-
-watch(
-  () => props.companyNo,
-  companyNo => {
-    if (!companyNo && !remoteSelectRef.value) return;
-    remoteSelectRef.value.initalData({ companyNo });
-  },
-  {
-    deep: true
-  }
-);
-
-defineExpose({
-  initalData
-});
-</script>
-
-<template>
-  <RemoteSelect
-    v-model="value"
-    :api="httpCustomerlist"
-    :placeholder="placeholder"
-    :disabled="disabled"
-    ref="remoteSelectRef"
-    response-label-prop="companyName"
-    response-val-prop="companyNo"
-    request-prop="companyName"
-    prop="item"
-  />
-</template>

+ 8 - 7
src/components/RemoteSelect/src/search/Category.vue → src/components/RemoteSelect/src/search/Video.vue

@@ -1,18 +1,18 @@
 <script setup lang="ts">
 import { ref } from "vue";
 import { useVModel } from "@vueuse/core";
-import { httpList } from "/@/api/operate/setComGood";
+import { httpVideoList } from "/@/api/components/remoteSelect";
 import RemoteSelect from "../remote-select";
 
 const props = defineProps<{
   placeholder?: string;
   modelValue?: string;
-  cat_name?: string;
+  unit?: string;
 }>();
 
 const remoteSelectRef = ref<any>(null);
 
-defineEmits(["update:modelValue"]);
+const emit = defineEmits(["update:modelValue", "change"]);
 
 const value = useVModel(props, "modelValue");
 
@@ -28,12 +28,13 @@ defineExpose({
 <template>
   <RemoteSelect
     v-model="value"
-    :api="httpList"
+    :api="httpVideoList"
     :placeholder="placeholder"
     ref="remoteSelectRef"
-    response-label-prop="search"
+    response-label-prop="video_name"
     response-val-prop="id"
-    request-prop="cat_name"
-    @inital="id => (value = id)"
+    request-prop="video_name"
+    @item-change="val => emit('change', val)"
+    @inital="unit => (value = unit)"
   />
 </template>

+ 7 - 0
src/config/status.ts

@@ -55,6 +55,13 @@ export const GOOD_OPTIONS = [
   { id: "1", label: "商城商品", value: "1", type: "success" },
   { id: "2", label: "兑换商品", value: "2", type: "primary" }
 ];
+
+export const BATCH_USER_OPTIONS = [
+  { id: "1", label: "待处理", value: "1", type: "warning" },
+  { id: "2", label: "处理中", value: "2", type: "primary" },
+  { id: "3", label: "处理成功", value: "2", type: "success" },
+  { id: "4", label: "处理失败", value: "2", type: "error" }
+];
 export const POWERS = [
   "001",
   "002",

+ 13 - 7
src/utils/column-helper.ts

@@ -57,13 +57,7 @@ export function renderImage(prop = "image") {
 export function convertOptions(source: any[], prop = "id") {
   return source.map(item => ({ value: item[prop], label: item.label }));
 }
-export function timeInterval(start: string, end: string) {
-  return {
-    cellRenderer({ row }) {
-      return `${row[start]}~${row[end]}`;
-    }
-  };
-}
+
 export function renderHtml(prop = "content") {
   return {
     cellRenderer({ row }) {
@@ -97,3 +91,15 @@ export function renderHtml(prop = "content") {
     }
   };
 }
+export function timeInterval(props: string[], tem: string) {
+  return {
+    cellRenderer({ row }) {
+      let str = "";
+      props.forEach((s, index) => {
+        str += index === 0 ? `${row[s]}` : ` ${tem}${row[s]}`;
+      });
+
+      return str;
+    }
+  };
+}

+ 94 - 0
src/views/mobile/user/config/_details.ts

@@ -0,0 +1,94 @@
+/* eslint-disable prettier/prettier */
+import { FormConfig } from "/@/components/PageSearch";
+export const projectFormConfig: FormConfig = {
+  labelWidth: "85px",
+  formItems: [
+    {
+      label: "账户id",
+      field: "id",
+      type: "input",
+      isHidden: true,
+      placeholder: "账户id",
+      span: 24
+    },
+    {
+      label: "账户",
+      field: "username",
+      slot: "username",
+      placeholder: "账户",
+      span: 12
+    },
+    {
+      label: "添加时间",
+      field: "addtime",
+      slot: "addtime",
+      placeholder: "添加时间",
+      span: 12
+    },
+    {
+      label: "公司",
+      field: "company_title",
+      slot: "company_title",
+      placeholder: "公司",
+      span: 12
+    },
+    {
+      label: "卡类型",
+      field: "card_title",
+      slot: "card_title",
+      placeholder: "卡类型",
+      span: 12
+    },
+    {
+      label: "有效开始日期",
+      field: "starttime",
+      type: "date_picker",
+      otherOptions: {
+        type: "date",
+        format: "YYYY-MM-DD"
+      },
+      placeholder: "有效开始日期",
+      span: 12
+    },
+    {
+      label: "有效结束时间",
+      field: "expiretime",
+      type: "date_picker",
+      otherOptions: {
+        type: "date",
+        format: "YYYY-MM-DD"
+      },
+      placeholder: "有效结束时间",
+      span: 12
+    },
+    {
+      label: "姓名",
+      field: "name",
+      type: "input",
+      placeholder: "姓名",
+      span: 12
+    },
+    {
+      label: "手机号",
+      field: "mobile",
+      type: "input",
+      placeholder: "手机号",
+      span: 12
+    },
+    {
+      label: "备注",
+      field: "remark",
+      type: "textarea",
+      placeholder: "字母段",
+      span: 24
+    },
+    {
+      label: "直播视频",
+      field: "video_ids",
+      slot: "video_ids",
+      type: "array",
+      placeholder: "直播视频",
+      span: 24
+    }
+  ]
+};

+ 52 - 0
src/views/mobile/user/config/_rules.ts

@@ -0,0 +1,52 @@
+import { FormRules } from "element-plus";
+import { isArray, isMobile, isChinese, isEmoticon } from "/@/utils/validate";
+export const projectFormRules: FormRules = {
+  starttime: {
+    trigger: "change",
+    required: true,
+    validator(_, value) {
+      const val = value ?? "";
+      if (val === "") return new Error("请选择有效开始日期");
+      return true;
+    }
+  },
+  expiretime: {
+    trigger: "change",
+    required: true,
+    validator(_, value) {
+      const val = value ?? "";
+      if (val === "") return new Error("请选择有效结束日期");
+      return true;
+    }
+  },
+
+  name: {
+    trigger: "change",
+    required: true,
+    validator(_, value) {
+      if (value === "") return new Error("请输入姓名!");
+      if (!isChinese(value)) return new Error("姓名必须为汉字!");
+      if (isEmoticon(value)) return new Error("姓名必须为汉字!");
+      return true;
+    }
+  },
+  mobile: {
+    trigger: "change",
+    required: true,
+    validator(_, value) {
+      if (!value || !isMobile(value)) return new Error("手机号不规范!");
+      return true;
+    }
+  },
+  video_ids: {
+    trigger: "change",
+    required: true,
+    validator(_, value) {
+      console.log(value);
+      if (!isArray(value)) return new Error("请选择直播视频");
+      const length = value.length;
+      if (length === 0) return new Error("请选择直播视频");
+      return true;
+    }
+  }
+};

+ 9 - 5
src/views/mobile/user/config/content.config.ts

@@ -1,5 +1,9 @@
 import { ContentConfig } from "/@/components/PageContent";
-import { httpDelete, httpList, httpUpdate } 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";
 
@@ -21,7 +25,7 @@ const columns = [
     ...renderStatus(ACCOUNT_STATUS_OPTIONS)
   },
   {
-    prop: "nickname",
+    prop: "name",
     label: "客户姓名",
     minWidth: "100px"
   },
@@ -34,12 +38,12 @@ const columns = [
     prop: "time",
     minWidth: "310",
     label: "账户有效期",
-    ...timeInterval("starttime", "expiretime")
+    ...timeInterval(["starttime", "expiretime"], "~")
   },
   {
     prop: "activetime",
     label: "账户激活时间",
-    minWidth: "160px"
+    width: "180px"
   },
   {
     prop: "addtime",
@@ -58,7 +62,7 @@ const contentConfig: ContentConfig = {
   title: "用户管理",
   columns,
   apis: {
-    httpDelete,
+    // httpDelete,
     httpList,
     httpUpdate
   },

+ 37 - 76
src/views/mobile/user/config/modal.config.ts

@@ -1,9 +1,9 @@
 import { ModalConfig } from "/@/components/PageModal/src/types";
-import { isLicense } from "/@/utils/validate";
-
+import { h } from "vue";
+import { ElTag, ElImage } from "element-plus";
 const modalConfig: ModalConfig = {
   title: "账号",
-  colLayout: { span: 24 },
+  colLayout: { span: 12 },
   itemStyle: {},
   contact: "invoice_mobile",
   formItems: [
@@ -12,41 +12,54 @@ const modalConfig: ModalConfig = {
       type: "input",
       label: "账号",
       labelWidth: "120px",
-      placeholder: "账号",
-      rules: [{ required: true, trigger: "change", message: "请输入账号" }]
+      placeholder: "账号"
+    },
+
+    {
+      field: "company_title",
+      type: "input",
+      label: "公司",
+      labelWidth: "120px",
+      placeholder: "公司"
     },
-    //密码
-    //有效期
+
     {
-      field: "date_picker",
-      type: "date_picker",
-      label: "有效期",
+      field: "card_title",
+      type: "input",
+      label: "卡类型",
       labelWidth: "120px",
-      otherOptions: {
-        type: "daterange",
-        startProp: "starttime",
-        endProp: "expiretime",
-        startPlaceholder: "开始时间",
-        endPlaceholder: "结束时间"
-      },
-      rules: [{ required: true, trigger: "change", message: "请输入账号" }]
+      placeholder: "卡类型"
     },
 
     {
-      field: "nickname",
+      field: "name",
       type: "input",
       label: "客户姓名",
       labelWidth: "120px",
-      placeholder: "客户姓名",
-      rules: [{ required: true, trigger: "change", message: "请输入客户姓名" }]
+      placeholder: "客户姓名"
     },
     {
       field: "mobile",
       type: "input",
       label: "手机号",
       labelWidth: "120px",
-      placeholder: "手机号",
-      rules: [{ required: true, trigger: "change", message: "请输入手机号" }]
+      placeholder: "手机号"
+    },
+    {
+      field: "addtime",
+      type: "input",
+      label: "创建时间",
+      labelWidth: "120px",
+      placeholder: "创建时间"
+    },
+
+    {
+      field: "video_list",
+      type: "array",
+      label: "直播视频",
+      labelWidth: "120px",
+      placeholder: "直播视频",
+      span: 24
     },
     {
       field: "remark",
@@ -54,60 +67,8 @@ const modalConfig: ModalConfig = {
       label: "备注",
       labelWidth: "120px",
       placeholder: "备注",
-      rules: [{ required: true, trigger: "change", message: "请输入备注" }]
+      span: 24
     }
-    // {
-    //   field: "invoice_addr",
-    //   type: "input",
-    //   labelWidth: "120px",
-    //   label: "有效期",
-    //   placeholder: "有效期",
-    //   rules: [{ required: true, trigger: "change", message: "请选择有效期" }]
-    // },
-    // {
-    //   field: "invoice_code",
-    //   type: "input",
-    //   labelWidth: "120px",
-    //   label: "纳税识别号",
-    //   placeholder: "纳税识别号",
-    //   rules: [
-    //     {
-    //       validator(_, value) {
-    //         return isLicense(value);
-    //       },
-    //       required: true,
-    //       message: "纳税人识别号格式不正确"
-    //     }
-    //   ]
-    // },
-    // {
-    //   field: "invoice_bank",
-    //   type: "input",
-    //   labelWidth: "120px",
-    //   label: "企业开户银行",
-    //   placeholder: "企业开户银行",
-    //   rules: [
-    //     { required: true, trigger: "change", message: "请输入企业开户银行" }
-    //   ]
-    // },
-    // {
-    //   field: "invoice_bankNo",
-    //   type: "input",
-    //   labelWidth: "120px",
-    //   label: "银行账户",
-    //   placeholder: "银行账户",
-    //   rules: [{ required: true, trigger: "change", message: "请输入银行账户" }]
-    // },
-    // {
-    //   field: "invoice_mobile",
-    //   type: "contact",
-    //   label: "企业联系方式",
-    //   labelWidth: "120px",
-    //   placeholder: "企业联系方式",
-    //   rules: [
-    //     { required: true, trigger: "change", message: "请输入企业联系方式" }
-    //   ]
-    // }
   ]
 };
 

+ 130 - 7
src/views/mobile/user/index.vue

@@ -1,21 +1,34 @@
 <script setup lang="ts">
-import { ref } from "vue";
+import { ref, unref, computed } 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 { PageModal, usePageModal } from "/@/components/PageModalShell";
 import modalConfig from "./config/modal.config";
 import { PageContent } from "/@/components/PageContent";
 import type { PageContentInstance } from "/@/components/PageContent";
 import { useResponseHandle } from "/@/hooks/useAsync";
 import { httpDetail } from "/@/api/mobile/user";
+import { projectFormConfig } from "./config/_details";
+import { projectFormRules } from "./config/_rules";
+import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
+
+import {
+  BasicForm,
+  transform,
+  createDefaultData
+} from "/@/components/BasicForm";
+import { Video } from "/@/components/RemoteSelect";
+import { ElForm } from "element-plus";
+// import dayjs from "dayjs";
+const { formItems } = projectFormConfig;
+const formData = ref<Record<string, any>>(createDefaultData(formItems));
 const pageContentRef = ref<PageContentInstance | null>(null);
 
 const {
   pageModalRef,
   handleUpdateData,
-  handleCreateData,
   handlePreviewData,
   handleConfrim,
   defaultInfo
@@ -24,9 +37,10 @@ const {
 });
 const { handleResetClick, handleSearchClick } = usePageSearch();
 const responseHandle = useResponseHandle();
+const Video_id = ref("");
+let columnsData = null;
 async function handleDetailData(row, type) {
   const { id } = row;
-  //
   const { code, data, message } = await httpDetail({ id: id });
 
   responseHandle({
@@ -37,11 +51,52 @@ async function handleDetailData(row, type) {
         handlePreviewData(data);
       }
       if (type === "update") {
-        handleUpdateData(data);
+        formData.value = transform(formItems, data, {
+          video_ids: "video_list"
+        });
+        columnsData = data;
+        handleUpdateData(unref(formData));
       }
     }
   });
 }
+const basicFormRef = ref<InstanceType<typeof ElForm>>(null);
+function handleCreate() {
+  basicFormRef.value.validate(isValid => {
+    if (!isValid) return;
+    const { video_ids } = formData.value;
+    const params = unref(formData);
+
+    let arr = [];
+    video_ids.forEach(e => {
+      arr.push(e.id);
+    });
+    params.video_ids = arr;
+    handleConfrim("update", params);
+  });
+}
+function videoChange(e) {
+  if (e) {
+    const { id, video_name } = e;
+    const index = formData.value.video_ids.findIndex(
+      e => e.id + "" === id + ""
+    );
+    if (index == -1) {
+      formData.value.video_ids.push({ id, video_name });
+    }
+  }
+}
+async function handleDelete() {
+  // const { config, row, prop } = props;
+  // const { code, message } = await config.api({
+  //   ...(prop ? { [prop]: row[prop] } : { id: row.id })
+  // });
+  // responseHandle({
+  //   code,
+  //   message,
+  //   handler: () => emit("reload")
+  // });
+}
 </script>
 
 <template>
@@ -54,15 +109,83 @@ async function handleDetailData(row, type) {
   <PageContent
     ref="pageContentRef"
     :content-config="contentConfig"
-    @create-btn-click="handleCreateData"
     @preview-btn-click="row => handleDetailData(row, 'preview')"
     @update-btn-click="row => handleDetailData(row, 'update')"
   />
+  <!-- <template #operation>
+      <el-popconfirm
+        title="是否确认删除"
+        placement="top"
+        @onConfirm="handleDelete"
+      >
+        <el-button
+          class="reset-margin"
+          link
+          type="primary"
+          :icon="useRenderIcon('RefreshLeft')"
+        />
+      </el-popconfirm>
+    </template>
+  </PageContent> -->
   <PageModal
     ref="pageModalRef"
     :modal-config="modalConfig"
     :default-info="defaultInfo"
     @confirm-btn-click="handleConfrim"
-  />
+  >
+    <BasicForm
+      ref="basicFormRef"
+      v-bind="projectFormConfig"
+      :form-data="formData"
+      :rules="projectFormRules"
+      :disabled="false"
+      label-width="120px"
+    >
+      <template #username>
+        <div>{{ formData.username }}</div>
+      </template>
+      <template #addtime>
+        <div>{{ formData.addtime }}</div>
+      </template>
+      <template #company_title>
+        <div>{{ formData.company_title }}</div>
+      </template>
+      <template #card_title>
+        <div>{{ formData.card_title }}</div>
+      </template>
+
+      <template #video_ids>
+        <div
+          v-show="formData.video_ids && formData.video_ids.length > 0"
+          style="width: 100%; padding: 0 0 15px 0"
+        >
+          <el-tag
+            v-for="(tag, index) in formData.video_ids"
+            :key="tag.id + index"
+            class="mx-1"
+            disable-transitions
+            closable
+            size="large"
+            @close="formData.video_ids.splice(index, 1)"
+          >
+            {{ tag.video_name }}
+          </el-tag>
+        </div>
+        <div style="width: 50%">
+          <Video
+            v-model="Video_id"
+            placeholder="请选择直播视频"
+            @change="videoChange"
+          />
+        </div>
+      </template>
+
+      <template #footer>
+        <div class="w-full flex justify-end">
+          <ElButton type="primary" @click="handleCreate">保存</ElButton>
+        </div>
+      </template>
+    </BasicForm>
+  </PageModal>
   <!-- </PageAuth> -->
 </template>

+ 7 - 424
src/views/operate/batchCreatUser/config/_details.ts

@@ -1,12 +1,5 @@
 /* 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: [
@@ -14,14 +7,14 @@ export const projectFormConfig: FormConfig = {
       label: "公司",
       field: "company_id",
       placeholder: "公司",
-      span: 12,
+      span: 24,
       slot: "company_id"
     },
     {
       label: "卡类型",
       field: "card_id",
       placeholder: "卡类型",
-      span: 12,
+      span: 24,
       slot: "card_id"
     },
     {
@@ -29,21 +22,21 @@ export const projectFormConfig: FormConfig = {
       field: "headname",
       slot: "headname",
       placeholder: "前缀",
-      span: 6
+      span: 12
     },
     {
       label: "字母段",
       field: "username_prefix",
       type: "input",
       placeholder: "字母段",
-      span: 6
+      span: 12
     },
     {
       label: "年份段",
       field: "username_year",
       type: "number",
       placeholder: "年份段",
-      span: 6
+      span: 12
     },
 
     {
@@ -51,7 +44,7 @@ export const projectFormConfig: FormConfig = {
       field: "suffix",
       slot: "suffix",
       placeholder: "数字段",
-      span: 6
+      span: 12
     },
 
     {
@@ -67,417 +60,7 @@ export const projectFormConfig: FormConfig = {
         format: "YYYY-MM-DD"
       },
       placeholder: "有效时间",
-      span: 12
+      span: 24
     }
   ]
 };
-
-//平台商品详情字段
-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
-  }
-];

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

@@ -1,18 +1,5 @@
 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",

+ 31 - 25
src/views/operate/batchCreatUser/config/content.config.ts

@@ -1,13 +1,7 @@
 import { ContentConfig } from "/@/components/PageContent";
-import {
-  httpList,
-  httpAdd,
-  httpUpdate,
-  httpStatus,
-  httpDelete
-} from "/@/api/operate/batchCreatUser";
-import { renderStatus } from "/@/utils/column-helper";
-import { STATUS_OPTIONS } from "/@/config/status";
+import { httpList, httpAdd } from "/@/api/operate/batchCreatUser";
+import { renderStatus, timeInterval } from "/@/utils/column-helper";
+import { BATCH_USER_OPTIONS } from "/@/config/status";
 
 const columns = [
   {
@@ -18,49 +12,61 @@ const columns = [
 
   {
     prop: "id",
-    label: "ID"
+    label: "ID",
+    width: "90px"
   },
   {
-    prop: "title",
-    label: "卡类型"
+    prop: "status",
+    label: "状态",
+    ...renderStatus(BATCH_USER_OPTIONS),
+    width: "100px"
+  },
+  {
+    prop: "company_title",
+    label: "公司名称",
+    minWidth: "150px"
   },
 
   {
-    prop: "status",
-    label: "状态",
-    ...renderStatus(STATUS_OPTIONS)
+    prop: "card_title",
+    label: "卡类型",
+    width: "120px"
   },
   {
     prop: "contacts",
-    label: "联系人"
+    label: "字母段-年份段",
+    ...timeInterval(["username_prefix", "username_year"], "-"),
+
+    width: "120px"
   },
   {
-    prop: "mobile",
-    label: "联系方式"
+    prop: "starttime",
+    label: "有效日期",
+    ...timeInterval(["starttime", "expiretime"], "~"),
+    width: "200px"
   },
+
   {
     prop: "addtime",
     label: "创建时间",
-    sortable: true
+    sortable: true,
+    width: "160px"
   },
 
   {
     label: "操作",
     fixed: "right",
-    width: 160,
+    width: 60,
     slot: "operation"
   }
 ];
 
 const contentConfig: ContentConfig = {
-  title: "商品管理",
+  title: "批量创建账号",
   columns,
   apis: {
     httpAdd,
-    httpList,
-    httpUpdate,
-    httpStatus,
-    httpDelete
+    httpList
   }
 };
 

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

@@ -0,0 +1,14 @@
+import { ModalConfig } from "/@/components/PageModal/src/types";
+import { isLicense } from "/@/utils/validate";
+
+const modalConfig: ModalConfig = {
+  title: "批量创建账号",
+  colLayout: { span: 24 },
+  itemStyle: {},
+  contact: "batchCreatUser",
+  labelWidth: "100px",
+  width: "700px",
+  formItems: []
+};
+
+export default modalConfig;

+ 4 - 13
src/views/operate/batchCreatUser/config/search.config.ts

@@ -1,29 +1,20 @@
 import { FormConfig } from "/@/components/PageSearch";
-import { STATUS_OPTIONS } from "/@/config/status";
-import { convertOptions } from "/@/utils/column-helper";
-
 const searchFormConfig: FormConfig = {
   formItems: [
-    {
-      field: "status",
-      type: "select",
-      placeholder: "状态",
-      options: convertOptions(STATUS_OPTIONS)
-    },
     {
       field: "title",
       type: "input",
       placeholder: "企业名称"
     },
     {
-      field: "contacts",
+      field: "company_title",
       type: "input",
-      placeholder: "联系人"
+      placeholder: "企业名称"
     },
     {
-      field: "mobile",
+      field: "card_title",
       type: "input",
-      placeholder: "联系方式"
+      placeholder: "卡类型名称"
     }
   ]
 };

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

@@ -1,81 +0,0 @@
-<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>

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

@@ -1,55 +0,0 @@
-<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>

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

@@ -1,107 +0,0 @@
-<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>

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

@@ -1,80 +0,0 @@
-<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>

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

@@ -1,40 +1,94 @@
 <script setup lang="ts">
-import { usePageSearch } from "/@/components/PageSearch";
+import { PageSearch, usePageSearch } from "/@/components/PageSearch";
 import searchConfig from "./config/search.config";
 import contentConfig from "./config/content.config";
 import PageAuth from "/@/components/PageAuth";
-import { useRouter } from "vue-router";
+import { PageModal, usePageModal } from "/@/components/PageModalShell";
+import modalConfig from "./config/modal.config";
+import { PageContent } from "/@/components/PageContent";
+import type { PageContentInstance } from "/@/components/PageContent";
+import { Company, Card } from "/@/components/RemoteSelect";
+import { projectFormConfig } from "./config/_details";
+import { projectFormRules } from "./config/_rules";
+import {
+  BasicForm,
+  transform,
+  createDefaultData
+} from "/@/components/BasicForm";
+import { ElForm } from "element-plus";
+import { ref, unref } from "vue";
+import dayjs from "dayjs";
+// import { httpDetail } from "/@/api/parameter/video";
+const pageContentRef = ref<PageContentInstance | null>(null);
+const { pageModalRef, handleCreateData, handleConfrim, defaultInfo } =
+  usePageModal({
+    pageContentRef
+  });
+const { handleResetClick, handleSearchClick } = usePageSearch();
+const { formItems } = projectFormConfig;
 
-import PageContainer, {
-  type Events,
-  type Hooks
-} from "/@/components/PageContainer";
-
-const pageName = "batchCreatUser";
-
-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)
-  }
-};
+const basicFormRef = ref<InstanceType<typeof ElForm>>(null);
+const formData = ref<Record<string, any>>(createDefaultData(formItems));
+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") : "";
+    delete params["headname"];
+    delete params["suffix"];
+    delete params["title"];
+    handleConfrim("create", params);
+  });
+}
 </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"
   />
+  <PageModal
+    ref="pageModalRef"
+    :modal-config="modalConfig"
+    :default-info="defaultInfo"
+    @confirm-btn-click="handleConfrim"
+  >
+    <BasicForm
+      ref="basicFormRef"
+      v-bind="projectFormConfig"
+      :form-data="formData"
+      :rules="projectFormRules"
+      :disabled="false"
+      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 #footer>
+        <div class="w-full flex justify-end">
+          <ElButton type="primary" @click="handleCreate">保存</ElButton>
+        </div>
+      </template>
+    </BasicForm>
+  </PageModal>
   <!-- </PageAuth> -->
 </template>

+ 0 - 103
src/views/operate/setComGood/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/operate/setComGood/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>