xgj vor 1 Monat
Ursprung
Commit
8d0b9ed51d

+ 4 - 4
src/layouts/components/Header/ToolBarRight.vue

@@ -1,11 +1,11 @@
 <template>
   <div class="tool-bar-ri">
     <div class="header-icon">
-      <AssemblySize id="assemblySize" />
-      <Language id="language" />
-      <SearchMenu id="searchMenu" />
+      <!-- <AssemblySize id="assemblySize" /> -->
+      <!-- <Language id="language" /> -->
+      <!-- <SearchMenu id="searchMenu" /> -->
       <ThemeSetting id="themeSetting" />
-      <Message id="message" />
+      <!-- <Message id="message" /> -->
       <Fullscreen id="fullscreen" />
     </div>
     <span class="username">{{ username }}</span>

+ 9 - 1
src/layouts/components/Header/components/InfoDialog.vue

@@ -1,6 +1,8 @@
 <template>
   <el-dialog v-model="dialogVisible" title="个人信息" width="500px" draggable>
-    <span>This is userInfo</span>
+    <span>
+      <h3>合作机构名称:{{ username }}</h3>
+    </span>
     <template #footer>
       <span class="dialog-footer">
         <el-button @click="dialogVisible = false">取消</el-button>
@@ -11,6 +13,12 @@
 </template>
 
 <script setup lang="ts">
+import { computed } from "vue";
+import { useUserStore } from "@/stores/modules/user";
+
+const userStore = useUserStore();
+const username = computed(() => userStore.userInfo.name);
+
 import { ref } from "vue";
 
 const dialogVisible = ref(false);

+ 85 - 7
src/layouts/components/Header/components/PasswordDialog.vue

@@ -1,22 +1,100 @@
 <template>
-  <el-dialog v-model="dialogVisible" title="修改密码" width="500px" draggable>
-    <span>This is Password</span>
-    <template #footer>
-      <span class="dialog-footer">
+  <el-dialog v-model="dialogVisible" title="修改密码" width="500px" draggable @close="onReset(ruleFormRef)">
+    <el-form ref="ruleFormRef" :model="ruleForm" size="large" label-width="120px">
+      <!-- <el-form-item
+        label="昵称"
+        :rules="[
+          {
+            required: true,
+            message: '请输入昵称',
+            trigger: 'blur'
+          }
+        ]"
+        prop="nickname"
+      >
+        <el-input clearable v-model="ruleForm.nickname" placeholder="请输入昵称" maxlength="10" show-word-limit />
+      </el-form-item> -->
+
+      <el-form-item
+        label="原密码"
+        prop="oldPassword"
+        :rules="[
+          {
+            required: true,
+            message: '请输入原密码',
+            trigger: 'blur'
+          }
+        ]"
+      >
+        <el-input clearable show-password v-model="ruleForm.oldPassword" placeholder="请输入新密码" />
+      </el-form-item>
+
+      <el-form-item
+        prop="password"
+        label="新密码"
+        :rules="[
+          {
+            required: true,
+            message: '请输入新密码',
+            trigger: 'blur'
+          }
+        ]"
+      >
+        <el-input clearable show-password v-model="ruleForm.password" placeholder="密码" />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="onSubmit(ruleFormRef)">确定</el-button>
         <el-button @click="dialogVisible = false">取消</el-button>
-        <el-button type="primary" @click="dialogVisible = false">确认</el-button>
-      </span>
-    </template>
+      </el-form-item>
+    </el-form>
   </el-dialog>
 </template>
 
 <script setup lang="ts">
 import { ref } from "vue";
+import { useUserStore } from "@/stores/modules/user";
+import { ElMessage, type FormInstance } from "element-plus";
+import { LOGIN_URL } from "@/config";
+import { useRouter } from "vue-router";
+
+import request from "@/api";
+
+const router = useRouter();
+const userStore = useUserStore();
 
 const dialogVisible = ref(false);
 const openDialog = () => {
   dialogVisible.value = true;
 };
 
+const ruleForm = ref({
+  password: "",
+  oldPassword: ""
+});
+const ruleFormRef = ref();
+
+const onSubmit = async (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  await formEl.validate((valid, fields) => {
+    if (!valid) return;
+    request.post("/archivesService/agency/update/password", ruleForm.value).then(_ => {
+      ElMessage({
+        type: "success",
+        message: "修改成功"
+      });
+
+      // 2.清除 Token
+      userStore.setToken("");
+
+      // 3.重定向到登陆页
+      router.replace(LOGIN_URL);
+    });
+  });
+};
+const onReset = () => {
+  if (!ruleFormRef.value) return;
+  ruleFormRef.value.resetFields();
+};
+
 defineExpose({ openDialog });
 </script>

+ 18 - 0
src/utils/index.ts

@@ -342,3 +342,21 @@ export const handleDownloadFile = async (response, fileName, params = {}) => {
     throw error; // 可以根据需要抛出错误
   }
 };
+
+/**
+ * 根据对象数组中的某个属性值进行去重
+ * @param array 对象数组,需要去重的数组
+ * @param key 指定根据哪个属性进行去重
+ * @returns 返回去重后的对象数组
+ */
+export const unique = (array, key) => {
+  // 使用Set实现根据属性值的唯一性
+  const _set = [...new Set(array.map(e => e[key]))];
+  const deArray = [];
+  // 根据_set中的属性值,找出原数组中对应的项
+  _set.map(item => {
+    deArray.push(array[array.findIndex(val => val[key] === item)]);
+  });
+  // 返回去重后的数组
+  return deArray;
+};

+ 1 - 1
src/views/promotion/components/PreviewPromotionalInvoiceDetailDialog.vue

@@ -104,7 +104,7 @@
                 <div style="color: #a8abb2">
                   [ 收款ID:{{ row.order.mchId }}]
                   <br />
-                  [账号ID: {{ row.order.agencyId }}]
+                  <!-- [账号ID: {{ row.order.agencyId }}] -->
                 </div>
               </template>
             </el-table-column>

+ 103 - 0
src/views/promotion/components/SearchArchivesSelect.vue

@@ -0,0 +1,103 @@
+<template>
+  <el-select
+    v-model="selected"
+    filterable
+    clearable
+    :placeholder="props.placeholder"
+    remote
+    remote-show-suffix
+    :remote-method="searchArchives"
+    @change="change"
+  >
+    <el-option v-for="(item, idx) in options" :key="item.id" :value="item.id" :label="item.name">
+      <div class="flex items-center justify-between">
+        <span>{{ item.name }}</span>
+        <el-tag type="info" class="ml-4">{{ item.id }}</el-tag>
+      </div>
+    </el-option>
+  </el-select>
+</template>
+
+<script setup>
+import { computed, nextTick, onMounted, ref } from "vue";
+import { unique } from "@/utils";
+import request from "@/api";
+const props = defineProps({
+  value: {
+    type: String,
+    default: ""
+  },
+  placeholder: {
+    type: String,
+    default: undefined
+  },
+  list: {
+    type: Array,
+    default: () => []
+  },
+  channelIds: {
+    type: String,
+    default: ""
+  }
+});
+const emit = defineEmits(["input", "change"]);
+const selected = computed({
+  get() {
+    return props.value;
+  },
+  set(val) {
+    emit("input", val);
+  }
+});
+const change = e => {
+  emit(
+    "change",
+    e,
+    options.value.find(v => v.id == e)
+  );
+  console.log(e);
+};
+
+const options = ref([]);
+const searchArchives = async (q, init = false) => {
+  if (!q && !init) return;
+  options.value = [];
+  const { data } = await request.get(`/archivesService/agency/archives/paginate`, {
+    page: 1,
+    pageSize: 100,
+    keyword: q.trim(),
+    channelIds: props.channelIds,
+    needSubArchives: 1
+  });
+  const tmp = data.list
+    .map(v => {
+      v.familyIds = [v.id, ...(v.associatArchives || []).map(v3 => v3.id)];
+      return v.associatArchives?.length
+        ? [
+            v,
+            ...v.associatArchives.map(v2 => {
+              v2.familyIds = [v.id, ...v.associatArchives.map(v3 => v3.id)];
+              return v2;
+            })
+          ]
+        : [v];
+    })
+    .flat();
+  nextTick(() => {
+    options.value = unique(tmp, "id");
+    if (options.value[0]?.id && !init) {
+      selected.value = options.value[0].id;
+    }
+  });
+};
+
+onMounted(() => {
+  if (props.list && props.list.length) {
+    options.value = props.list;
+  } else {
+    searchArchives("", true);
+  }
+});
+</script>
+
+<style lang="scss" scoped></style>

+ 38 - 8
src/views/promotion/order.vue

@@ -80,16 +80,36 @@
                 <el-select v-model="state.key" placeholder="请选择" style="width: 150px">
                   <el-option label="订单号" value="key" />
                   <el-option label="用户ID" value="user" />
-                  <el-option label="用户手机尾号" value="mobile" />
-                  <el-option label="商品名称" value="goodsName" />
+                  <el-option label="推广商品" value="shop" />
                 </el-select>
                 <el-input
                   v-model="state.query.value"
                   placeholder="请输入关联业务单号"
-                  v-if="state.key == 'orderNo'"
-                  style="width: 195px"
+                  v-if="state.key == 'key'"
+                  class="w-[180px]"
+                  clearable
+                />
+                <SearchArchivesSelect
+                  v-model="state.query.archivesId"
+                  v-else-if="state.key == 'user'"
+                  placeholder="输入姓名或者档案号"
+                  class="w-[180px]"
                 />
-                <el-input v-else v-model="state.value" placeholder="请输入" style="width: 195px" />
+
+                <el-select
+                  v-else-if="state.key == 'shop'"
+                  placeholder="请选择推广商品"
+                  v-model="state.query.promotionGoodsId"
+                  class="w-[180px]"
+                  clearable
+                >
+                  <el-option
+                    v-for="item in promotionGoodsList"
+                    :key="item.memberCard"
+                    :label="item.memberCardName"
+                    :value="item.id"
+                  />
+                </el-select>
                 <el-button :icon="Search" @click="onSearch">查询</el-button>
               </div>
             </el-col>
@@ -138,7 +158,7 @@
             <div style="color: #a8abb2">
               [ 收款ID:{{ row.mchId }} ]
               <br />
-              [ 账号ID: {{ row.agencyId }} ]
+              <!-- [ 账号ID: {{ row.agencyId }} ] -->
             </div>
           </template>
         </el-table-column>
@@ -188,6 +208,7 @@
 import { ref, reactive } from "vue";
 import { Search } from "@element-plus/icons-vue";
 import PerviewDetail from "./components/PerviewDetail.vue";
+import SearchArchivesSelect from "./components/SearchArchivesSelect.vue";
 import { statusList, accountTypes } from "./constant.ts";
 import { promotionSitePaginate } from "@/api/modules/promotion";
 import http from "@/api";
@@ -208,7 +229,9 @@ const state = reactive({
     paymentType: [],
     agencyIds: [],
     name: "", // 搜索项目:user: 用户;outTradeNo:第三方订单号
-    key: ""
+    key: "",
+    archivesId: "",
+    promotionGoodsId: []
   },
   times: [],
   list: [],
@@ -254,6 +277,12 @@ const getMemberCardList = () => {
       memberCardList.value = resp.data;
     });
 };
+const promotionGoodsList = ref([]);
+const getPromotionGoodsList = () => {
+  http.get("archivesService/agency/promotionGoods/list").then(resp => {
+    promotionGoodsList.value = resp.data?.list;
+  });
+};
 const handleOpenViewDetail = () => {
   perviewDetailRef.value.initData();
 };
@@ -280,10 +309,11 @@ const getChannleList = () => {
     page: 1,
     pageSize: 1000
   }).then(res => {
-    channelList.value = res.data.list;
+    channelList.value = res.data?.list;
   });
 };
 const initData = () => {
+  getPromotionGoodsList();
   getMemberCardList();
   getList();
   getChannleList();