Pārlūkot izejas kodu

客户管理模块

chenlei 6 mēneši atpakaļ
vecāks
revīzija
f34de109db

+ 30 - 1
src/api/customer/user.js

@@ -23,5 +23,34 @@ export default {
      */
     getFeedbackList:params=>{
         return get('/feedBack/feedBackList',params)
-    }
+    },
+    /**
+     * 阅读记录列表 
+     * @param {Object} params
+     * @param {String} params.PageSize
+     * @param {String} params.CurrentIndex
+     * @param {String} params.ProductType 类型
+     * @param {String} params.UserId 用户id
+     * @param {String} params.PermissionIds 品种id
+     * @returns 
+     */
+    getUserReadRecordList:params=>{
+        return get('/user/readRecordList',params)
+    },
+    /**
+     * 正式用户列表
+     * @param {Object} params
+     * @param {Number} params.PageSize
+     * @param {Number} params.CurrentIndex
+     * @param {Number} params.Keyword
+     * @param {Number} params.SortParam
+     * @param {Number} params.SortType
+     * @param {Number} params.FollowingGzh
+     * @param {Number} params.RegisterBeginDate 开始时间
+     * @param {Number} params.RegisterEndDate 结束时间
+     * @returns 
+     */
+    getOfficialList:params=>{
+        return get('/user/official/list',params)
+    },
 };

+ 6 - 0
src/api/products/index.js

@@ -0,0 +1,6 @@
+import apiProductsConfig from './products'
+
+export {
+  apiProductsConfig,
+}
+

+ 28 - 0
src/api/products/products.js

@@ -0,0 +1,28 @@
+import { get, post } from "@/api/index";
+
+export default {
+    /**
+     * 单品列表 
+     * @param {Object} params
+     * @param {String} params.PageSize
+     * @param {String} params.CurrentIndex
+     * @param {String} params.ProductType 类型
+     * @param {String} params.PermissionIds 品种id
+     * @param {String} params.KeyWord 搜索关键字
+     * @returns 
+     */
+    getUnSetProductList:params=>{
+        return get('/product/unSetProductList',params)
+    },
+    /**
+     * 增加单品产品 
+     * @param {Object} params
+     * @param {String} params.Type 类型
+     * @param {String} params.Price 价格
+     * @param {String} params.SourceId 产品id
+     * @returns 
+     */
+    postAddProduct:params=>{
+        return post('/product/addProduct',params)
+    },
+};

+ 8 - 0
src/router/modules/customer.js

@@ -17,6 +17,14 @@ export default[
             title:'临时用户列表'
         }
       },
+      {
+        path:'userList',
+        component:()=>import('@/views/customer/UserList.vue'),
+        name:'UserList',
+        meta:{
+            title:'用户列表'
+        }
+      },
       {
         path:'feedbackList',
         component:()=>import('@/views/customer/FeedbackList.vue'),

+ 30 - 0
src/router/modules/products.js

@@ -0,0 +1,30 @@
+import LayoutIndex from '@/layout/Index.vue'
+
+export default[
+  {
+    path:'/products',
+    component:LayoutIndex,
+    name:'ProductsIndex',
+    meta:{
+      title:'付费产品配置'
+    },
+    children:[
+      {
+        path:'singleConfigList',
+        component:()=>import('@/views/products/SingleConfigList.vue'),
+        name:'SingleConfigList',
+        meta:{
+            title:'单品配置'
+        }
+      },
+      {
+        path:'packageConfigList',
+        component:()=>import('@/views/products/PackageConfigList.vue'),
+        name:'PackageConfigList',
+        meta:{
+            title:'套餐配置'
+        }
+      }
+    ]
+  }
+]

+ 1 - 0
src/views/Login.vue

@@ -28,6 +28,7 @@ async function submitForm(formEl) {
         Username: formState.account,
         password: md5(md5(formState.pwd) + md5key + `${t}`),
         ReqTime: `${t}`,
+        LoginType:"password",
       }).then(res => {
         if (res.Ret === 200) {
           if (formState.checked) {

+ 74 - 36
src/views/customer/TempUserList.vue

@@ -2,6 +2,8 @@
 import { ref, reactive } from 'vue'
 import { Search } from '@element-plus/icons-vue'
 import {apiCustomerUser} from '@/api/customer'
+import { apiMediaCommon } from '@/api/media'
+import ReadDialog from './components/ReadDialog.vue'
 
 const tableColumns = [
     {
@@ -12,6 +14,10 @@ const tableColumns = [
         label:'最近一次阅读时间',
         key:'LastReadTime',
         sortable:true
+    },{
+        label:'开户状态',
+        key:'AccountStatus',
+        sortable:false,
     },{
         label:'累计阅读次数',
         key:'ReadCount',
@@ -31,7 +37,9 @@ const tableQuery = reactive({
     sortParam:'',
     sortType:''
 })
+
 const tableData = ref([])
+const show = ref(false)
 function getTableData(){
     apiCustomerUser.getTempCustomList({
         Keyword:tableQuery.keyWord,
@@ -47,6 +55,16 @@ function getTableData(){
     })
 }
 getTableData()
+getLableList()
+const labelOptions = ref([])
+const userId = ref('')
+function getLableList(){
+    apiMediaCommon.getPermissionList().then(res=>{
+        if(res.Ret!==200) return
+        labelOptions.value = res.Data.List||[]
+    })
+}
+
 function handlePageChange(page){
     tableQuery.currentPage = page
     getTableData()
@@ -62,55 +80,75 @@ function handleSortChange({order,prop}){
     tableQuery.sortType = order==='ascending'?1:0
     getTableData()
 }
+
+// 查看用户详情
+function Details(row) {
+    if (row.ReadCount <= 0) return;
+    show.value = true;
+    userId.value = row.Id + '';
+}
 </script>
 
 <template>
-    <div class="temp-user-list-wrap">
-        <div class="search-box">
-            <el-input 
-                v-model="tableQuery.keyWord"
-                :prefix-icon="Search" clearable
-                style="width:400px"
-                placeholder="请输入手机号" 
-                @input="handlePageChange(1)"
+    <el-card class="box-card">
+        <div class="temp-user-list-wrap">
+            <div class="search-box">
+                <el-button type="primary" style="margin-right: 20px;">导出表格</el-button>
+                <el-input 
+                    v-model="tableQuery.keyWord"
+                    :prefix-icon="Search" clearable
+                    style="width:400px"
+                    placeholder="请输入手机号" 
+                    @input="handlePageChange(1)"
+                    />
+            </div>
+            <div class="table-box">
+                <el-table stripe border :data="tableData" @sort-change="handleSortChange">
+                    <el-table-column 
+                        v-for="column in tableColumns" :key="column.key"
+                        :prop="column.key" :label="column.label" :sortable="column.sortable">
+                        <template #default="scope" v-if="column.key === 'AccountStatus'">
+                            <el-tag :type="scope.row[column.key]=== 'Open' ?'success':'info'">{{scope.row[column.key]=== 'Open'?'已开户':'未开户' }}</el-tag>
+                        </template>
+                        <template #default="scope" v-else-if="column.key === 'ReadCount'">
+                            <span class="ReadCount" @click="Details(scope.row)">
+                                {{ scope.row[column.key] }}
+                            </span>
+                        </template>
+                        <template #default="scope" v-else>
+                            {{scope.row[column.key]}}
+                        </template>
+                    </el-table-column>
+                </el-table>
+                <el-pagination
+                    background
+                    layout="total,prev,pager,next,jumper"
+                    :current-page="tableQuery.currentPage"
+                    :page-size="tableQuery.pageSize"
+                    :total="tableQuery.totals"
+                    @current-change="handlePageChange"
+                    style=" justify-content: flex-end; margin-top: 50px;"
                 />
+            </div>
         </div>
-        <div class="table-box">
-            <el-table stripe border :data="tableData" @sort-change="handleSortChange">
-                <el-table-column 
-                    v-for="column in tableColumns" :key="column.key"
-                    :prop="column.key" :label="column.label" :sortable="column.sortable"/>
-            </el-table>
-            <el-pagination
-                background
-                layout="total,prev,pager,next,jumper"
-                :current-page="tableQuery.currentPage"
-                :page-size="tableQuery.pageSize"
-                :total="tableQuery.totals"
-                @current-change="handlePageChange"
-                style=" justify-content: flex-end;border:1px solid #ebeef5;border-top: none;"
-            />
-        </div>
-    </div>
+        <ReadDialog :show="show" :labelOptions="labelOptions" :userId="userId"></ReadDialog>
+    </el-card>
 </template>
 
 <style scoped lang="scss">
 .temp-user-list-wrap{
-    height: calc(100vh - 108px); //layout padding 30*2 headHeight 48
+    height: calc(100vh - 208px); //layout padding 30*2 headHeight 48
     /* display: flex;
     flex-direction: column; */
     .search-box{
         text-align: right;
-        margin-bottom: 20px;
+        margin: 20px 0 40px 0;
+    }
+    .table-box{
+       .ReadCount {
+        color: rgba(8, 108, 224, 1);
+        cursor: pointer;
+       }
     }
-    /* .table-box{
-        flex: 1;
-        display: flex;
-        flex-direction: column;
-        .el-table{
-            flex:1;
-            overflow-y: auto;
-        }
-    } */
 }
 </style>

+ 201 - 0
src/views/customer/UserList.vue

@@ -0,0 +1,201 @@
+<script setup>
+import { ref, reactive } from 'vue'
+import { Search } from '@element-plus/icons-vue'
+import {apiCustomerUser} from '@/api/customer'
+import { apiMediaCommon } from '@/api/media'
+import ReadDialog from './components/ReadDialog.vue'
+
+const tableColumns = [
+    {
+        label:'姓名',
+        key:'Mobile',
+        sortable:false
+    },
+    {
+        label:'手机号',
+        key:'Mobile',
+        sortable:false
+    },
+    {
+        label:'公司名称',
+        key:'Mobile',
+        sortable:false
+    },
+    {
+        label:'注册时间',
+        key:'LastReadTime',
+        sortable:false
+    },{
+        label:'是否关注公众号',
+        key:'AccountStatus',
+        sortable:false,
+    },{
+        label:'最近一次阅读时间',
+        key:'LastReadTime',
+        sortable:false
+    },{
+        label:'累计阅读次数',
+        key:'ReadCount',
+        sortable:false
+    }
+]
+
+const tableQuery = reactive({
+    keyWord:'',
+    currentPage:1,
+    pageSize:10,
+    totals:0,
+    sortParam:'',
+    sortType:'',
+    FollowingGzh:true,
+    RegisterBeginDate:'',
+    RegisterEndDate:'',
+})
+
+const tableData = ref([])
+const show = ref(false)
+function getTableData(){
+    apiCustomerUser.getOfficialList({
+        Keyword:tableQuery.keyWord,
+        CurrentIndex:tableQuery.currentPage,
+        PageSize:tableQuery.pageSize,
+        SortParam:tableQuery.sortParam,
+        SortType:tableQuery.sortType,
+        FollowingGzh:tableQuery.FollowingGzh,
+        RegisterBeginDate:tableQuery.RegisterBeginDate,
+        RegisterEndDate:tableQuery.RegisterEndDate,
+    }).then(res=>{
+        if(res.Ret!==200) return 
+
+        tableData.value = res.Data.List||[]
+        tableQuery.totals = res.Data.Paging.Totals||0
+    })
+}
+getTableData()
+getLableList()
+const labelOptions = ref([])
+const userId = ref('')
+const value1 = ref(['',''])
+function getLableList(){
+    apiMediaCommon.getPermissionList().then(res=>{
+        if(res.Ret!==200) return
+        labelOptions.value = res.Data.List||[]
+    })
+}
+
+function handlePageChange(page){
+    tableQuery.currentPage = page
+    getTableData()
+}
+function handleSortChange({order,prop}){
+    // ascending 
+    const propMap = {
+        0:'CreatedTime',
+        1:'ReadCount',
+        2:'LastReadTime',
+    }
+    tableQuery.sortParam = propMap[prop]||2
+    tableQuery.sortType = order==='ascending'?1:0
+    getTableData()
+}
+
+// 查看用户详情
+function Details(row) {
+    if (row.ReadCount <= 0) return;
+    show.value = true;
+    userId.value = row.Id + '';
+}
+function handleSelectChange() {
+    getTableData();
+}
+function changeDatePicker(val) {
+    console.log(value1.value);
+    tableQuery.RegisterBeginDate = val[0];
+    tableQuery.RegisterEndDate = val[1];
+    getTableData();
+}
+</script>
+
+<template>
+    <el-card class="box-card">
+        <div class="temp-user-list-wrap">
+            <div class="top-box">
+                <div>
+                    <el-select v-model="tableQuery.FollowingGzh" @change="handleSelectChange()" placeholder="是否关注公众号" style="width: 150px; margin-right: 20px;">
+                        <el-option label="是" :value="true"></el-option>
+                        <el-option label="否" :value="false"></el-option>
+                    </el-select>
+                    <el-date-picker
+                        v-model="value1"
+                        value-format="YYYY-MM-DD"
+                        type="daterange"
+                        @change="changeDatePicker"
+                        range-separator="至"
+                        start-placeholder="开始日期"
+                        end-placeholder="结束日期">
+                    </el-date-picker>
+                </div>
+                <div class="search-box">
+                    <el-button type="primary" style="margin-right: 20px;">导出表格</el-button>
+                    <el-input 
+                        v-model="tableQuery.keyWord"
+                        :prefix-icon="Search" clearable
+                        style="width:400px"
+                        placeholder="请输入手机号" 
+                        @input="handlePageChange(1)"
+                        />
+                </div>
+            </div>
+            <div class="table-box">
+                <el-table stripe border :data="tableData" @sort-change="handleSortChange">
+                    <el-table-column 
+                        v-for="column in tableColumns" :key="column.key"
+                        :prop="column.key" :label="column.label" :sortable="column.sortable">
+                        <template #default="scope" v-if="column.key === 'AccountStatus'">
+                            <el-tag :type="scope.row[column.key]=== 'Open' ?'success':'info'">{{scope.row[column.key]=== 'Open'?'已开户':'未开户' }}</el-tag>
+                        </template>
+                        <template #default="scope" v-else-if="column.key === 'ReadCount'">
+                            <span class="ReadCount" @click="Details(scope.row)">
+                                {{ scope.row[column.key] }}
+                            </span>
+                        </template>
+                        <template #default="scope" v-else>
+                            {{scope.row[column.key]}}
+                        </template>
+                    </el-table-column>
+                </el-table>
+                <el-pagination
+                    background
+                    layout="total,prev,pager,next,jumper"
+                    :current-page="tableQuery.currentPage"
+                    :page-size="tableQuery.pageSize"
+                    :total="tableQuery.totals"
+                    @current-change="handlePageChange"
+                    style=" justify-content: flex-end;margin-top: 50px;"
+                />
+            </div>
+        </div>
+        <ReadDialog :show="show" :labelOptions="labelOptions" :userId="userId"></ReadDialog>
+    </el-card>
+</template>
+
+<style scoped lang="scss">
+.temp-user-list-wrap{
+    height: calc(100vh - 208px); //layout padding 30*2 headHeight 48
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .search-box{
+            text-align: right;
+            margin: 20px 0 40px 0;
+        }
+    }
+    .table-box{
+       .ReadCount {
+        color: rgba(8, 108, 224, 1);
+        cursor: pointer;
+       }
+    }
+}
+</style>

+ 181 - 0
src/views/customer/components/ReadDialog.vue

@@ -0,0 +1,181 @@
+<script setup>
+const show = defineModel('show', { type: Boolean, default: false })
+const props=defineProps({
+    labelOptions:{
+        type:Array,
+        default:[]
+    },
+    userId:{
+        type:String,
+        default:''
+    },
+})
+const emits = defineEmits(["success"])
+emits("success")
+
+watch(() => props.show, (newval) => {
+  if (newval) {
+    getTableData()
+  }
+})
+const options = ref([
+    {
+        value: 'report',
+        label: '报告'
+    }, {
+        value: 'audio',
+        label: '音频'
+    }, {
+        value: 'video',
+        label: '视频'
+    }
+])
+
+import { ref, reactive } from 'vue'
+import {apiCustomerUser} from '@/api/customer'
+
+const tableColumns = [
+    {
+        label:'标题',
+        key:'SourceName',
+        sortable:false
+    },{
+        label:'产品类型',
+        key:'SourceId',
+        sortable:false
+    },{
+        label:'品种',
+        key:'PermissionNames',
+        sortable:false,
+    },{
+        label:'最近一次点击时间',
+        key:'ClickTime',
+        sortable:true
+    },{
+        label:'停留时长',
+        key:'ReadDurationMinutes',
+        sortable:true
+    }
+]
+
+const tableQuery = reactive({
+    currentPage:1,
+    pageSize:10,
+    totals:0,
+    sortParam:'',
+    sortType:'',
+    PermissionIds:null,
+    ProductType:'',
+})
+const tableData = ref([])
+function getTableData(){
+    apiCustomerUser.getUserReadRecordList({
+        CurrentIndex:tableQuery.currentPage,
+        PageSize:tableQuery.pageSize,
+        SortParam:tableQuery.sortParam,
+        SortType:tableQuery.sortType,
+        ProductType:tableQuery.ProductType,
+        PermissionIds:tableQuery.PermissionIds?.join(','),
+        UserId:props.userId,
+    }).then(res=>{
+        if(res.Ret!==200) return
+        tableData.value = res.Data.List||[]
+        tableQuery.totals = res.Data.Paging && res.Data.Paging.Totals||0
+    })
+}
+function handlePageChange(page){
+    tableQuery.currentPage = page
+    getTableData()
+}
+function handleSortChange({order,prop}){
+    const propMap = {
+        0:'ClickTime',
+        1:'ReadDurationMinutes',
+    }
+    tableQuery.sortParam = propMap[prop]||2
+    tableQuery.sortType = order==='ascending'?1:0
+    getTableData()
+}
+
+function handleSelectChange(){
+    getTableData()
+}
+
+</script>
+
+<template>
+  <el-dialog
+    v-model="show"
+    :close-on-click-modal="false"
+    :modal-append-to-body="false"
+    width="60%"
+    draggable
+    title="阅读详情"
+  >
+    <div class="dialog-content">
+        <div class="dialog-content-top">
+            <el-select v-model="tableQuery.ProductType"  @change="handleSelectChange()" placeholder="请选择" style="width: 250px; margin-right: 20px;">
+                <el-option
+                v-for="item in options"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value">
+                </el-option>
+            </el-select>
+            <el-cascader
+                filterable
+                :options="props.labelOptions"
+                collapse-tags
+                v-model="tableQuery.PermissionIds" 
+                 @change="handleSelectChange()"
+                :props="{
+                    value:'id',
+                    label:'name',
+                    emitPath:false,
+                    multiple:true
+                }"
+                style="width: 250px;"
+                clearable>
+            </el-cascader>
+        </div>
+        <div class="table">
+            <el-table :data="tableData" @sort-change="handleSortChange">
+                <el-table-column 
+                    v-for="column in tableColumns" :key="column.key"
+                    :prop="column.key" :label="column.label" :sortable="column.sortable">
+                    <template #default="scope">
+                        {{scope.row[column.key]}}
+                    </template>
+                </el-table-column>
+            </el-table>
+            <el-pagination
+                background
+                layout="total,prev,pager,next,jumper"
+                :current-page="tableQuery.currentPage"
+                :page-size="tableQuery.pageSize"
+                :total="tableQuery.totals"
+                @current-change="handlePageChange"
+                style=" justify-content: flex-end; margin-top: 10px;"
+            />
+        </div>
+    </div>
+  </el-dialog>
+</template>
+
+<style scoped lang="scss">
+.dialog-content {
+    // padding: 10px 50px 50px 50px;
+    .dialog-content-top {
+        display: flex;
+        justify-content: flex-start;
+        padding-bottom: 30px;
+        :deep(.el-cascader-node__label) {
+            max-width: 111px;
+        }
+    }
+    .table {
+        padding-bottom: 30px;
+    }
+}
+
+</style>

+ 12 - 0
src/views/products/PackageConfigList.vue

@@ -0,0 +1,12 @@
+<script setup>
+import { ref } from "vue";
+</script>
+
+<template>
+    <el-card class="box-card">
+        PackageConfigList
+    </el-card>
+</template>
+
+<style scoped lang="scss">
+</style>

+ 243 - 0
src/views/products/SingleConfigList.vue

@@ -0,0 +1,243 @@
+<script setup>
+import { ref, reactive } from 'vue'
+import { Search } from '@element-plus/icons-vue'
+import {apiProductsConfig} from '@/api/products'
+import { apiMediaCommon } from '@/api/media'
+import addSingleList from './components/addSingleList.vue'
+const tableColumns = [
+    {
+        label:'产品名称',
+        key:'Mobile',
+        sortable:false,
+        align: 'center'
+    },
+    {
+        label:'产品类型',
+        key:'Mobile',
+        sortable:false,
+        align: 'center'
+    },
+    {
+        label:'商品价格',
+        key:'Mobile',
+        sortable:false,
+        align: 'center'
+    },
+    {
+        label:'风险等级',
+        key:'LastReadTime',
+        sortable:false,
+        align: 'center'
+    },{
+        label:'状态',
+        key:'AccountStatus',
+        sortable:false,
+        align: 'center'
+    },{
+        label:'创建人',
+        key:'LastReadTime',
+        sortable:false,
+        align: 'center'
+    },{
+        label:'创建时间',
+        key:'ReadCount',
+        sortable:false,
+        align: 'center'
+    },
+    {
+        label:'更新时间',
+        key:'ReadCount',
+        sortable:false,
+        align: 'center'
+    },
+    {
+        label:'操作',
+        key:'ReadCount',
+        sortable:false,
+        align: 'center'
+    }
+]
+const options = ref([
+    {
+        value: 'report',
+        label: '报告'
+    }, {
+        value: 'audio',
+        label: '音频'
+    }, {
+        value: 'video',
+        label: '视频'
+    }
+])
+const tableData = ref([])
+const show = ref(false)
+const labelOptions = ref([])
+const userId = ref('')
+const isAdd = ref(false)
+const tableQuery = reactive({
+    keyWord:'',
+    currentPage:1,
+    pageSize:10,
+    totals:0,
+    ProductType:'report',
+    PermissionIds:null,
+    RegisterBeginDate:'',
+    RegisterEndDate:'',
+})
+
+function getTableData(){
+    apiProductsConfig.getUnSetProductList({
+        Keyword:tableQuery.keyWord,
+        CurrentIndex:tableQuery.currentPage,
+        PageSize:tableQuery.pageSize,
+        ProductType:tableQuery.ProductType,
+        RegisterBeginDate:tableQuery.RegisterBeginDate,
+        RegisterEndDate:tableQuery.RegisterEndDate,
+        PermissionIds:tableQuery.PermissionIds?.join(','),
+    }).then(res=>{
+        if(res.Ret!==200) return 
+        tableData.value = res.Data.List||[]
+        tableQuery.totals = res.Data.Paging.Totals||0
+    })
+}
+
+getTableData()
+getLableList()
+
+function getLableList(){
+    apiMediaCommon.getPermissionList().then(res=>{
+        if(res.Ret!==200) return
+        labelOptions.value = res.Data.List||[]
+    })
+}
+function handlePageChange(page){
+    tableQuery.currentPage = page
+    getTableData()
+}
+function handleSortChange({order,prop}){
+    // ascending 
+    const propMap = {
+        0:'CreatedTime',
+        1:'ReadCount',
+        2:'LastReadTime',
+    }
+    tableQuery.sortParam = propMap[prop]||2
+    tableQuery.sortType = order==='ascending'?1:0
+    getTableData()
+}
+// 查看用户详情
+function Details(row) {
+    if (row.ReadCount <= 0) return;
+    show.value = true;
+    userId.value = row.Id + '';
+}
+function handleSelectChange() {
+    getTableData();
+}
+</script>
+
+<template>
+    <el-card class="box-card">
+        <div class="temp-user-list-wrap" v-if="!isAdd">
+            <div class="top-box">
+                <div>
+                    <el-button type="primary" style="margin-right: 20px;" @click="isAdd = true">添加单品</el-button>
+                    <el-select v-model="tableQuery.ProductType"  @change="handleSelectChange()" placeholder="请选择" style="width: 200px; margin-right: 20px;">
+                        <el-option
+                        v-for="item in options"
+                        :key="item.value"
+                        :label="item.label"
+                        :value="item.value">
+                        </el-option>
+                    </el-select>
+                    <el-cascader
+                        filterable
+                        :options="labelOptions"
+                        collapse-tags
+                        v-model="tableQuery.PermissionIds" 
+                        @change="handleSelectChange()"
+                        :props="{
+                            value:'id',
+                            label:'name',
+                            emitPath:false,
+                            multiple:true
+                        }"
+                        style=" margin-right: 20px"
+                        clearable>
+                    </el-cascader>
+                    <el-date-picker
+                        v-model="tableQuery.RegisterBeginDate"
+                        type="date"
+                        placeholder="创建时间"
+                        format="YYYY-MM-DD"
+                        style="margin-right: 20px;"
+                        value-format="YYYY-MM-DD"
+                    />
+                    <el-date-picker
+                        v-model="tableQuery.RegisterEndDate"
+                        type="date"
+                        placeholder="更新时间"
+                        format="YYYY-MM-DD"
+                        value-format="YYYY-MM-DD"
+                    />
+                </div>
+                <div class="search-box">
+                    <el-input 
+                        v-model="tableQuery.keyWord"
+                        :prefix-icon="Search" clearable
+                        style="width:400px"
+                        placeholder="请输入手机号" 
+                        @input="handlePageChange(1)"
+                        />
+                </div>
+            </div>
+            <div class="table-box">
+                <el-table border :data="tableData" @sort-change="handleSortChange">
+                    <el-table-column 
+                        v-for="column in tableColumns" :key="column.key"
+                        :prop="column.key" :label="column.label" :sortable="column.sortable" :align="column.align">
+                        <template #default="scope" v-if="column.key === 'AccountStatus'">
+                            <el-tag :type="scope.row[column.key]=== 'Open' ?'success':'info'">{{scope.row[column.key]=== 'Open'?'已开户':'未开户' }}</el-tag>
+                        </template>
+                        <template #default="scope" v-else-if="column.key === 'ReadCount'">
+                            <span class="ReadCount" @click="Details(scope.row)">
+                                {{ scope.row[column.key] }}
+                            </span>
+                        </template>
+                        <template #default="scope" v-else>
+                            {{scope.row[column.key]}}
+                        </template>
+                    </el-table-column>
+                </el-table>
+                <el-pagination
+                    background
+                    layout="total,prev,pager,next,jumper"
+                    :current-page="tableQuery.currentPage"
+                    :page-size="tableQuery.pageSize"
+                    :total="tableQuery.totals"
+                    @current-change="handlePageChange"
+                    style=" justify-content: flex-end;margin-top: 50px;"
+                />
+            </div>
+        </div>
+        <addSingleList :show="isAdd" @close="isAdd = false" :labelOptions="labelOptions"></addSingleList>
+    </el-card>
+</template>
+
+<style scoped lang="scss">
+.temp-user-list-wrap{
+    height: calc(100vh - 208px); //layout padding 30*2 headHeight 48
+    .top-box{
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 20px 0 40px 0;
+    }
+    .table-box{
+       .ReadCount {
+        color: rgba(8, 108, 224, 1);
+        cursor: pointer;
+       }
+    }
+}
+</style>

+ 204 - 0
src/views/products/components/addSingleList.vue

@@ -0,0 +1,204 @@
+<script setup>
+import { ref, reactive } from 'vue'
+import {apiProductsConfig} from '@/api/products'
+import { Search } from '@element-plus/icons-vue'
+
+const show = defineModel('show', { type: Boolean, default: false })
+const props=defineProps({
+    labelOptions:{
+        type:Array,
+        default:[]
+    },
+})
+watch(() => props.show, (newval) => {
+  if (newval) {
+    console.log(newval);
+    
+    getTableData()
+  }
+})
+const emits = defineEmits(["close"])
+const tableColumns = [
+    {
+        label:'产品名称',
+        key:'ProductName',
+        sortable:false,
+        align:'center',
+        minwidthsty:150
+    },{
+        label:'发布时间',
+        key:'PublishedTime',
+        sortable:false,
+        align:'center',
+        widthsty:200
+    },{
+        label:'产品类型',
+        key:'ProductType',
+        sortable:false,
+        align:'center',
+        widthsty:100
+    },{
+        label:'品种',
+        key:'ClickTime',
+        sortable:false,
+        align:'center'
+    },{
+        label:'风险等级',
+        key:'RiskLevel',
+        sortable:false,
+        align:'center',
+        widthsty:100
+    },
+    {
+        label:'商品价格(元)',
+        key:'ReadDurationMinutes',
+        sortable:false,
+        align:'center'
+    },
+    {
+        label:'操作',
+        key:'handle',
+        align:'center'
+    },
+]
+const tableData = ref([])
+const tableQuery = reactive({
+    keyWord:'',
+    currentPage:1,
+    pageSize:10,
+    totals:0,
+    ProductType:'report',
+    PermissionIds:null,
+})
+function getTableData(){
+    apiProductsConfig.getUnSetProductList({
+        Keyword:tableQuery.keyWord,
+        CurrentIndex:tableQuery.currentPage,
+        PageSize:tableQuery.pageSize,
+        ProductType:tableQuery.ProductType,
+        PermissionIds:tableQuery.PermissionIds?.join(','),
+    }).then(res=>{
+        if(res.Ret!==200) return 
+        tableData.value = res.Data.List||[]
+        tableQuery.totals = res.Data.Paging.Totals||0
+    })
+}
+function handlePageChange(page){
+    tableQuery.currentPage = page
+    getTableData()
+}
+function handleSortChange({order,prop}){
+    const propMap = {
+        0:'ClickTime',
+        1:'ReadDurationMinutes',
+    }
+    tableQuery.sortParam = propMap[prop]||2
+    tableQuery.sortType = order==='ascending'?1:0
+    getTableData()
+}
+function handleSelectChange(){
+    getTableData()
+}
+function close() {
+    emits("close")
+}
+function stockProducts(row){
+    console.log(row);
+    
+}
+</script>
+
+<template>
+<div class="dialog-content" v-if="props.show">
+    <div>
+        <el-radio-group v-model="tableQuery.ProductType" size="large" @change="handleSelectChange()">
+            <el-radio-button label="报告" value="report" />
+            <el-radio-button label="音视频" value="audio" />
+        </el-radio-group>
+    </div>
+    <div class="top-box">
+        <div>
+            <!-- <el-select v-model="tableQuery.ProductType" clearable  @change="handleSelectChange()" placeholder="请选择" style="width: 250px; margin-right: 20px;">
+                <el-option
+                v-for="item in options"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value">
+                </el-option>
+            </el-select> -->
+            <el-cascader
+                filterable
+                :options="props.labelOptions"
+                collapse-tags
+                placeholder="请选择品种"
+                v-model="tableQuery.PermissionIds" 
+                @change="handleSelectChange()"
+                :props="{
+                    value:'id',
+                    label:'name',
+                    emitPath:false,
+                    multiple:true
+                }"
+                style="width: 250px; margin-right: 20px;"
+                clearable>
+            </el-cascader>
+            <el-input 
+                v-model="tableQuery.keyWord"
+                :prefix-icon="Search" clearable
+                style="width:250px"
+                placeholder="产品名称" 
+                @input="handlePageChange(1)"
+            />
+        </div>
+        <div>
+            <el-button type="primary" plain @click="close">返回</el-button>
+        </div>
+    </div>
+    <div class="table">
+        <el-table :data="tableData" @sort-change="handleSortChange" border>
+            <el-table-column 
+                v-for="column in tableColumns" :key="column.key"
+                :prop="column.key" :label="column.label" :sortable="column.sortable" :align="column.align" :width="column.widthsty"
+                :min-width="column.minwidthsty || ''">
+                <template #default="scope" v-if="column.key==='ReadDurationMinutes'">
+                    <el-input v-model="scope.row[column.key]" placeholder="请输入数字" />
+                </template>
+                <template #default="scope" v-else-if="column.key==='handle'">
+                    <span class="stock" @click="stockProducts(scope.row)">保存并上架</span>
+                </template>
+                <template #default="scope" v-else>
+                    {{scope.row[column.key]}}
+                </template>
+            </el-table-column>
+        </el-table>
+        <el-pagination
+            background
+            layout="total,prev,pager,next,jumper"
+            :current-page="tableQuery.currentPage"
+            :page-size="tableQuery.pageSize"
+            :total="tableQuery.totals"
+            @current-change="handlePageChange"
+            style=" justify-content: flex-end; margin-top:50px;"
+        />
+    </div>
+</div>
+</template>
+
+<style scoped lang="scss">
+.dialog-content {
+    padding: 20px;
+    .top-box {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 20px 0 20px 0;
+    }
+    .table {
+        padding-bottom: 30px;
+        .stock {
+            cursor:pointer;
+            color: rgba(8, 108, 224, 1);
+        }
+    }
+}
+</style>