Browse Source

代理系统

liu_lake 6 months ago
parent
commit
881861d2bf

+ 7 - 0
admin-ui/src/constants/constants.ts

@@ -89,3 +89,10 @@ export const payStatusOptions: SelectOption<number>[] = [
   { label: "支付成功", value: 1 },
   { label: "退款", value: 2 }
 ];
+/**
+ * 是否绑定
+ */
+export const totpOptions: SelectOption<number>[] = [
+  { label: "已绑定", value: 1 },
+  { label: "未绑定", value: 0 }
+];

+ 1 - 1
admin-ui/src/views/order/edit.vue

@@ -1,6 +1,6 @@
 <script setup lang="ts">
 import { reactive, ref } from "vue";
-import * as $api from "@/api/agent/index";
+import * as $api from "@/api/order/index";
 import { message } from "@/utils/message";
 import type { FormInstance } from "element-plus";
 import { cloneDeep } from "@pureadmin/utils";

+ 47 - 0
agent-ui/src/api/channel/index.ts

@@ -0,0 +1,47 @@
+import { Result, deleteRequest, get, post, put } from "../base";
+
+/**
+ * 分页查询
+ * @param query .
+ * @returns .
+ */
+export function queryPage<T>(query?: any): Promise<Result<T>> {
+  return get("/agent/pay/channel/page",  query);
+}
+
+/**
+ * 列表查询
+ * @param query .
+ * @returns .
+ */
+export function queryList<T>(query?: any): Promise<Result<T>> {
+  return get("/agent/pay/channel/list",  query);
+}
+
+/**
+ * 新增
+ * @param data .
+ * @returns .
+ */
+export function save<T>(data: any): Promise<Result<T>> {
+  return post("/agent/pay/channel/save", data);
+}
+
+/**
+ * 更新
+ * @param id .
+ * @param data .
+ * @returns  .
+ */
+export function update<T>(id: string, data: any): Promise<Result<T>> {
+  return put(`/agent/pay/channel/update`, {}, data);
+}
+
+/**
+ * 删除用户
+ * @param userIds .
+ * @returns  .
+ */
+export function del<T>(channelId: string): Promise<Result<T>> {
+  return deleteRequest(`/agent/pay/channel/remove/`+ channelId);
+}

+ 6 - 6
agent-ui/src/api/merchant/index.ts

@@ -15,7 +15,7 @@ export function queryPage<T>(query?: any): Promise<Result<T>> {
  * @returns .
  */
 export function queryList<T>(query?: any): Promise<Result<T>> {
-  return get("agent/pay/merchant/list", query);
+  return get("/agent/pay/merchant/list", query);
 }
 
 /**
@@ -24,7 +24,7 @@ export function queryList<T>(query?: any): Promise<Result<T>> {
  * @returns .
  */
 export function save<T>(data: any): Promise<Result<T>> {
-  return post("agent/pay/merchant/save", data);
+  return post("/agent/pay/merchant/save", data);
 }
 
 /**
@@ -34,14 +34,14 @@ export function save<T>(data: any): Promise<Result<T>> {
  * @returns  .
  */
 export function update<T>(id: string, data: any): Promise<Result<T>> {
-  return put(`agent/pay/merchant/update/${id}`, {}, data);
+  return put(`/agent/pay/merchant/update/${id}`, {}, data);
 }
 
 /**
  * 删除用户
- * @param userIds .
+ * @param merchantId .
  * @returns  .
  */
-export function del<T>(userIds: string[]): Promise<Result<T>> {
-  return deleteRequest(`agent/pay/merchant/remove`, {}, userIds);
+export function del<T>(merchantId: string): Promise<Result<T>> {
+  return deleteRequest(`/agent/pay/merchant/remove/`+ merchantId);
 }

+ 69 - 0
agent-ui/src/api/order/index.ts

@@ -0,0 +1,69 @@
+import { Result, deleteRequest, get, post, put } from "../base";
+
+/**
+ * 分页查询
+ * @param query .
+ * @returns .
+ */
+export function queryPage<T>(query?: any): Promise<Result<T>> {
+  return get("/agent/pay/order/page", query);
+}
+
+/**
+ * 列表查询
+ * @param query .
+ * @returns .
+ */
+export function queryList<T>(query?: any): Promise<Result<T>> {
+  return get("/agent/pay/order/list", query);
+}
+
+/**
+ * 新增
+ * @param data .
+ * @returns .
+ */
+export function save<T>(data: any): Promise<Result<T>> {
+  return post("/agent/pay/order/save", data);
+}
+
+/**
+ * 更新
+ * @param id .
+ * @param data .
+ * @returns  .
+ */
+export function update<T>(id: string, data: any): Promise<Result<T>> {
+  return put(`/agent/pay/order/update/${id}`, {}, data);
+}
+
+/**
+ * 删除用户
+ * @param userIds .
+ * @returns  .
+ */
+export function del<T>(userIds: string[]): Promise<Result<T>> {
+  return deleteRequest(`/agent/pay/order/remove`, {}, userIds);
+}
+
+
+/**
+ * 查询支付状态
+ * @param id .
+ * @returns  .
+ */
+export function queryPayStatus<T>(id: string): Promise<Result<T>> {
+  return get(`/agent/pay/order/status/${id}`,{});
+}
+
+
+
+
+/**
+ * 订单回调
+ * @param id .
+ * @returns  .
+ */
+export function orderCallback<T>(id: string): Promise<Result<T>> {
+  return get(`/agent/pay/order/callback/${id}`,{});
+}

+ 13 - 0
agent-ui/src/constants/constants.ts

@@ -83,3 +83,16 @@ export const configTypeMap: SelectOptionMap<string> = {
   1: "系统配置",
   2: "业务配置"
 };
+
+export const payStatusOptions: SelectOption<number>[] = [
+  { label: "支付失败", value: -1 },
+  { label: "待支付", value: 0 },
+  { label: "支付成功", value: 1 },
+  { label: "退款", value: 2 }
+];
+
+
+export const totpOptions: SelectOption<number>[] = [
+  { label: "已绑定", value: 1 },
+  { label: "未绑定", value: 0 }
+];

+ 19 - 0
agent-ui/src/views/channel/index.vue

@@ -0,0 +1,19 @@
+<script setup lang="ts">
+import { reactive } from "vue";
+import list from "./modules/list.vue";
+
+defineOptions({
+  name: "platformManage"
+});
+const pageData: any = reactive({
+  mode: "table"
+});
+</script>
+
+<template>
+  <el-card :shadow="'never'">
+    <template #default>
+      <list :mode="pageData.mode" />
+    </template>
+  </el-card>
+</template>

+ 230 - 0
agent-ui/src/views/channel/modules/edit.vue

@@ -0,0 +1,230 @@
+<script setup lang="ts">
+import { reactive, ref } from "vue";
+import * as $api from "@/api/channel/index";
+import { message } from "@/utils/message";
+import type { FormInstance } from "element-plus";
+import { cloneDeep } from "@pureadmin/utils";
+import {enableOptions} from "@/constants/constants";
+
+const title = "";
+defineOptions({ name: "templateEdit" });
+const isDetail = ref(false);
+const formRef = ref<FormInstance>();
+// 初始化数据
+const initData = {
+  serviceId: undefined,
+  privateKey: undefined,
+  publicKey: undefined,
+  status: 1
+};
+
+// 表单校验规则
+const formRules = {};
+
+// 页面数据
+const pageData: any = reactive({
+  name: false,
+  code: false,
+  appId: false,
+  privateKey: false,
+  publicKey: false,
+  astrictAmount: false,
+  astrictTrade: false,
+  rate: false,
+  status: false,
+  title: "",
+  formLoading: false,
+  mode: "add",
+  isUpdate: false,
+  // 表单数据
+  formData: initData,
+  formRules: formRules
+});
+// 暴露给父级调用
+const emits = defineEmits(["ok", "close"]);
+// 打开弹窗
+const open = (data: any, dataSource: any, mode: string) => {
+  pageData.formData = cloneDeep(data) || initData;
+  if (mode === "edit") {
+    pageData.title = `${title} - 编辑`;
+    isDetail.value = false;
+  } else if (mode === "detail") {
+    pageData.title = `${title} - 查看`;
+    isDetail.value = true;
+  } else {
+    pageData.title = `${title} - 新增`;
+    isDetail.value = false;
+  }
+  pageData.dataSource = dataSource;
+  pageData.isUpdate = !!pageData.formData.id;
+  pageData.dialogVisible = true;
+};
+// 关闭弹窗
+const handleClose = () => {
+  pageData.dialogVisible = false;
+  emits("close");
+};
+// 确定并关闭弹窗
+const handleConfirm = () => {
+  formRef.value!.validate((isValid: boolean) => {
+    if (isValid) {
+      const { id } = pageData.formData;
+      if (id) {
+        _update();
+      } else {
+        _save();
+      }
+    } else {
+      message("表单校验失败", { type: "warning" });
+    }
+  });
+};
+const _save = () => {
+  pageData.formLoading = true;
+  const _data = cloneDeep(pageData.formData);
+  $api
+    .save(_data)
+    .then((res: any) => {
+      if (res.success) {
+        _confirm();
+      } else {
+        message(res.message, { type: "warning" });
+      }
+    })
+    .finally(() => {
+      pageData.formLoading = false;
+    });
+};
+const _update = () => {
+  pageData.formLoading = true;
+  const _data = cloneDeep(pageData.formData);
+  $api
+    .update(pageData.formData.id, _data)
+    .then((res: any) => {
+      if (res.success) {
+        _confirm();
+      } else {
+        message(res.message, { type: "warning" });
+      }
+    })
+    .finally(() => {
+      pageData.formLoading = false;
+    });
+};
+const _confirm = () => {
+  pageData.dialogVisible = false;
+  emits("ok");
+};
+defineExpose({ open });
+</script>
+
+<template>
+  <el-dialog v-model="pageData.dialogVisible" destroy-on-close :width="500">
+    <template #header>
+      <el-text class="mx-1" type="primary" size="large">{{
+        pageData.title
+      }}</el-text>
+    </template>
+    <div class="el-dialog-content">
+      <el-form
+        ref="formRef"
+        :model="pageData.formData"
+        style="width: 90%; margin: 20px auto 0"
+        label-width="auto"
+        :rules="pageData.formRules"
+        :loading="pageData.formLoading"
+      >
+        <el-form-item label="名称" prop="userName">
+          <el-input
+            v-model="pageData.formData.name"
+            clearable
+            placeholder="请输入名称"
+            size="small"
+            :readonly="isDetail"
+          />
+        </el-form-item>
+        <el-form-item label="编码" prop="password">
+          <el-input
+            v-model="pageData.formData.code"
+            clearable
+            placeholder="请输入编码"
+            size="small"
+            :readonly="isDetail"
+          />
+        </el-form-item>
+        <el-form-item label="appId" prop="password">
+          <el-input
+            v-model="pageData.formData.appId"
+            clearable
+            placeholder="请输入appId"
+            size="small"
+            :readonly="isDetail"
+          />
+        </el-form-item>   <el-form-item label="密钥" prop="password">
+          <el-input
+            v-model="pageData.formData.privateKey"
+            clearable
+            placeholder="请输入密钥"
+            size="small"
+            :readonly="isDetail"
+          />
+        </el-form-item>
+        <el-form-item label="公钥" prop="password">
+          <el-input
+            v-model="pageData.formData.publicKey"
+            clearable
+            placeholder="请输入公钥"
+            size="small"
+            :readonly="isDetail"
+          />
+        </el-form-item>        <el-form-item label="单笔限制金额" prop="password">
+          <el-input
+            v-model="pageData.formData.astrictAmount"
+            clearable
+            placeholder="请输入单笔限制金额"
+            size="small"
+            :readonly="isDetail"
+          />
+        </el-form-item>
+        <el-form-item label="限制流水" prop="password">
+          <el-input
+            v-model="pageData.formData.astrictTrade"
+            clearable
+            placeholder="请输入限制流水"
+            size="small"
+            :readonly="isDetail"
+          />
+        </el-form-item>
+        <el-form-item label="统一费率" prop="password">
+          <el-input
+            v-model="pageData.formData.rate"
+            clearable
+            placeholder="请输入统一费率"
+            size="small"
+            :readonly="isDetail"
+          />
+        </el-form-item>
+        <el-form-item label="状态" prop="password">
+          <el-select
+              v-model="pageData.formData.status"
+              clearable
+              placeholder="请选择状态"
+          >
+            <el-option
+                v-for="item in enableOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+    </div>
+    <template #footer>
+      <el-button v-if="!isDetail" @click="handleClose">取消</el-button>
+      <el-button v-if="!isDetail" type="primary" @click="handleConfirm"
+        >确认</el-button
+      >
+    </template>
+  </el-dialog>
+</template>

+ 391 - 0
agent-ui/src/views/channel/modules/list.vue

@@ -0,0 +1,391 @@
+<script setup lang="ts">
+import FormSearch, { type FormField } from "@/components/opts/form-search.vue";
+import TableButtons from "@/components/opts/btns2.vue";
+import Edit from "./edit.vue";
+import { PureTable } from "@pureadmin/table";
+import { computed, onBeforeMount, onMounted, reactive, ref, watch } from "vue";
+import * as $api from "@/api/channel/index";
+import { hasAuth } from "@/router/utils";
+import message from "@/utils/message";
+import { enableOptions } from "@/constants/constants";
+import { cloneDeep } from "@pureadmin/utils";
+
+const editRef = ref();
+
+defineOptions({
+  name: "channelList"
+});
+
+const props: any = defineProps({
+  mode: {
+    required: false,
+    type: String,
+    default: "table"
+  }
+});
+
+const searchFormFields = computed((): FormField[] => {
+  const fields: FormField[] = [
+
+    {
+      type: "select",
+      label: "状态",
+      prop: "status",
+      placeholder: "请选择",
+      dataSourceKey: "enableOptions",
+      options: {
+        keys: {
+          label: "label",
+          value: "value",
+          prop: "value"
+        },
+        filterable: true
+      }
+    }
+  ];
+  if (props.mode === "table") {
+    return fields;
+  } else {
+    return fields;
+  }
+});
+
+const pageData: any = reactive({
+  mode: "table",
+  permission: {
+  },
+  searchParam: {
+    searchState: true,
+    searchForm: {}
+  },
+  dataSource: {
+    enableOptions: enableOptions
+  },
+  /*按钮 */
+  btnOpts: {
+    size: "small",
+    leftBtns: [
+      {
+        key: "add",
+        label: "新增",
+        type: "primary",
+        icon: "ep:plus",
+        state: true
+      }
+    ],
+    rightBtns: [
+      {
+        key: "search",
+        label: "查询",
+        icon: "ep:search",
+        state: true,
+        options: {
+          circle: true
+        }
+      },
+      {
+        key: "refresh",
+        label: "刷新",
+        icon: "ep:refresh",
+        state: true,
+        options: {
+          circle: true
+        }
+      }
+    ]
+  },
+  tableParam: {
+    list: [],
+    columns: [
+      {
+        label: "ID",
+        prop: "id",
+        slot: "id",
+        hidden:true,
+        width: 220
+      },
+      {
+        label: "通道名称",
+        prop: "name",
+        slot: "name"
+      },
+      {
+        label: "编码",
+        prop: "code",
+        slot: "code"
+      },
+      {
+        label: "appId",
+        prop: "appId",
+        slot: "appId"
+      },
+      {
+        label: "密钥",
+        prop: "privateKey",
+        slot: "privateKey"
+      },
+      {
+        label: "公钥",
+        prop: "publicKey",
+        slot: "publicKey"
+      },
+      {
+        label: "单笔限制金额",
+        prop: "astrictAmount",
+        slot: "astrictAmount"
+      },
+      {
+        label: "限制流水",
+        prop: "astrictTrade",
+        slot: "astrictTrade"
+      },
+      {
+        label: "统一费率",
+        prop: "rate",
+        slot: "rate"
+      },
+      {
+        label: "状态",
+        prop: "status",
+        slot: "enableOptions"
+      },
+      {
+        label: "更新时间",
+        prop: "updateTime",
+        slot: "updateTime"
+      },
+      {
+        label: "操作",
+        fixed: "right",
+        slot: "operation"
+      }
+    ],
+    loading: false,
+    pagination: {
+      small: true,
+      pageSize: 10,
+      defaultPageSize: 10,
+      currentPage: 1,
+      background: true,
+      total: 0
+    }
+  }
+});
+
+const btnClickHandle = (val: string) => {
+  switch (val) {
+    case "add":
+      editRef.value!.open({ enable: 1 }, pageData.dataSource, "add");
+      break;
+    case "update":
+      break;
+    case "search":
+      _updateSearchState();
+      break;
+    case "refresh":
+      _loadData();
+      break;
+    case "switch":
+      break;
+    default:
+      break;
+  }
+};
+
+/**
+ *  更新搜索表单
+ * @param data .
+ */
+const _updateSearchFormData = (data: any) => {
+  pageData.searchParam.searchForm = data;
+};
+/**
+ * 点击搜索按钮
+ */
+const _searchForm = (data: any) => {
+  pageData.searchParam.searchForm = data;
+  _loadData();
+};
+/**
+ * 重置
+ */
+const _resetSearchForm = (data?: any) => {
+  pageData.searchParam.searchForm = data;
+};
+/**
+ * 更新搜索表达的状态
+ */
+const _updateSearchState = () => {
+  pageData.searchParam.searchState = !pageData.searchParam.searchState;
+};
+/**
+ * 分页 - 改变每页条数
+ * @param val .
+ */
+const handleChangePageSize = (val: any) => {
+  pageData.tableParam.pagination.pageSize = val;
+  _loadData();
+};
+/**
+ * 分页 - 改变页码
+ * @param val .
+ */
+const handleChangeCurrentPage = (val: any) => {
+  pageData.tableParam.pagination.currentPage = val;
+  _loadData();
+};
+/**
+ * 获取查询参数
+ */
+const getQueryParams = () => {
+  const sqp = {};
+  const param = Object.assign(sqp, pageData.searchParam.searchForm);
+  param.current = pageData.tableParam.pagination.currentPage;
+  param.size = pageData.tableParam.pagination.pageSize;
+  return param;
+};
+/**
+ * 获取列表数据
+ * @param page .
+ */
+const _loadData = (page?: number) => {
+  const query = getQueryParams();
+  if (page) {
+    query.current = page;
+  }
+  pageData.tableParam.loading = true;
+  $api
+    .queryPage(query)
+    .then((res: any) => {
+      if (res.success) {
+        pageData.tableParam.list = res.result.records;
+        pageData.tableParam.pagination.total = Number(res.result.total);
+      }
+    })
+    .finally(() => {
+      pageData.tableParam.loading = false;
+    });
+};
+/**
+ * 查看详情
+ * @param row .
+ */
+const handleDetail = (row: any) => {
+  editRef.value!.open(cloneDeep(row), pageData.dataSource, "detail");
+};
+/**
+ * 编辑
+ * @param row .
+ */
+const handleEdit = (row: any) => {
+  editRef.value!.open(cloneDeep(row), pageData.dataSource, "edit");
+};
+/**
+ * 删除
+ * @param row .
+ */
+const handleDel = (row: any) => {
+  message.confirm(`确认删除 id 为 (${row.id}) 的数据?`).then(() => {
+    $api.del(row.id).then((res: any) => {
+      if (res.success) {
+        message.success("删除成功");
+        _loadData();
+      } else {
+        message.warning(res.message);
+      }
+    });
+  });
+};
+/**
+ * 批量删除
+ * @param ids .
+ */
+const batchDel = (ids: string[]) => {
+  if (ids && ids.length > 0) {
+    $api.del(ids).then((res: any) => {
+      if (res.success) {
+        message.success("删除成功");
+        _loadData();
+      } else {
+        message.warning(res.message);
+      }
+    });
+  }
+};
+watch(
+  () => props.orgInfo,
+  val => {
+    if (val) {
+      _loadData();
+    }
+  }
+);
+onBeforeMount(() => {});
+onMounted(() => {
+  _loadData(1);
+});
+</script>
+
+<template>
+  <div>
+    <form-search
+      size="small"
+      :show="pageData.searchParam.searchState"
+      :form-field="searchFormFields"
+      :data-source="pageData.dataSource"
+      :query-permission="pageData.permission.query"
+      @search-form="_updateSearchFormData"
+      @search="_searchForm"
+      @reset="_resetSearchForm"
+    />
+    <!--operate-->
+    <table-buttons
+      :size="pageData.btnOpts.size"
+      :left-btns="pageData.btnOpts.leftBtns"
+      :right-btns="pageData.btnOpts.rightBtns"
+      @click="btnClickHandle"
+    />
+    <!--table-->
+    <pure-table
+      :data="pageData.tableParam.list"
+      :columns="pageData.tableParam.columns"
+      row-key="id"
+      size="small"
+      border
+      stripe
+      :header-row-class-name="'table-header'"
+      :loading="pageData.tableParam.loading"
+      :pagination="pageData.tableParam.pagination"
+      @page-current-change="handleChangeCurrentPage"
+      @page-size-change="handleChangePageSize"
+    >
+      <template #ellipsis="{ row, column }">
+        <el-tooltip placement="top-start" :content="row[column.property]"
+          >{{ row[column.property] }}
+        </el-tooltip>
+      </template>
+      <template #enableOptions="scope">
+        <el-tag v-if="scope.row.status==1">启用</el-tag>
+        <el-tag v-if="scope.row.status==0">禁用</el-tag>
+      </template>
+      <template #operation="{ row }">
+        <div class="flex justify-center items-center">
+          <el-link
+            type="primary"
+            @click="handleEdit(row)"
+            >编辑
+          </el-link>
+          <el-divider
+            direction="vertical"
+          />
+          <el-link
+            type="primary"
+            @click="handleDel(row)"
+            >删除
+          </el-link>
+        </div>
+      </template>
+    </pure-table>
+    <edit ref="editRef" @ok="_loadData" />
+  </div>
+</template>

+ 10 - 1
agent-ui/src/views/merchant/modules/edit.vue

@@ -124,7 +124,7 @@ defineExpose({ open });
         :rules="pageData.formRules"
         :loading="pageData.formLoading"
       >
-        <el-form-item label="代理名称" prop="userName">
+        <el-form-item label="商户名称" prop="userName">
           <el-input
             v-model="pageData.formData.userName"
             clearable
@@ -133,6 +133,15 @@ defineExpose({ open });
             :readonly="isDetail"
           />
         </el-form-item>
+        <el-form-item label="费率" prop="userName">
+          <el-input-number style="width: 355px"
+            v-model="pageData.formData.rate"
+            clearable
+            placeholder="请输入费率"
+            size="small"
+            :readonly="isDetail"
+          />
+        </el-form-item>
         <el-form-item label="密码" prop="password">
           <el-input
             v-model="pageData.formData.password"

+ 27 - 18
agent-ui/src/views/merchant/modules/list.vue

@@ -7,7 +7,7 @@ import { computed, onBeforeMount, onMounted, reactive, ref, watch } from "vue";
 import * as $api from "@/api/merchant/index";
 import { hasAuth } from "@/router/utils";
 import message from "@/utils/message";
-import { enableOptions } from "@/constants/constants";
+import {enableOptions, totpOptions} from "@/constants/constants";
 import { cloneDeep } from "@pureadmin/utils";
 
 const editRef = ref();
@@ -28,9 +28,9 @@ const searchFormFields = computed((): FormField[] => {
   const fields: FormField[] = [
     {
       type: "input",
-      label: "代理商名称",
-      prop: "agentname",
-      placeholder: "请输入代理商名模糊查询"
+      label: "商名称",
+      prop: "userName",
+      placeholder: "请输入商模糊查询"
     },
     {
       type: "select",
@@ -58,17 +58,14 @@ const searchFormFields = computed((): FormField[] => {
 const pageData: any = reactive({
   mode: "table",
   permission: {
-    query: ["user:query"],
-    save: ["user:save"],
-    update: ["user:update"],
-    del: ["user:del"]
   },
   searchParam: {
     searchState: true,
     searchForm: {}
   },
   dataSource: {
-    enableOptions: enableOptions
+    enableOptions: enableOptions,
+    totpOptions: totpOptions
   },
   /*按钮 */
   btnOpts: {
@@ -79,8 +76,7 @@ const pageData: any = reactive({
         label: "新增",
         type: "primary",
         icon: "ep:plus",
-        state: true,
-        permission: ["user:save"]
+        state: true
       }
     ],
     rightBtns: [
@@ -114,7 +110,7 @@ const pageData: any = reactive({
         width: 220
       },
       {
-        label: "代理商名称",
+        label: "用户名",
         prop: "userName",
         slot: "userName"
       },
@@ -126,12 +122,12 @@ const pageData: any = reactive({
       {
         label: "谷歌校验器",
         prop: "hasTpop",
-        slot: "hasTpop"
+        slot: "totpOptions"
       },
       {
         label: "状态",
         prop: "status",
-        slot: "status"
+        slot: "enableOptions"
       },
       {
         label: "更新时间",
@@ -270,7 +266,14 @@ const handleEdit = (row: any) => {
  */
 const handleDel = (row: any) => {
   message.confirm(`确认删除 id 为 (${row.id}) 的数据?`).then(() => {
-    batchDel([row.id]);
+    $api.del(row.id).then((res: any) => {
+      if (res.success) {
+        message.success("删除成功");
+        _loadData();
+      } else {
+        message.warning(res.message);
+      }
+    });
   });
 };
 /**
@@ -336,6 +339,15 @@ onMounted(() => {
       @page-current-change="handleChangeCurrentPage"
       @page-size-change="handleChangePageSize"
     >
+
+      <template #enableOptions="scope">
+        <el-tag v-if="scope.row.status==0">禁用</el-tag>
+        <el-tag v-if="scope.row.status==1">启用</el-tag>
+      </template>
+      <template #totpOptions="scope">
+        <el-tag v-if="scope.row.status==0">未绑定</el-tag>
+        <el-tag v-if="scope.row.status==1">已绑定</el-tag>
+      </template>
       <template #ellipsis="{ row, column }">
         <el-tooltip placement="top-start" :content="row[column.property]"
           >{{ row[column.property] }}
@@ -348,17 +360,14 @@ onMounted(() => {
       <template #operation="{ row }">
         <div class="flex justify-center items-center">
           <el-link
-            v-show="hasAuth(pageData.permission.update)"
             type="primary"
             @click="handleEdit(row)"
             >编辑
           </el-link>
           <el-divider
-            v-show="hasAuth(pageData.permission.del)"
             direction="vertical"
           />
           <el-link
-            v-show="hasAuth(pageData.permission.del)"
             type="primary"
             @click="handleDel(row)"
             >删除

+ 155 - 0
agent-ui/src/views/order/edit.vue

@@ -0,0 +1,155 @@
+<script setup lang="ts">
+import { reactive, ref } from "vue";
+import * as $api from "@/api/order/index";
+import { message } from "@/utils/message";
+import type { FormInstance } from "element-plus";
+import { cloneDeep } from "@pureadmin/utils";
+
+const title = "";
+defineOptions({ name: "templateEdit" });
+const isDetail = ref(false);
+const formRef = ref<FormInstance>();
+// 初始化数据
+const initData = {
+  userName: undefined,
+  password: undefined,
+  status: 1
+};
+
+// 表单校验规则
+const formRules = {};
+
+// 页面数据
+const pageData: any = reactive({
+  dialogVisible: false,
+  title: "",
+  formLoading: false,
+  mode: "add",
+  isUpdate: false,
+  // 表单数据
+  formData: initData,
+  formRules: formRules
+});
+// 暴露给父级调用
+const emits = defineEmits(["ok", "close"]);
+// 打开弹窗
+const open = (data: any, dataSource: any, mode: string) => {
+  pageData.formData = cloneDeep(data) || initData;
+  if (mode === "edit") {
+    pageData.title = `${title} - 编辑`;
+    isDetail.value = false;
+  } else if (mode === "detail") {
+    pageData.title = `${title} - 查看`;
+    isDetail.value = true;
+  } else {
+    pageData.title = `${title} - 新增`;
+    isDetail.value = false;
+  }
+  pageData.dataSource = dataSource;
+  pageData.isUpdate = !!pageData.formData.id;
+  pageData.dialogVisible = true;
+};
+// 关闭弹窗
+const handleClose = () => {
+  pageData.dialogVisible = false;
+  emits("close");
+};
+// 确定并关闭弹窗
+const handleConfirm = () => {
+  formRef.value!.validate((isValid: boolean) => {
+    if (isValid) {
+      const { id } = pageData.formData;
+      if (id) {
+        _update();
+      } else {
+        _save();
+      }
+    } else {
+      message("表单校验失败", { type: "warning" });
+    }
+  });
+};
+const _save = () => {
+  pageData.formLoading = true;
+  const _data = cloneDeep(pageData.formData);
+  $api
+    .save(_data)
+    .then((res: any) => {
+      if (res.success) {
+        _confirm();
+      } else {
+        message(res.message, { type: "warning" });
+      }
+    })
+    .finally(() => {
+      pageData.formLoading = false;
+    });
+};
+const _update = () => {
+  pageData.formLoading = true;
+  const _data = cloneDeep(pageData.formData);
+  $api
+    .update(pageData.formData.id, _data)
+    .then((res: any) => {
+      if (res.success) {
+        _confirm();
+      } else {
+        message(res.message, { type: "warning" });
+      }
+    })
+    .finally(() => {
+      pageData.formLoading = false;
+    });
+};
+const _confirm = () => {
+  pageData.dialogVisible = false;
+  emits("ok");
+};
+defineExpose({ open });
+</script>
+
+<template>
+  <el-dialog v-model="pageData.dialogVisible" destroy-on-close :width="500">
+    <template #header>
+      <el-text class="mx-1" type="primary" size="large">{{
+        pageData.title
+      }}</el-text>
+    </template>
+    <div class="el-dialog-content">
+      <el-form
+        ref="formRef"
+        :model="pageData.formData"
+        style="width: 90%; margin: 20px auto 0"
+        label-width="auto"
+        :rules="pageData.formRules"
+        :loading="pageData.formLoading"
+      >
+        <el-form-item label="代理名称" prop="userName">
+          <el-input
+            v-model="pageData.formData.userName"
+            clearable
+            placeholder="请输入名称"
+            size="small"
+            :readonly="isDetail"
+          />
+        </el-form-item>
+        <el-form-item label="密码" prop="password">
+          <el-input
+            v-model="pageData.formData.password"
+            type="password"
+            clearable
+            placeholder="请输入密码"
+            size="small"
+            :readonly="isDetail"
+          />
+        </el-form-item>
+      </el-form>
+    </div>
+    <template #footer>
+      <el-button v-if="!isDetail" @click="handleClose">取消</el-button>
+      <el-button v-if="!isDetail" type="primary" @click="handleConfirm"
+        >确认</el-button
+      >
+    </template>
+  </el-dialog>
+</template>

+ 398 - 0
agent-ui/src/views/order/index.vue

@@ -0,0 +1,398 @@
+<script setup lang="ts">
+import FormSearch, { type FormField } from "@/components/opts/form-search.vue";
+import TableButtons from "@/components/opts/btns2.vue";
+import Edit from "./edit.vue";
+import { PureTable } from "@pureadmin/table";
+import { computed, onBeforeMount, onMounted, reactive, ref, watch } from "vue";
+import * as $api from "@/api/order/index";
+import { hasAuth } from "@/router/utils";
+import message from "@/utils/message";
+import {enableOptions, payStatusOptions} from "@/constants/constants";
+import { cloneDeep } from "@pureadmin/utils";
+
+const editRef = ref();
+
+defineOptions({
+  name: "orderList"
+});
+
+const props: any = defineProps({
+  mode: {
+    required: false,
+    type: String,
+    default: "table"
+  }
+});
+
+const searchFormFields = computed((): FormField[] => {
+  const fields: FormField[] = [
+    {
+      type: "input",
+      label: "订单号",
+      prop: "orderNo",
+      placeholder: "请输入代理商名模糊查询"
+    },    {
+      type: "input",
+      label: "平台订单号",
+      prop: "platformOrderNo",
+      placeholder: "请输入代理商名模糊查询"
+    },
+    {
+      type: "select",
+      label: "状态",
+      prop: "status",
+      placeholder: "请选择",
+      dataSourceKey: "enableOptions",
+      options: {
+        keys: {
+          label: "label",
+          value: "value",
+          prop: "value"
+        },
+        filterable: true
+      }
+    }
+  ];
+  if (props.mode === "table") {
+    return fields;
+  } else {
+    return fields;
+  }
+});
+
+const pageData: any = reactive({
+  mode: "table",
+  permission: {
+    // query: ["user:query"],
+    // save: ["user:save"],
+    // update: ["user:update"],
+    // del: ["user:del"]
+  },
+  searchParam: {
+    searchState: true,
+    searchForm: {}
+  },
+  dataSource: {
+    enableOptions: payStatusOptions
+  },
+  /*按钮 */
+  btnOpts: {
+    size: "small",
+    leftBtns: [
+
+    ],
+    rightBtns: [
+      {
+        key: "search",
+        label: "查询",
+        icon: "ep:search",
+        state: true,
+        options: {
+          circle: true
+        }
+      },
+      {
+        key: "refresh",
+        label: "刷新",
+        icon: "ep:refresh",
+        state: true,
+        options: {
+          circle: true
+        }
+      }
+    ]
+  },
+  tableParam: {
+    list: [],
+    columns: [
+      {
+        label: "ID",
+        prop: "id",
+        slot: "id",
+        width: 220
+      },
+      {
+        label: "订单号",
+        prop: "orderNo",
+        slot: "orderNo"
+      },
+      {
+        label: "平台订单号",
+        prop: "platformOrderNo",
+        slot: "platformOrderNo"
+      },
+      {
+        label: "金额",
+        prop: "amount",
+        slot: "amount"
+      },
+      {
+        label: "手续费",
+        prop: "fee",
+        slot: "fee"
+      },{
+        label: "费率",
+        prop: "rate",
+        slot: "rate"
+      },
+      {
+        label: "状态",
+        prop: "status",
+        slot: "enableOptions"
+      },
+      {
+        label: "更新时间",
+        prop: "updateTime",
+        slot: "updateTime"
+      },
+      {
+        label: "操作",
+        fixed: "right",
+        slot: "operation"
+      }
+    ],
+    loading: false,
+    pagination: {
+      small: true,
+      pageSize: 10,
+      defaultPageSize: 10,
+      currentPage: 1,
+      background: true,
+      total: 0
+    }
+  }
+});
+
+const btnClickHandle = (val: string) => {
+  switch (val) {
+    case "add":
+      editRef.value!.open({ enable: 1 }, pageData.dataSource, "add");
+      break;
+    case "update":
+      break;
+    case "search":
+      _updateSearchState();
+      break;
+    case "refresh":
+      _loadData();
+      break;
+    case "switch":
+      break;
+    default:
+      break;
+  }
+};
+
+/**
+ *  更新搜索表单
+ * @param data .
+ */
+const _updateSearchFormData = (data: any) => {
+  pageData.searchParam.searchForm = data;
+};
+/**
+ * 点击搜索按钮
+ */
+const _searchForm = (data: any) => {
+  pageData.searchParam.searchForm = data;
+  _loadData();
+};
+/**
+ * 重置
+ */
+const _resetSearchForm = (data?: any) => {
+  pageData.searchParam.searchForm = data;
+};
+/**
+ * 更新搜索表达的状态
+ */
+const _updateSearchState = () => {
+  pageData.searchParam.searchState = !pageData.searchParam.searchState;
+};
+/**
+ * 分页 - 改变每页条数
+ * @param val .
+ */
+const handleChangePageSize = (val: any) => {
+  pageData.tableParam.pagination.pageSize = val;
+  _loadData();
+};
+/**
+ * 分页 - 改变页码
+ * @param val .
+ */
+const handleChangeCurrentPage = (val: any) => {
+  pageData.tableParam.pagination.currentPage = val;
+  _loadData();
+};
+/**
+ * 获取查询参数
+ */
+const getQueryParams = () => {
+  const sqp = {};
+  const param = Object.assign(sqp, pageData.searchParam.searchForm);
+  param.current = pageData.tableParam.pagination.currentPage;
+  param.size = pageData.tableParam.pagination.pageSize;
+  return param;
+};
+/**
+ * 获取列表数据
+ * @param page .
+ */
+const _loadData = (page?: number) => {
+  const query = getQueryParams();
+  if (page) {
+    query.current = page;
+  }
+  pageData.tableParam.loading = true;
+  $api
+    .queryPage(query)
+    .then((res: any) => {
+      if (res.success) {
+        pageData.tableParam.list = res.result.records;
+        pageData.tableParam.pagination.total = Number(res.result.total);
+      }
+    })
+    .finally(() => {
+      pageData.tableParam.loading = false;
+    });
+};
+/**
+ * 查看详情
+ * @param row .
+ */
+const handleDetail = (row: any) => {
+  editRef.value!.open(cloneDeep(row), pageData.dataSource, "detail");
+};
+/**
+ * 编辑
+ * @param row .
+ */
+const handleEdit = (row: any) => {
+  editRef.value!.open(cloneDeep(row), pageData.dataSource, "edit");
+};
+const handlePayStatus = (row: any) => {
+    $api.queryPayStatus(row.id).then((res: any) => {
+        if (res.success) {
+            message.success("查询支付状态成功");
+            _loadData();
+        } else {
+            message.warning(res.message);
+        }
+    });
+};
+const handleCallback = (row: any) => {
+    $api.orderCallback(row.id).then((res: any) => {
+        if (res.success) {
+            message.success("回调成功");
+            _loadData();
+        } else {
+            message.warning(res.message);
+        }
+    });
+};
+/**
+ * 删除
+ * @param row .
+ */
+const handleDel = (row: any) => {
+  message.confirm(`确认删除 id 为 (${row.id}) 的数据?`).then(() => {
+    batchDel([row.id]);
+  });
+};
+/**
+ * 批量删除
+ * @param ids .
+ */
+const batchDel = (ids: string[]) => {
+  if (ids && ids.length > 0) {
+    $api.del(ids).then((res: any) => {
+      if (res.success) {
+        message.success("删除成功");
+        _loadData();
+      } else {
+        message.warning(res.message);
+      }
+    });
+  }
+};
+watch(
+  () => props.orgInfo,
+  val => {
+    if (val) {
+      _loadData();
+    }
+  }
+);
+onBeforeMount(() => {});
+onMounted(() => {
+  _loadData(1);
+});
+</script>
+
+<template>
+  <div>
+    <form-search
+      size="small"
+      :show="pageData.searchParam.searchState"
+      :form-field="searchFormFields"
+      :data-source="pageData.dataSource"
+      :query-permission="pageData.permission.query"
+      @search-form="_updateSearchFormData"
+      @search="_searchForm"
+      @reset="_resetSearchForm"
+    />
+    <!--operate-->
+    <table-buttons
+      :size="pageData.btnOpts.size"
+      :left-btns="pageData.btnOpts.leftBtns"
+      :right-btns="pageData.btnOpts.rightBtns"
+      @click="btnClickHandle"
+    />
+    <!--table-->
+    <pure-table
+      :data="pageData.tableParam.list"
+      :columns="pageData.tableParam.columns"
+      row-key="id"
+      size="small"
+      border
+      stripe
+      :header-row-class-name="'table-header'"
+      :loading="pageData.tableParam.loading"
+      :pagination="pageData.tableParam.pagination"
+      @page-current-change="handleChangeCurrentPage"
+      @page-size-change="handleChangePageSize"
+    >
+
+      <template #ellipsis="{ row, column }">
+        <el-tooltip placement="top-start" :content="row[column.property]"
+        >{{ row[column.property] }}
+        </el-tooltip>
+      </template>
+      <template #enableOptions="scope">
+        <el-tag v-if="scope.row.status==-1">支付失败</el-tag>
+        <el-tag v-if="scope.row.status==0">待支付</el-tag>
+        <el-tag v-if="scope.row.status==1">支付成功</el-tag>
+        <el-tag v-if="scope.row.status==2">退款</el-tag>
+      </template>
+      <template #operation="{ row }">
+        <div class="flex justify-center items-center">
+          <el-link
+            type="primary"
+            @click="handlePayStatus(row)"
+          >查询支付状态
+          </el-link>
+          <el-divider
+            direction="vertical"
+          />
+          <el-link
+            type="primary"
+            @click="handleCallback(row)"
+          >回调
+          </el-link>
+        </div>
+      </template>
+    </pure-table>
+    <edit ref="editRef" @ok="_loadData" />
+  </div>
+</template>

+ 7 - 0
merchant-ui/src/constants/constants.ts

@@ -83,3 +83,10 @@ export const configTypeMap: SelectOptionMap<string> = {
   1: "系统配置",
   2: "业务配置"
 };
+
+export const payStatusOptions: SelectOption<number>[] = [
+  { label: "支付失败", value: -1 },
+  { label: "待支付", value: 0 },
+  { label: "支付成功", value: 1 },
+  { label: "退款", value: 2 }
+];