xiaodai2017 пре 2 година
родитељ
комит
f7e1b2d7a5
32 измењених фајлова са 1460 додато и 125 уклоњено
  1. 18 0
      src/api/export.ts
  2. 12 28
      src/api/mobile/exchangeOrder.ts
  3. 3 1
      src/components/PageContent/src/actions/index.ts
  4. 0 1
      src/components/PageContent/src/page-content.tsx
  5. 2 1
      src/components/PageContent/src/types.ts
  6. 169 0
      src/components/PageListModall/columns.tsx
  7. 3 0
      src/components/PageListModall/index.ts
  8. 52 0
      src/components/PageListModall/pageListModal.vue
  9. 26 0
      src/components/PageListModall/search.config.ts
  10. 41 0
      src/components/PageListModall/types.ts
  11. 5 9
      src/components/resetPassword.vue
  12. 3 0
      src/components/resetPwd/index.ts
  13. 63 0
      src/components/resetPwd/pageListModal.vue
  14. 30 0
      src/components/resetPwd/types.ts
  15. 128 0
      src/utils/export.ts
  16. 1 1
      src/views/interest/account/index.vue
  17. 3 9
      src/views/mobile/exchangeOrder/config/content.config.ts
  18. 95 0
      src/views/mobile/exchangeStock/config/content.config1.ts
  19. 31 0
      src/views/mobile/exchangeStock/config/search.config1.ts
  20. 13 17
      src/views/mobile/exchangeStock/index.vue
  21. 99 0
      src/views/mobile/shopStock/config/_details.ts
  22. 33 0
      src/views/mobile/shopStock/config/_rules.ts
  23. 56 21
      src/views/mobile/shopStock/config/content.config.ts
  24. 95 0
      src/views/mobile/shopStock/config/content.config1.ts
  25. 1 1
      src/views/mobile/shopStock/config/modal.config.ts
  26. 31 0
      src/views/mobile/shopStock/config/search.config1.ts
  27. 176 0
      src/views/mobile/shopStock/cpns/addModel.vue
  28. 88 0
      src/views/mobile/shopStock/cpns/ladder-table.vue
  29. 11 0
      src/views/mobile/shopStock/cpns/utils/create-basic-title.ts
  30. 27 0
      src/views/mobile/shopStock/cpns/utils/types.ts
  31. 138 36
      src/views/mobile/shopStock/index.vue
  32. 7 0
      src/views/mobile/user/index.vue

+ 18 - 0
src/api/export.ts

@@ -0,0 +1,18 @@
+import { http } from "../utils/http";
+import { loadEnv } from "@build/index";
+
+const { VITE_PROXY_USER_REAL } = loadEnv();
+
+interface postType extends Promise<any> {
+  data?: object;
+  code?: number;
+  message?: string;
+}
+
+//导出
+export const httpExport = (url: string, data?: object): postType => {
+  return http.request("post", `${VITE_PROXY_USER_REAL}admin/${url}`, {
+    data,
+    responseType: "blob"
+  });
+};

+ 12 - 28
src/api/mobile/exchangeOrder.ts

@@ -5,43 +5,27 @@ const { VITE_PROXY_DOMAIN_REAL } = loadEnv();
 
 //获取数据
 export async function httpList(): Promise<DataType<Menu[]>> {
-  return http.request(
-    `post`,
-    `${VITE_PROXY_DOMAIN_REAL}admin/orderServiceList`,
-    {
-      data: {}
-    }
-  );
+  return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/orderList`, {
+    data: {}
+  });
 }
 // 详情
 export async function httpDetail(data: object = {}): Promise<DataType<any>> {
-  return http.request(
-    "post",
-    `${VITE_PROXY_DOMAIN_REAL}admin/orderServiceRead`,
-    {
-      data
-    }
-  );
+  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/orderRead`, {
+    data
+  });
 }
 
 //发货
 export async function httpDeliver(): Promise<DataType<Menu[]>> {
-  return http.request(
-    `post`,
-    `${VITE_PROXY_DOMAIN_REAL}admin/orderServiceDeliver`,
-    {
-      data: {}
-    }
-  );
+  return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/orderDeliver`, {
+    data: {}
+  });
 }
 
 //导出
 export async function httpExport(data: object): Promise<DataType<Menu[]>> {
-  return http.request(
-    `post`,
-    `${VITE_PROXY_DOMAIN_REAL}admin/orderServiceExport`,
-    {
-      data
-    }
-  );
+  return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/orderExport`, {
+    data
+  });
 }

+ 3 - 1
src/components/PageContent/src/actions/index.ts

@@ -5,6 +5,7 @@ import Preview from "./action-preview";
 import Status from "./action-status";
 import ResetPwd from "./action-resetPwd";
 import ChangePwd from "./action-changePwd";
+import Export from "./action-export";
 import Log from "./action-log";
 const Operation = {
   Create,
@@ -14,7 +15,8 @@ const Operation = {
   Status,
   ResetPwd,
   ChangePwd,
-  Log
+  Log,
+  Export
 };
 
 export { Operation };

+ 0 - 1
src/components/PageContent/src/page-content.tsx

@@ -156,7 +156,6 @@ const PageConent = defineComponent({
         contentConfig
         // , powers
       } = props;
-      // console.log(powers);
       // const { columns } = contentConfig;
 
       return (

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

@@ -56,7 +56,8 @@ export type ActionType =
   | "status"
   | "resetPwd"
   | "changePwd"
-  | "log";
+  | "log"
+  | "export";
 
 export interface ContentApis {
   httpAdd?: API;

+ 169 - 0
src/components/PageListModall/columns.tsx

@@ -0,0 +1,169 @@
+import { ref } from "vue";
+import dayjs from "dayjs";
+import { GOOD_OPTIONS } from "/@/config/status";
+import { renderImage, renderStatus } from "/@/utils/column-helper";
+// import { send_status_list } from "/@/utils/status";
+export function useColumns() {
+  const columns = ref([
+    {
+      type: "selection",
+      width: 30
+    },
+    {
+      label: "商品编号",
+      prop: "good_code",
+      width: 160,
+      showOverflowTooltip: true
+    },
+    {
+      label: "商品类型",
+      prop: "type",
+      width: 85,
+      showOverflowTooltip: true,
+      ...renderStatus(GOOD_OPTIONS, "type")
+    },
+    {
+      label: "图片",
+      prop: "good_cover_img",
+      width: 60,
+      showOverflowTooltip: true,
+      ...renderImage("good_cover_img")
+    },
+    {
+      label: "商品名称",
+      prop: "good_name",
+      minWidth: 160
+    },
+    {
+      label: "单位",
+      prop: "unit",
+      width: 80,
+      showOverflowTooltip: true
+    },
+    {
+      label: "起订量",
+      prop: "moq",
+      width: 80,
+      showOverflowTooltip: true
+    },
+    {
+      label: "步长",
+      prop: "step",
+      width: 80,
+      showOverflowTooltip: true
+    },
+    {
+      label: "售价",
+      prop: "price",
+      width: 110,
+      showOverflowTooltip: true
+    }
+  ]);
+
+  return {
+    columns
+  };
+}
+
+export const order_detail_columns = [
+  {
+    field: "sequenceNo",
+    label: "确认单编号"
+  },
+  {
+    field: "ownerName",
+    label: "销售员"
+  },
+  {
+    field: "department",
+    label: "平台名称"
+  },
+  {
+    field: "companyName",
+    label: "业务公司名称"
+  },
+  {
+    field: "customerName",
+    label: "客户名称"
+  },
+  {
+    field: "goodNum",
+    label: "商品数量"
+  },
+  {
+    field: "goodPrice",
+    label: "商品单价"
+  },
+  {
+    field: "goodName",
+    label: "商品名称"
+  },
+
+  {
+    field: "inv_fee",
+    label: "开票中"
+  },
+  {
+    field: "ainv_fee",
+    label: "已开票"
+  },
+  {
+    field: "winv_num",
+    label: "未开票数量"
+  },
+  {
+    field: "winv_fee",
+    label: "未开票"
+  }
+];
+
+/**
+ * @invoice_addr 公司注册地址
+ * @invoice_people  法人
+ * @invoice_mobile 联系方式
+ * @invoice_code 纳税识别号
+ * @invoice_bank 开户行
+ * @invoice_bankNo 开户账户
+ */
+export const convertInvoiceTitle = (title: Record<string, string>) => {
+  const { company_address, mobile, company_license, bank_name, bankNo } = title;
+
+  return {
+    invoice_addr: company_address,
+    invoice_mobile: mobile,
+    invoice_code: company_license,
+    invoice_bank: bank_name,
+    invoice_bankNo: bankNo
+  };
+};
+
+export const convertInvoiceTitleData = (title: Record<string, string>) => {
+  const {
+    invoice_addr,
+    invoice_mobile,
+    invoice_code,
+    invoice_bank,
+    invoice_bankNo
+  } = title;
+
+  return {
+    invoice_code,
+    addrAndmobile: invoice_addr + " " + invoice_mobile,
+    bankAndBankNo: invoice_bank + " " + invoice_bankNo
+  };
+};
+
+export const invoice_columns = [
+  {
+    label: "纳税人识别号",
+    field: "invoice_code"
+  },
+  {
+    label: "地址、电话",
+    field: "addrAndmobile"
+  },
+  {
+    label: "开户行及账号",
+    field: "bankAndBankNo"
+  }
+];

+ 3 - 0
src/components/PageListModall/index.ts

@@ -0,0 +1,3 @@
+import pageListModal from "./pageListModal.vue";
+
+export default pageListModal;

+ 52 - 0
src/components/PageListModall/pageListModal.vue

@@ -0,0 +1,52 @@
+<script setup lang="ts">
+import { computed, ref } from "vue";
+import { PageContent } from "/@/components/PageContent";
+import { PageSearch, usePageSearch } from "/@/components/PageSearch";
+import { modalProps } from "./types";
+// import type { PageContentInstance } from "/@/components/PageContent";
+const { handleResetClick, handleSearchClick } = usePageSearch();
+const props = defineProps(modalProps);
+const { modalConfig } = props;
+const { title, searchConfig, contentConfig } = modalConfig;
+const pageContentRef = ref<InstanceType<typeof PageContent>>(null);
+// const emit = defineEmits(["confirmBtnClick"]);
+
+const dialogVisible = ref(false);
+
+async function show(_group_id) {
+  dialogVisible.value = true;
+  console.log(pageContentRef);
+  pageContentRef.value.getPageData({ id: _group_id });
+}
+defineExpose({
+  show
+});
+</script>
+
+<template>
+  <el-dialog
+    :title="title"
+    v-model="dialogVisible"
+    center
+    top="8vh"
+    destroy-on-close
+    width="1040px"
+  >
+    <PageSearch
+      :form-config="searchConfig"
+      @search-btn-click="handleSearchClick"
+      @reset-btn-click="handleResetClick"
+    />
+    <PageContent ref="pageContentRef" :content-config="contentConfig" />
+  </el-dialog>
+</template>
+
+<style lang="scss" scoped>
+:deep(.el-pagination) {
+  justify-content: flex-start !important;
+}
+
+.search {
+  padding: 0px !important;
+}
+</style>

+ 26 - 0
src/components/PageListModall/search.config.ts

@@ -0,0 +1,26 @@
+import { FormConfig } from "/@/components/PageSearch";
+// import { INV_OPEN_STATUS } from "/@/utils/details/inv-open";
+
+const searchFormConfig: FormConfig = {
+  colLayout: { span: 8 },
+  formItems: [
+    {
+      field: "status",
+      type: "input",
+      placeholder: "发票申请状态",
+      options: []
+    },
+    {
+      field: "inv_type",
+      type: "select",
+      placeholder: "发票类型"
+    },
+    {
+      field: "customer",
+      type: "input",
+      placeholder: "客户名称"
+    }
+  ]
+};
+
+export default searchFormConfig;

+ 41 - 0
src/components/PageListModall/types.ts

@@ -0,0 +1,41 @@
+import pageModal from "./page-modal.vue";
+import { FormConfig as searchFormConfig } from "/@/components/PageSearch";
+import { ContentConfig } from "/@/components/PageContent";
+
+export type PageModalInstance = typeof pageModal & {
+  dialogVisible: boolean;
+  // confirmLoading: boolean;
+  // type: ActionType;
+};
+
+export interface ModalConfig {
+  title: string;
+  searchConfig?: searchFormConfig;
+  contentConfig?: ContentConfig;
+}
+
+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
+  }
+};

+ 5 - 9
src/views/interest/account/resetPassword.vue → src/components/resetPassword.vue

@@ -4,7 +4,6 @@ import { ElMessage, FormInstance, FormRules } from "element-plus";
 import { reactive, ref, watch, nextTick } from "vue";
 import { useNav } from "/@/layout/hooks/useNav";
 import { isAlphanumeric, isnumber, validAlphabets } from "/@/utils/validate";
-
 const { logout } = useNav();
 const formSize = ref("default");
 const ruleFormRef = ref<FormInstance>();
@@ -43,12 +42,11 @@ const rules = reactive<FormRules>({
         if (value === "") {
           callback(new Error("新密码不能为空!"));
         } else {
-          if (isnumber(value) && value.length > 5 && value.length < 19) {
+          if (isnumber(value)) {
             callback();
           } else {
-            callback(new Error("新密码为6-16位数字!"));
+            callback(new Error("新密码只能能为纯数字!"));
           }
-
           // if (!isAlphanumeric(value)) {
           //   callback(new Error("新密码为6-16位数字字母组合!"));
           // } else if (value.length < 6 || value.length > 16) {
@@ -91,7 +89,7 @@ const submitForm = async (formEl: FormInstance | undefined) => {
       if (loading.value === true) return;
       loading.value = true;
       let model = Object.assign({}, ruleForm);
-      model.id = id.value;
+      model.id = "36";
       const { code, message } = await httpChangePwd(model);
       loading.value = false;
       if (code === 0) {
@@ -125,14 +123,12 @@ const closeDialog = () => {
 };
 
 const loading = ref(true);
-const titleType = ref("");
 async function initForm() {
   loading.value = true;
-  titleType.value = "修改密码";
 
   await resetForm(ruleFormRef.value);
 
-  console.log(ruleForm);
+  // console.log(ruleForm);
   loading.value = false;
 }
 watch(
@@ -157,7 +153,7 @@ watch(
     v-model="showModelThis"
     append-to-body
     :width="'900px'"
-    :title="titleType"
+    title="修改密码"
     v-loading="loading"
     @close="closeDialog"
   >

+ 3 - 0
src/components/resetPwd/index.ts

@@ -0,0 +1,3 @@
+import pageListModal from "./pageListModal.vue";
+
+export default pageListModal;

+ 63 - 0
src/components/resetPwd/pageListModal.vue

@@ -0,0 +1,63 @@
+<script setup lang="ts">
+import { ref, unref } from "vue";
+import { BasicForm, FormItem } from "/@/components/BasicForm";
+import { modalProps } from "./types";
+
+const props = defineProps(modalProps);
+const { title, api, formItems, formGroup } = props;
+const emit = defineEmits(["confirmBtnClick"]);
+
+const formData = ref({});
+
+const formRef = ref<InstanceType<typeof BasicForm>>(null);
+const dialogVisible = ref(false);
+const confirmLoading = ref(false);
+
+function handleConfirmClick() {
+  console.log(formData.value);
+  formRef.value.validate(async isVaild => {
+    //表单校验通过派发事件
+    if (isVaild) {
+      const { code, data, message } = await api(unref(formData));
+      if (code === 0) {
+        emit("confirmBtnClick");
+      } else {
+        console.log("989");
+      }
+    }
+  });
+}
+
+defineExpose({
+  dialogVisible,
+  confirmLoading
+});
+</script>
+
+<template>
+  <el-dialog
+    :title="title"
+    v-model="dialogVisible"
+    center
+    destroy-on-close
+    width="1040px"
+  >
+    <!-- 表单 -->
+    <BasicForm
+      ref="formRef"
+      v-bind="modalConfig"
+      v-model:form-data="formData"
+    />
+
+    <!-- 保存/重置 -->
+    <div class="flex justify-end">
+      <el-button
+        type="primary"
+        :loading="confirmLoading"
+        @click="handleConfirmClick"
+        >保存</el-button
+      >
+      <el-button @click="dialogVisible = false">关闭</el-button>
+    </div>
+  </el-dialog>
+</template>

+ 30 - 0
src/components/resetPwd/types.ts

@@ -0,0 +1,30 @@
+import pageModal from "./page-modal.vue";
+import { FormGorup, FormItem } from "/@/components/BasicForm";
+
+interface ContentApiResponse {
+  code: number;
+  message: string;
+  data: any;
+}
+
+type API = (data: any) => Promise<ContentApiResponse>;
+
+export type PageModalInstance = typeof pageModal & {
+  dialogVisible: boolean;
+  // confirmLoading: boolean;
+  // type: ActionType;
+};
+
+export interface ModalConfig {
+  title: string;
+  api: API;
+  formItems: Array<FormItem>;
+  formGroup: Array<FormGorup>;
+}
+
+export const modalProps = {
+  modalConfig: {
+    type: Object as PropType<ModalConfig>,
+    required: true
+  }
+};

+ 128 - 0
src/utils/export.ts

@@ -0,0 +1,128 @@
+import { ElMessage } from "element-plus";
+import { utils, writeFile } from "xlsx";
+import { httpExport } from "/@/api/export";
+import { responseHandle } from "./responseHandle";
+
+type Options<T> = {
+  //导出方式 http(网络请求) front(纯前端导出)
+  type: "front" | "http";
+  //type为http时需要url作为请求url
+  url?: string;
+  //type未http时请求的参数
+  params?: any;
+  //type为front时 需要传入导出的数据
+  data?: T[];
+  //ttpe为front时 需要传入导出的列
+  columns?: any[];
+  //导出文件名
+  name?: string;
+};
+
+//要排除的列
+const EXCLUDE_COLUMNS = ["序号", "操作"];
+
+//纯前端导出
+function frontEndExport<T>(
+  _options: Pick<Options<T>, "data" | "columns" | "name">
+) {
+  const { data, columns, name } = _options;
+
+  if (!data || !columns) return;
+  if (data.length === 0) return ElMessage.warning("请打开勾选列并勾选导出数据");
+
+  //生成表数据
+  const result = generatorResult({ data, columns });
+  const titleColumns: string[] = columns
+    .map(({ label }) => label)
+    .filter(label => label && !EXCLUDE_COLUMNS.includes(label));
+  result.unshift(titleColumns);
+
+  //生成表
+  const workBook = utils.book_new();
+  const workSheet = utils.aoa_to_sheet(result);
+
+  utils.book_append_sheet(workBook, workSheet, "sheet1");
+
+  //导出
+  writeFile(workBook, name);
+}
+
+//配合后端文件流导出
+async function httpRequsetExport<T>(
+  _options: Pick<Options<T>, "url" | "name" | "params">
+) {
+  if (!_options.url) return;
+
+  const { code, message, data } = await httpExport(_options.url, {
+    data: _options.params
+  });
+
+  function handler() {
+    const url = window.URL.createObjectURL(
+      //todo:blob对象类型
+      new Blob([data], {
+        type: ""
+      })
+    );
+
+    //创建a标签 执行下载
+    const link = document.createElement("a");
+    link.style.display = "none";
+    link.href = url;
+    link.setAttribute("download", _options.name);
+
+    //删除a标签 释放url
+    document.appendChild(link);
+    link.click();
+    link.remove();
+    window.URL.revokeObjectURL(url);
+  }
+
+  responseHandle({
+    code,
+    handler,
+    message,
+    logout: () => {
+      console.log("todo:登出");
+    }
+  });
+}
+
+function generatorResult<T>({
+  data,
+  columns
+}: Pick<Options<T>, "data" | "columns">): string[][] {
+  return data.map(item => {
+    const row: string[] = [];
+
+    for (let i = 0; i < columns.length; i++) {
+      const { prop, transform } = columns[i];
+
+      if (!prop) continue;
+
+      //存在transform时执行转换数据
+      const colData = transform ? transform(item[prop]) : item[prop];
+      row.push(colData);
+    }
+
+    return row;
+  });
+}
+
+export function exportPageContent<T = any>({
+  type,
+  url,
+  columns,
+  data,
+  name: _name
+}: Options<T>) {
+  const name = _name ? _name : "导出数据.xlsx";
+  switch (type) {
+    case "front":
+      frontEndExport({ data, columns, name });
+      break;
+    case "http":
+      httpRequsetExport({ url, name });
+      break;
+  }
+}

+ 1 - 1
src/views/interest/account/index.vue

@@ -10,7 +10,7 @@ import { httpDetail } from "/@/api/interest/account";
 import type { PageContentInstance } from "/@/components/PageContent";
 import { useResponseHandle } from "/@/hooks/useAsync";
 const pageContentRef = ref<PageContentInstance | null>(null);
-import resetPassword from "./resetPassword.vue";
+import resetPassword from "/@/components/resetPassword.vue";
 const pageName = "account";
 const {
   pageModalRef,

+ 3 - 9
src/views/mobile/exchangeOrder/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/exchangeOrder";
 import { renderStatus, renderImage } from "/@/utils/column-helper";
 import { ORDER_OPTIONS } from "/@/config/status";
-import { ElTag } from "element-plus";
 
 const columns = [
   {
@@ -33,11 +30,7 @@ const columns = [
     label: "卡类型",
     width: "100px"
   },
-  {
-    prop: "name",
-    label: "客户名称",
-    width: "100px"
-  },
+
   {
     prop: "username",
     label: "账号/卡号",
@@ -108,8 +101,9 @@ const columns = [
   }
 ];
 const contentConfig: ContentConfig = {
-  title: "兑换商品订单管理",
+  title: "订单管理",
   columns,
+  showExpand: row => row.child.length > 0,
   apis: {
     httpList
   },

+ 95 - 0
src/views/mobile/exchangeStock/config/content.config1.ts

@@ -0,0 +1,95 @@
+// import { ModalConfig } from "/@/components/PageListModal2";
+import { httpLog } from "/@/api/mobile/exchangeStock";
+import { renderImage } from "/@/utils/column-helper";
+const columns = [
+  {
+    type: "selection",
+    width: 55,
+    hide: ({ checkList }) => !checkList.includes("勾选列")
+  },
+  // {
+  //   prop: "id",
+  //   label: "ID"
+  // },
+
+  {
+    prop: "account_username",
+    label: "账户"
+  },
+  {
+    prop: "account_name",
+    label: "账户姓名"
+  },
+  {
+    prop: "good_code",
+    label: "商品编码",
+    width: 160
+  },
+  {
+    label: "图片",
+    prop: "good_cover_img",
+    width: 60,
+    showOverflowTooltip: true,
+    ...renderImage("good_cover_img")
+  },
+  {
+    label: "商品名称",
+    prop: "good_name",
+    minWidth: 160
+  },
+  {
+    prop: "inventory",
+    label: "库存数",
+    width: "110px"
+  },
+  {
+    label: "单位",
+    prop: "unit",
+    width: 80,
+    showOverflowTooltip: true
+  },
+  {
+    label: "起订量",
+    prop: "moq",
+    width: 80,
+    showOverflowTooltip: true
+  },
+  {
+    label: "步长",
+    prop: "step",
+    width: 80,
+    showOverflowTooltip: true
+  },
+  {
+    label: "售价",
+    prop: "price",
+    width: 110,
+    showOverflowTooltip: true
+  },
+
+  {
+    prop: "updatetime",
+    label: "更新时间",
+    width: "160px"
+  },
+
+  {
+    label: "操作",
+    fixed: "right",
+    width: 120,
+    slot: "operation"
+  }
+];
+const contentConfig = {
+  title: "兑换商品",
+  searchConfig: { formItems: [] },
+  contentConfig: {
+    title: "卡类型管理2",
+    columns,
+    apis: {
+      httpList: httpLog
+    }
+  }
+};
+
+export default contentConfig;

+ 31 - 0
src/views/mobile/exchangeStock/config/search.config1.ts

@@ -0,0 +1,31 @@
+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: "video_name",
+      type: "input",
+      placeholder: "视频名称"
+    },
+    {
+      field: "video_url",
+      type: "input",
+      placeholder: "视频地址"
+    },
+    {
+      field: "video_sn",
+      type: "input",
+      placeholder: "视频编号"
+    }
+  ]
+};
+
+export default searchFormConfig;

+ 13 - 17
src/views/mobile/exchangeStock/index.vue

@@ -1,4 +1,5 @@
 <script setup lang="ts">
+import { ref, unref } from "vue";
 import { PageSearch, usePageSearch } from "/@/components/PageSearch";
 import searchConfig from "./config/search.config";
 import contentConfig from "./config/content.config";
@@ -14,34 +15,29 @@ import {
   transform,
   createDefaultData
 } from "/@/components/BasicForm";
-import { ref, unref } from "vue";
+
 import addModel from "./cpns/addModel.vue";
-// import dayjs from "dayjs";
 import { useResponseHandle } from "/@/hooks/useAsync";
-// import OrderDialog from "/@/components/PageListModal";
 import LadderModal from "./cpns/ladder-modal.vue";
 import LadderTable from "./cpns/ladder-table.vue";
 import { ComCard } from "/@/components/RemoteSelect";
 import OrderDialog from "/@/components/PageListModal";
 import { ElForm, ElMessage } from "element-plus";
+import PageListModall from "/@/components/PageListModall";
+import contentConfig1 from "./config/content.config1";
+
 const responseHandle = useResponseHandle();
 const ladderModalRef = ref<InstanceType<typeof LadderModal>>(null);
 const pageContentRef = ref<PageContentInstance | null>(null);
 const modelRef = ref<InstanceType<typeof OrderDialog>>(null);
 const actionModalRef = ref<InstanceType<typeof addModel>>(null);
-const {
-  pageModalRef,
-  handleUpdateData,
-  handleCreateData,
-  handlePreviewData,
-  handleConfrim,
-  defaultInfo
-} = usePageModal({
-  pageContentRef
-});
+const { pageModalRef, handleCreateData, handleConfrim, defaultInfo } =
+  usePageModal({
+    pageContentRef
+  });
 const { handleResetClick, handleSearchClick } = usePageSearch();
 const { formItems } = projectFormConfig;
-// const modelRef = ref<InstanceType<typeof OrderDialog>>(null);
+const PageListModalReff = ref<InstanceType<typeof PageListModall>>(null);
 const basicFormRef = ref<InstanceType<typeof ElForm>>(null);
 const formData = ref<Record<string, any>>(createDefaultData(formItems));
 function handleCreate() {
@@ -68,8 +64,6 @@ function handleCreate() {
       ElMessage.warning("库存数不能为空!");
       return;
     }
-    // console.log(list);
-    // const params = unref(formData);
 
     handleConfrim("create", params);
     // emit("create", params);
@@ -104,7 +98,8 @@ function handleAddOrder(list) {
   });
 }
 function aa(id) {
-  console.log(id);
+  PageListModalReff.value.show(id);
+  // console.log(id);
 }
 </script>
 
@@ -123,6 +118,7 @@ function aa(id) {
     @update-btn-click="({ id }) => handleDetailData(id, 'update')"
     @log-btn-click="({ id }) => aa(id)"
   />
+  <PageListModal2 ref="PageListModalReff" :modal-config="contentConfig1" />
   <PageModal
     ref="pageModalRef"
     :modal-config="modalConfig"

+ 99 - 0
src/views/mobile/shopStock/config/_details.ts

@@ -0,0 +1,99 @@
+/* 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 {
+  renderStatus,
+  renderImage,
+  renderImages
+} from "/@/utils/column-helper";
+// import { payWayOptions, sendWayOptions, supplyAreaOptions } from "./_options";
+
+export const projectFormConfig: FormConfig = {
+  labelWidth: "100px",
+  formItems: [
+    {
+      label: "商品信息",
+      field: "list",
+      type: "array",
+      placeholder: "商品信息",
+      span: 24,
+      slot: "list"
+    }
+  ]
+};
+
+export const bargainColumns: DescriptionColumns = [
+  {
+    field: "good_cover_img",
+    label: "封面图",
+    span: 4,
+    render: (_, row) => renderImage("good_cover_img").cellRenderer({ row })
+  },
+  {
+    field: "good_name",
+    label: "商品名称",
+    span: 20
+  },
+  {
+    field: "good_code",
+    label: "商品编码",
+    span: 6
+  },
+  {
+    field: "unit",
+    label: "单位",
+    span: 6
+  },
+  {
+    field: "moq",
+    label: "起订量",
+    span: 6
+  },
+  {
+    field: "step",
+    label: "步长",
+    span: 6
+  },
+  {
+    field: "price",
+    label: "售价",
+    span: 8
+  },
+  {
+    field: "inventory",
+    label: "当前库存数",
+    span: 8
+  },
+  {
+    field: "updatetime",
+    label: "更新时间",
+    span: 8
+  },
+
+  {
+    field: "good_banner_img",
+    label: "轮播图",
+    span: 12
+    // render: (_, row) => renderImages("good_banner_img").cellRenderer({ row })
+  },
+  {
+    field: "good_img",
+    label: "详情图",
+    // render: (_, row) => renderImages("good_img").cellRenderer({ row }),
+    span: 12
+  },
+  {
+    field: "good_param",
+    label: "商品参数",
+    span: 12
+  },
+  {
+    field: "good_remark",
+    label: "商品备注",
+    span: 12
+  }
+];

+ 33 - 0
src/views/mobile/shopStock/config/_rules.ts

@@ -0,0 +1,33 @@
+import { FormRules } from "element-plus";
+
+export const ladderFormRules: FormRules = {
+  key: {
+    trigger: "change",
+    required: true,
+    message: "请选择商品类型"
+  },
+  value: {
+    trigger: "change",
+    required: true,
+    message: "请选择单位"
+  }
+};
+
+export const projectFormRules: FormRules = {
+  number: {
+    trigger: "change",
+    required: true,
+    validator(_, value) {
+      if (value === "") return new Error("请输入库存变动数");
+      return true;
+    }
+  },
+  flag: {
+    trigger: "change",
+    required: true,
+    validator(_, value) {
+      if (value.length === 0) return new Error("请选择修改状态!");
+      return true;
+    }
+  }
+};

+ 56 - 21
src/views/mobile/shopStock/config/content.config.ts

@@ -1,11 +1,17 @@
 import { isString } from "@pureadmin/utils";
 import { h } from "vue";
 import { ContentConfig } from "/@/components/PageContent";
-import { httpList } from "/@/api/mobile/shopStock";
-import { renderStatus } from "/@/utils/column-helper";
+import {
+  // httpDelete,
+  // httpStatus,
+  httpList,
+  httpAdd,
+  httpLog,
+  httpUpdate
+} from "/@/api/mobile/shopStock";
 import { STATUS_OPTIONS } from "/@/config/status";
 import { ElTag } from "element-plus";
-
+import { renderImage } from "/@/utils/column-helper";
 const columns = [
   {
     type: "selection",
@@ -13,30 +19,56 @@ const columns = [
     hide: ({ checkList }) => !checkList.includes("勾选列")
   },
   {
-    prop: "id",
-    label: "ID",
-    width: "70px"
+    prop: "good_code",
+    label: "商品编码",
+    width: 160
+  },
+  {
+    label: "图片",
+    prop: "good_cover_img",
+    width: 60,
+    showOverflowTooltip: true,
+    ...renderImage("good_cover_img")
+  },
+  {
+    label: "商品名称",
+    prop: "good_name",
+    minWidth: 160
+  },
+  {
+    prop: "inventory",
+    label: "库存数",
+    width: "110px"
+  },
+  {
+    label: "单位",
+    prop: "unit",
+    width: 80,
+    showOverflowTooltip: true
   },
   {
-    prop: "status",
-    label: "状态",
-    minWidth: "90px",
-    ...renderStatus(STATUS_OPTIONS)
+    label: "起订量",
+    prop: "moq",
+    width: 80,
+    showOverflowTooltip: true
   },
   {
-    prop: "video_name",
-    label: "视频名称",
-    minWidth: "250px"
+    label: "步长",
+    prop: "step",
+    width: 80,
+    showOverflowTooltip: true
   },
   {
-    prop: "remark",
-    label: "视频描述"
+    label: "售价",
+    prop: "price",
+    width: 110,
+    showOverflowTooltip: true
   },
 
   {
-    prop: "addtime",
-    label: "创建时间",
-    minWidth: "160px"
+    prop: "updatetime",
+    label: "更新时间",
+    width: "160px"
   },
 
   {
@@ -47,12 +79,15 @@ const columns = [
   }
 ];
 const contentConfig: ContentConfig = {
-  title: "商城商品库存管理",
+  title: "商城商品库存",
   columns,
   apis: {
-    httpAdd: true,
+    httpAdd,
+    // httpDelete,
+    // httpStatus,
     httpList,
-    httpUpdate: true
+    httpLog,
+    httpUpdate
   }
 };
 

+ 95 - 0
src/views/mobile/shopStock/config/content.config1.ts

@@ -0,0 +1,95 @@
+// import { ModalConfig } from "/@/components/PageListModal2";
+import { httpLog } from "/@/api/mobile/shopStock";
+import { renderImage } from "/@/utils/column-helper";
+const columns = [
+  {
+    type: "selection",
+    width: 55,
+    hide: ({ checkList }) => !checkList.includes("勾选列")
+  },
+  // {
+  //   prop: "id",
+  //   label: "ID"
+  // },
+
+  {
+    prop: "account_username",
+    label: "账户"
+  },
+  {
+    prop: "account_name",
+    label: "账户姓名"
+  },
+  {
+    prop: "good_code",
+    label: "商品编码",
+    width: 160
+  },
+  {
+    label: "图片",
+    prop: "good_cover_img",
+    width: 60,
+    showOverflowTooltip: true,
+    ...renderImage("good_cover_img")
+  },
+  {
+    label: "商品名称",
+    prop: "good_name",
+    minWidth: 160
+  },
+  {
+    prop: "inventory",
+    label: "库存数",
+    width: "110px"
+  },
+  {
+    label: "单位",
+    prop: "unit",
+    width: 80,
+    showOverflowTooltip: true
+  },
+  {
+    label: "起订量",
+    prop: "moq",
+    width: 80,
+    showOverflowTooltip: true
+  },
+  {
+    label: "步长",
+    prop: "step",
+    width: 80,
+    showOverflowTooltip: true
+  },
+  {
+    label: "售价",
+    prop: "price",
+    width: 110,
+    showOverflowTooltip: true
+  },
+
+  {
+    prop: "updatetime",
+    label: "更新时间",
+    width: "160px"
+  },
+
+  {
+    label: "操作",
+    fixed: "right",
+    width: 120,
+    slot: "operation"
+  }
+];
+const contentConfig = {
+  title: "兑换商品",
+  searchConfig: { formItems: [] },
+  contentConfig: {
+    title: "卡类型管理2",
+    columns,
+    apis: {
+      httpList: httpLog
+    }
+  }
+};
+
+export default contentConfig;

+ 1 - 1
src/views/mobile/shopStock/config/modal.config.ts

@@ -2,7 +2,7 @@ import { ModalConfig } from "/@/components/PageModal/src/types";
 import { isLicense } from "/@/utils/validate";
 
 const modalConfig: ModalConfig = {
-  title: "视频",
+  title: "商城商品库存",
   colLayout: { span: 24 },
   itemStyle: {},
   contact: "invoice_mobile",

+ 31 - 0
src/views/mobile/shopStock/config/search.config1.ts

@@ -0,0 +1,31 @@
+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: "video_name",
+      type: "input",
+      placeholder: "视频名称"
+    },
+    {
+      field: "video_url",
+      type: "input",
+      placeholder: "视频地址"
+    },
+    {
+      field: "video_sn",
+      type: "input",
+      placeholder: "视频编号"
+    }
+  ]
+};
+
+export default searchFormConfig;

+ 176 - 0
src/views/mobile/shopStock/cpns/addModel.vue

@@ -0,0 +1,176 @@
+<script setup lang="ts">
+import { computed, ref, watchEffect, reactive, unref } from "vue";
+import { ActionType } from "/@/components/PageContent";
+import { createBasicTitle } from "./utils/create-basic-title";
+import BasicDescriptions from "/@/components/BasicDescriptions";
+import { ElForm, ElMessage } from "element-plus";
+import type { FormInstance, FormRules } from "element-plus";
+import { projectFormRules } from "../config/_rules";
+import { FLAG_OPTIONS } from "/@/config/status";
+import { useNav } from "/@/layout/hooks/useNav";
+import { bargainColumns } from "../config/_details";
+const { logout } = useNav();
+import { httpAdd, httpDetail, httpUpdate } from "/@/api/mobile/shopStock";
+const emit = defineEmits(["submitOk"]);
+const ruleFormRef = ref<FormInstance>();
+const form = {
+  id: "",
+  number: 1,
+  flag: "1"
+};
+const ruleForm = reactive({ ...form });
+const type = ref<ActionType>("preview");
+const dialogVisible = ref(false);
+const confirmLoading = ref(false);
+const title = ref("");
+const uID = ref("");
+const bargain = ref({});
+
+const submitForm = async (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  await formEl.validate(async (valid, fields) => {
+    if (valid) {
+      if (confirmLoading.value) return;
+      confirmLoading.value = true;
+      const model = unref(ruleForm);
+      const { flag, number } = model;
+      const { inventory } = bargain;
+      if (flag === "-1") {
+        if (Number(number) > Number(inventory)) {
+          ElMessage.warning("减少库存操作时,变动库存不能大于当前库存!");
+          return;
+        }
+      }
+      let res = {};
+      if (type.value == "create") {
+        delete model["id"];
+        res = await httpAdd(model);
+      } else {
+        res = await httpUpdate(model);
+      }
+      const { code: hcode, data, message } = res;
+      confirmLoading.value = false;
+      if (hcode === 0) {
+        dialogVisible.value = false;
+        emit("submitOk", {});
+      } else if (hcode >= 100 && hcode <= 104) {
+        logout();
+      } else {
+        ElMessage.warning(message);
+      }
+    } else {
+      console.log("error submit!", fields);
+    }
+    handleAddOrder;
+  });
+};
+
+function handleAddOrder(list) {
+  console.log(list);
+}
+const initData = async () => {
+  if (confirmLoading.value) return;
+  confirmLoading.value = true;
+  const { code, data, message } = await httpDetail({ id: uID.value });
+  if (code === 0) {
+    bargain.value = data;
+    const { id } = data;
+    ruleForm.id = id;
+  } else if (code >= 100 && code <= 104) {
+    logout();
+  } else {
+    ElMessage.warning(message);
+  }
+  confirmLoading.value = false;
+};
+defineExpose({
+  onShow: async (basicTitle: string, readonly: ActionType, id: string) => {
+    type.value = readonly;
+    const readTitle = createBasicTitle(type.value);
+    title.value =
+      readonly == "preview" ? basicTitle + readTitle : readTitle + basicTitle;
+    Object.keys(ruleForm).forEach(key => {
+      ruleForm[key] = form[key];
+    });
+    dialogVisible.value = true;
+    confirmLoading.value = false;
+    uID.value = id;
+    bargain.value = {};
+    if (type.value !== "create") {
+      await initData();
+    }
+  }
+});
+</script>
+
+<template>
+  <el-dialog
+    :title="title"
+    v-model="dialogVisible"
+    center
+    top="5vh"
+    destroy-on-close
+    width="1024px"
+  >
+    <BasicDescriptions
+      labelWidth="120"
+      v-if="bargain && bargain?.id"
+      :columns="bargainColumns"
+      :data="bargain"
+    />
+    <el-form
+      ref="ruleFormRef"
+      v-loading="confirmLoading"
+      :model="ruleForm"
+      v-show="type !== 'preview'"
+      :rules="projectFormRules"
+      label-width="100px"
+      :disabled="type === 'preview'"
+      status-icon
+    >
+      <el-row style="padding: 20px 0 0 0">
+        <el-col :span="8">
+          <el-form-item label="变动状态" prop="flag">
+            <el-select
+              v-model="ruleForm.flag"
+              placeholder="变动状态"
+              style="width: 100%"
+            >
+              <el-option
+                v-for="(item, index) in FLAG_OPTIONS"
+                :label="item.label"
+                :value="item.id"
+                :key="item.id + index"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="变动数量" prop="number">
+            <el-input-number
+              v-model="ruleForm.number"
+              :step="1"
+              :min="1"
+              :precision="0"
+              style="width: 100%"
+              :max="99999999"
+              value-on-clear="min"
+              controls-position="right"
+              step-strictly
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item>
+            <div class="w-full flex justify-end">
+              <el-button type="primary" @click="submitForm(ruleFormRef)"
+                >提交</el-button
+              >
+              <ElButton @click="() => (dialogVisible = false)">取消</ElButton>
+            </div>
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+  </el-dialog>
+</template>

+ 88 - 0
src/views/mobile/shopStock/cpns/ladder-table.vue

@@ -0,0 +1,88 @@
+<script setup lang="ts">
+import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
+import { GOOD_OPTIONS } from "/@/config/status";
+const emit = defineEmits(["choose", "delete", "update"]);
+
+defineProps<{
+  ladder: Record<string, any>[];
+  readonly: boolean;
+}>();
+</script>
+
+<template>
+  <ElTable size="small" border :data="ladder" max-height="500px">
+    <ElTableColumn prop="name" label="顺序" width="110px" fixed="left">
+      <template #="{ $index }">
+        {{ $index + 1 }}
+      </template>
+    </ElTableColumn>
+
+    <ElTableColumn prop="type" label="商品类型" width="110px">
+      <template #="{ row }">
+        <ElTag>{{
+          GOOD_OPTIONS.find(({ id }) => id === row.type + "")?.label || "--"
+        }}</ElTag>
+      </template>
+    </ElTableColumn>
+    <ElTableColumn prop="good_cover_img" width="60" label="图片">
+      <template #="{ row }">
+        <ElImage
+          :src="row.good_cover_img"
+          fit="cover"
+          lazy
+          :preview-src-list="
+            row.good_cover_img !== '' ? [row.good_cover_img] : []
+          "
+          z-index="99999"
+          preview-teleported
+        />
+      </template>
+    </ElTableColumn>
+    <ElTableColumn prop="good_name" label="商品名称" />
+    <ElTableColumn prop="inventory" label="添加库存数" width="150px">
+      <template #="{ row }">
+        <el-input-number
+          v-model="row.inventory"
+          :step="1"
+          :min="0"
+          :precision="0"
+          size="small"
+          :max="99999999"
+          value-on-clear="min"
+          controls-position="right"
+          step-strictly
+        />
+      </template>
+    </ElTableColumn>
+    <ElTableColumn prop="unit" label="单位" width="80px" />
+    <ElTableColumn prop="moq" label="起订量" width="80px" />
+    <ElTableColumn prop="step" label="步长" width="80px" />
+    <ElTableColumn prop="price" label="售价" width="110px" />
+    <!-- v-if="!readonly" -->
+    <ElTableColumn width="80px" fixed="right">
+      <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('delete', $index)"
+          >删除</ElButton
+        >
+      </template>
+    </ElTableColumn>
+  </ElTable>
+</template>

+ 11 - 0
src/views/mobile/shopStock/cpns/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];
+}

+ 27 - 0
src/views/mobile/shopStock/cpns/utils/types.ts

@@ -0,0 +1,27 @@
+import { ActionType } from "/@/components/PageContent";
+import pageModal from "../addModel.vue";
+
+export type PageModalInstance = typeof pageModal & {
+  dialogVisible: boolean;
+  confirmLoading: boolean;
+  type: ActionType;
+  title: String;
+};
+export const modalProps = {
+  dialogVisible: {
+    type: Boolean,
+    required: Boolean
+  },
+  confirmLoading: {
+    type: Boolean,
+    default: false
+  },
+  type: {
+    type: Object as PropType<ActionType>,
+    required: true
+  },
+  title: {
+    type: String,
+    required: true
+  }
+};

+ 138 - 36
src/views/mobile/shopStock/index.vue

@@ -1,55 +1,157 @@
 <script setup lang="ts">
-import { usePageSearch } from "/@/components/PageSearch";
+import { ref, unref } 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 PageAuth from "/@/components/PageAuth";
+import { PageModal, usePageModal } from "/@/components/PageModalShell";
 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 { projectFormConfig } from "./config/_details";
+import { projectFormRules } from "./config/_rules";
+import {
+  BasicForm,
+  transform,
+  createDefaultData
+} from "/@/components/BasicForm";
 
-const pageName = "stock";
-const basePath = "/sellOut/projectDetail";
-// , handleResetClick, handleSearchClick
-const { pageContentRef } = usePageSearch();
-const { push } = useRouter();
-const hooks: Hooks = {
-  pageSearchHook: () => usePageSearch(undefined, undefined, searchConfig)
-};
-const {
-  pageModalRef,
-  // handleUpdateData,
-  handleCreateData,
-  handlePreviewData,
-  handleConfrim,
-  defaultInfo
-} = usePageModal({ pageContentRef });
-const events: Events = {
-  content: {
-    preview: row => handlePreviewData(row),
-    create: () => {
-      console.log("1111");
+import addModel from "./cpns/addModel.vue";
+import { useResponseHandle } from "/@/hooks/useAsync";
+import LadderModal from "./cpns/ladder-modal.vue";
+import LadderTable from "./cpns/ladder-table.vue";
+import { ComCard } from "/@/components/RemoteSelect";
+import OrderDialog from "/@/components/PageListModal";
+import { ElForm, ElMessage } from "element-plus";
+import PageListModall from "/@/components/PageListModall";
+import contentConfig1 from "./config/content.config1";
+
+const responseHandle = useResponseHandle();
+const ladderModalRef = ref<InstanceType<typeof LadderModal>>(null);
+const pageContentRef = ref<PageContentInstance | null>(null);
+const modelRef = ref<InstanceType<typeof OrderDialog>>(null);
+const actionModalRef = ref<InstanceType<typeof addModel>>(null);
+const { pageModalRef, handleCreateData, handleConfrim, defaultInfo } =
+  usePageModal({
+    pageContentRef
+  });
+const { handleResetClick, handleSearchClick } = usePageSearch();
+const { formItems } = projectFormConfig;
+const PageListModalReff = ref<InstanceType<typeof PageListModall>>(null);
+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 { group_id, list } = formData.value;
+    const params = {
+      group_id,
+      list: []
+    };
+    let isok = true;
+    list.forEach(item => {
+      const num = Number(item.inventory ?? "");
+      const model = {
+        good_id: item.id,
+        inventory: num
+      };
+      params.list.push(model);
+      if (num === 0) {
+        isok = false;
+      }
+    });
+    if (!isok) {
+      ElMessage.warning("库存数不能为空!");
+      return;
+    }
+
+    handleConfrim("create", params);
+    // emit("create", params);
+  });
+}
+function Create() {
+  pageContentRef.value.getPageData({ id: "" });
+}
+async function handleDetailData(id, type) {
+  actionModalRef.value.onShow("兑换商品库存", type, id);
+}
+function modularShow() {
+  // if (!formData.value.group_id) return ElMessage.warning("请选择公司卡类型!");
+  modelRef.value.show("", "2");
+}
+function handleAddOrder(list) {
+  console.log(list);
+  list.forEach(item => {
+    const { id } = item;
+    let findex = formData.value.list.findIndex(e => e.id + "" == id + "");
+    if (findex == -1) {
+      let model = Object.assign(item, {
+        img: item.good_cover_img,
+        good_id: item.id,
+        jump_type: "2",
+        jump_param: `/good?id=${item.id}`,
+        style_type: "",
+        title: ""
+      });
+      formData.value.list.push(model);
     }
-  }
-};
+  });
+}
+function aa(id) {
+  console.log(PageListModalReff);
+  PageListModalReff.value.show(id);
+  // console.log(id);
+}
 </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="({ id }) => handleDetailData(id, 'preview')"
+    @update-btn-click="({ id }) => handleDetailData(id, 'update')"
+    @log-btn-click="({ id }) => aa(id)"
   />
+  <PageListModal2 ref="PageListModalReff" :modal-config="contentConfig1" />
   <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 #list>
+        <LadderTable
+          :readonly="false"
+          :ladder="formData.list"
+          @choose="() => modularShow()"
+          @update="({ data, index }) => ladderModalRef.onDisplay(data, index)"
+          @delete="index => formData.list.splice(index, 1)"
+        />
+      </template>
+      <template #footer>
+        <div class="w-full flex justify-end">
+          <ElButton type="primary" @click="handleCreate">保存</ElButton>
+        </div>
+      </template>
+    </BasicForm>
+  </PageModal>
+
+  <OrderDialog ref="modelRef" @save-btn-click="handleAddOrder" />
+  <addModel ref="actionModalRef" @submitOk="Create" />
   <!-- </PageAuth> -->
 </template>

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

@@ -13,6 +13,7 @@ import { httpDetail } from "/@/api/mobile/user";
 import { projectFormConfig } from "./config/_details";
 import { projectFormRules } from "./config/_rules";
 import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
+// import resetPassword from "/@/components/resetPassword.vue";
 
 import {
   BasicForm,
@@ -160,5 +161,11 @@ function videoChange(e) {
       </template>
     </BasicForm>
   </PageModal>
+  <!-- <reset-password
+    :itemId="passwordModelId"
+    :show-model="passwordModel"
+    @refresh="passwordModel = false"
+    @cancel="passwordModel = false"
+  /> -->
   <!-- </PageAuth> -->
 </template>