From d6000775372ca9f31d5da635362d41289bccae6e Mon Sep 17 00:00:00 2001
From: zxl <763096477@qq.com>
Date: 星期四, 15 五月 2025 17:45:05 +0800
Subject: [PATCH] 客户管理,客户列表页面

---
 manager/src/api/customer.js          |   78 +++++++++
 manager/src/views/customer/index.vue |  387 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 465 insertions(+), 0 deletions(-)

diff --git a/manager/src/api/customer.js b/manager/src/api/customer.js
new file mode 100644
index 0000000..bf261ad
--- /dev/null
+++ b/manager/src/api/customer.js
@@ -0,0 +1,78 @@
+import service from "@/libs/axios";
+
+// 鑾峰彇瀹㈡埛鍒楄〃
+export const getCustomerList = (params) => {
+  return service({
+    url: "/customerManager",
+    method: "GET",
+    params: params
+  })
+}
+// 娣诲姞鏍囩
+export const addCustomerTag = (params) => {
+  return service({
+    url: "/customerManager/addTag",
+    method: "POST",
+    data: params
+  })
+}
+// 淇敼鏍囩
+export const editTag = (params) => {
+  return service({
+    url: "/customerManager/editTag",
+    method: "PUT",
+    data: params
+  })
+}
+// 鍒犻櫎鏍囩
+export const delTag = (params) => {
+  return service({
+    url: "/customerManager/tag/" + params,
+    method: "DELETE",
+  })
+}
+// 鏍囩鍒楄〃
+export const getTagList = () => {
+  return service({
+    url: "/customerManager/tagList",
+    method: "GET",
+  })
+}
+// 鍒嗛〉鏍囩鍒楄〃
+export const getPageTagList = (params) =>{
+  return service({
+    url: "/customerManager/pageTagList",
+    method: "GET",
+    params:params
+  })
+}
+// 娣诲姞瀹㈡埛鏍囩鏍囪瘑
+export const saveCustomerTagById = (params) => {
+  return service({
+    url: "/customerManager/customerAddTag",
+    method: "POST",
+    data:params
+  })
+}
+// 淇敼瀹㈡埛鏍囩鏍囪瘑
+export const editCustomerTagById = (params) => {
+  return service({
+    url: "/customerManager/customerEditTag",
+    method: "PUT",
+    data:params
+  })
+}
+// 鍒犻櫎瀹㈡埛鏍囩鏍囪瘑ID鍒犻櫎
+export const removeCustomerTagById = (params) => {
+  return service({
+    url: "/customerManager/customerDelTag/" + params,
+    method: "DELETE",
+  })
+}
+export const getStoreSelectOptions = () =>{
+  return service({
+    url: '/customerManager/store/selectOption',
+    method: 'GET'
+  })
+}
+
diff --git a/manager/src/views/customer/index.vue b/manager/src/views/customer/index.vue
new file mode 100644
index 0000000..0076c30
--- /dev/null
+++ b/manager/src/views/customer/index.vue
@@ -0,0 +1,387 @@
+<template>
+  <div>
+    <card>
+      <Form
+        ref="searchForm"
+        @keydown.enter.native="handleSearch"
+        :model="searchForm"
+        inline
+        :label-width="70"
+        class="search-form"
+      >
+        <Form-item label="鐢ㄦ埛鍚�" prop="username">
+          <Input
+            type="text"
+            v-model="searchForm.username"
+            clearable
+            @on-clear="handleSearch"
+            @on-change="handleSearch"
+            style="width: 160px"
+          />
+        </Form-item>
+        <Form-item label="鏄电О" prop="nickname">
+          <Input
+            type="text"
+            v-model="searchForm.nickName"
+            clearable
+            @on-clear="handleSearch"
+            @on-change="handleSearch"
+            style="width: 160px"
+          />
+        </Form-item>
+        <Form-item label="鍟嗗" prop="storeId">
+          <Select
+            v-model="searchForm.storeId"
+            style="width:160px"
+            :loading="storeSelectLoading"
+            class="custom-select"
+            clearable
+            @on-clear="handleSearch"
+            @on-change="handleSearch"
+          >
+            <Option
+              v-for="item in selectOptions"
+              :value="item.id"
+              :key="item.id"
+            >
+              {{ item.storeName }}
+            </Option>
+          </Select>
+        </Form-item>
+        <Button
+          @click="handleSearch"
+          type="primary"
+          icon="ios-search"
+          class="search-btn"
+        >鎼滅储</Button
+        >
+      </Form>
+
+      <Table
+        :loading="loading"
+        border
+        :columns="columns"
+        :data="customerList"
+        ref="table"
+        sortable="custom"
+        @on-sort-change="changeSort"
+        @on-selection-change="showSelect"
+      >
+        <template slot-scope="{ row, index }" slot="action">
+          <Button type="info" size="small" style="margin-right: 5px" @click="openEdit(row)">缂栬緫鏍囩</Button>
+          <Button type="error" size="small" style="margin-right: 5px" @click="joinBlack(row)">鍔犲叆榛戝悕鍗�</Button>
+        </template>
+      </Table>
+      <Row type="flex" justify="end" class="mt_10">
+        <Page
+          :current="searchForm.pageNumber"
+          :total="total"
+          :page-size="searchForm.pageSize"
+          @on-change="changePage"
+          @on-page-size-change="changePageSize"
+          :page-size-opts="[10, 20, 50]"
+          size="small"
+          show-total
+          show-elevator
+          show-sizer
+        ></Page>
+      </Row>
+
+      <Modal
+        v-model="showCustomerTag"
+        :title="modelTitle"
+      >
+        <Form ref="form" :model="tagForm" :label-width="70" :rules="rules">
+          <FormItem label="鏍囩鍚嶇О" prop="tagList">
+              <Select
+                v-model="tagForm.tagList"
+                multiple
+                style="width:260px"
+                :loading="selectLoading"
+                class="custom-select"
+                @on-clear="handleRemoveTag"
+                @on-select="handleSelectChange"
+              >
+                <Option
+                  v-for="item in tagList"
+                  :value="item.id"
+                  :key="item.id"
+                >
+                  {{ item.tagName }}
+                </Option>
+              </Select>
+          </FormItem>
+        </Form>
+        <div slot="footer">
+          <Button type="text" @click="modelClose">纭畾</Button>
+<!--          <Button type="primary" :loading="submitLoading" @click="saveOrUpdate">鎻愪氦</Button>-->
+        </div>
+      </Modal>
+    </card>
+
+
+  </div>
+</template>
+
+<script>
+import JsonExcel from "vue-json-excel";
+import {getCustomerList,addCustomerTag,saveCustomerTagById,getTagList,getStoreSelectOptions} from "@/api/customer";
+
+export default {
+  name:"customer",
+  components:{
+    "download-excel": JsonExcel,
+  },
+  data(){
+    return{
+      loading: false, // 琛ㄥ崟鍔犺浇鐘舵��
+      //鏌ヨ瀹㈡埛鍒楄〃璇锋眰鍙傛暟
+      searchForm:{
+        storeId: '', //鍟嗗
+        username:'', //鐢ㄦ埛鍚�
+        nickName:'', // 鏄电О
+        pageNumber: 1, // 褰撳墠椤垫暟
+        pageSize: 10, // 椤甸潰澶у皬
+      },
+      //瀹㈡埛鍒楄〃琛ㄥご
+      columns: [
+        {
+          type: 'selection',
+          width: 60,
+          align: 'center'
+        },
+        {
+          title:'鐢ㄦ埛鍚�',
+          key: 'username',
+          minWidth: 60,
+          tooltip: true,
+        },
+        {
+          title:'鏄电О',
+          key: 'nickName',
+          minWidth: 60,
+          tooltip: true,
+        },
+        {
+          title:'鎬у埆',
+          key: 'sex',
+          tooltip: true,
+          render: (h, params) => {
+            const sexText = params.row.sex === 1 ? '鐢�' : '濂�';
+            return h('span', sexText);
+          }
+        },
+        {
+          title:'鍦板潃',
+          key: 'region',
+          minWidth: 60,
+          tooltip: true,
+        },
+        {
+          title:'鐘舵��',
+          key: 'disabled',
+          tooltip: true,
+          render: (h, params) => {
+            const sexText = params.row.disabled === true ? '绂佺敤' : '姝e父';
+            return h('span', sexText);
+          }
+        },
+        {
+          title:'瀹㈡埛鏍囩',
+          key: 'customerTagList',
+          minWidth: 60,
+          tooltip: true,
+          render: (h, params) => {
+            const tags = params.row.customerTagList || [];
+            return h('div', {
+              style: {
+                display: 'flex',
+                flexWrap: 'wrap', // 鍏佽鎹㈣
+                gap: '4px' // 鏍囩闂磋窛
+              }
+            }, tags.map(tag => {
+              return h('Tag', {
+                props: {
+                  color: tag.color || 'default', // 鍋囪鏍囩鏈夐鑹插瓧娈�
+                  size: 'small'
+                }
+              }, tag.name); // 鍋囪鏍囩瀵硅薄鏈塶ame瀛楁
+            }));
+          }
+        },
+        {
+          title: '鎿嶄綔',
+          key: 'action',
+          slot: 'action',
+          minWidth: 150,
+          align: 'center'
+        }
+
+      ],
+      //瀹㈡埛鍒楄〃鏁版嵁
+      customerList:[],
+      total:0,
+      selectCount: 0, // 宸查�夋暟閲�
+      selectList: [], // 宸查�夋暟鎹垪琛�
+
+      //瀹㈡埛鏍囩瀵硅瘽妗�---
+
+      showCustomerTag:false,
+      submitLoading:false,
+      selectLoading:false,
+      modelTitle:'',
+      tagList:[],
+      tagForm:{
+        id: '',
+        tagList: [],
+        createType: 'SYSTEM'
+      },
+      rules: {
+        tagList: [
+          {required: true, message: "鏍囩鍚嶇О涓嶈兘涓虹┖", trigger: "blur", type: 'array'}
+        ],
+      },
+      //鍟嗗涓嬫媺妗嗘暟鎹�
+      selectOptions:[],
+      storeSelectLoading: false
+
+    }
+  },
+  mounted(){
+    this.init();
+  },
+  methods:{
+    // 鑾峰緱鍟嗗涓嬫媺妗嗘暟鎹�
+    getStoreSelectOptions(){
+      this.storeSelectLoading = true;
+      getStoreSelectOptions().then(res =>{
+        this.storeSelectLoading = false;
+        if (res.code === 200){
+          this.selectOptions = res.data;
+        }
+      })
+    },
+    // 鑾峰緱瀹㈡埛琛ㄦ牸淇℃伅
+    getCustomerList(){
+      this.loading = true;
+      getCustomerList(this.searchForm).then(res =>{
+        this.loading = false;
+        if (res.code === 200) {
+          this.customerList = res.data;
+          this.total = res.total;
+        }
+      })
+    },
+    // 鑾峰緱瀹㈡埛鏍囩涓嬫媺妗嗘暟鎹�
+    getCustomerTagSelectOptions(){
+      this.selectLoading = true;
+      getTagList().then(res =>{
+        this.selectLoading = false;
+        if (res.code === 200){
+          this.tagList = res.data;
+        }
+      })
+    },
+    init(){
+      this.getCustomerList();
+      this.getCustomerTagSelectOptions();
+      this.getStoreSelectOptions();
+    },
+    changeSort(){
+
+    },
+    showSelect(){
+      this.selectList = e.map(d => d.id);
+      this.selectCount = e.length;
+    },
+    // 缂栬緫鏍囩
+    openEdit(row){
+      this.showCustomerTag = true
+      this.modelTitle = "缂栬緫鏍囩"
+      //鏀惧叆form
+      this.tagForm.id = row.id
+      this.tagForm.tagList = row.customerTagList
+
+
+    },
+    handleSearch(){
+      this.searchForm.pageNumber = 1;
+      this.searchForm.pageSize = 10;
+      this.getCustomerList();
+    },
+    // 鏂板鎴栦慨鏀�
+    // saveOrUpdate() {
+    //   this.$refs.form.validate(valid => {
+    //     if (valid) {
+    //       this.submitLoading = true
+    //         // 鏂板
+    //         console.log(this.tagForm)
+    //
+    //     }
+    //   });
+    // },
+    handleSelectChange(newVal){
+      console.log(newVal)
+      this.getCustomerList()
+    },
+    handleRemoveTag(removedTag) {
+      console.log(removedTag)
+      this.getCustomerList()
+    },
+    // 鍏抽棴寮圭獥
+    modelClose() {
+      this.submitLoading = false
+      this.showCustomerTag = false
+    },
+
+    delById(){
+
+    },
+    // 椤电爜
+    changePage(v){
+      this.searchForm.pageNumber = v
+      this.getCustomerList()
+    },
+    // 淇敼size
+    changePageSize(v){
+      this.searchForm.pageNumber = 1;
+      this.searchForm.pageSize = v;
+      this.getCustomerList()
+    },
+    joinBlack(){
+
+    },
+
+
+  }
+}
+
+</script>
+<style lang="scss" scoped>
+.export {
+  margin: 10px 20px 10px 0;
+}
+.export-excel-wrapper {
+  display: inline;
+}
+.order-tab {
+  width: 950px;
+  height: 36px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  background-color: #f0f0f0;
+  padding: 0 10px;
+  margin-bottom: 10px;
+  div {
+    text-align: center;
+    padding: 4px 12px;
+    border-radius: 4px;
+    cursor: pointer;
+  }
+  .current {
+    background-color: #ffffff;
+  }
+}
+</style>
+

--
Gitblit v1.8.0