zory 3 tygodni temu
rodzic
commit
55f781a8d2

+ 40 - 0
src/api/model/agent.js

@@ -0,0 +1,40 @@
+import config from "@/config";
+import http from "@/utils/request";
+
+export default {
+    list: {
+        url: `${config.API_URL}/agent/list`,
+        name: "-",
+        get: async function (data = {}) {
+            return await http.get(this.url, data);
+        }
+    },
+    save: {
+        url: `${config.API_URL}/agent/save`,
+        name: "-",
+        post: async function (data = {}) {
+            return await http.post(this.url, data);
+        },
+    },
+    del: {
+        url: `${config.API_URL}/agent/del`,
+        name: "-",
+        post: async function (data = {}) {
+            return await http.post(this.url, data);
+        },
+    },
+    batch: {
+        url: `${config.API_URL}/agent/batch`,
+        name: "-",
+        post: async function (data = {}) {
+            return await http.post(this.url, data);
+        },
+    },
+    time: {
+        url: `${config.API_URL}/agent/time`,
+        name: "-",
+        post: async function (data = {}) {
+            return await http.post(this.url, data);
+        },
+    },
+};

+ 1 - 1
src/api/model/auth.js

@@ -29,5 +29,5 @@ export default {
 		get: async function(data={}){
 			return await http.get(this.url, data);
 		}
-	}
+	},
 }

+ 14 - 0
src/api/model/common.js

@@ -9,6 +9,20 @@ export default {
 			return await http.post(this.url, data, config);
 		}
 	},
+	captcha: {
+		url: `${config.API_URL}/sms/captcha`,
+		name: "-",
+		get: async function(data, config={}){
+			return await http.get(this.url, data, config);
+		}
+	},
+	sms: {
+		url: `${config.API_URL}/sms/send`,
+		name: "-",
+		post: async function(data, config={}){
+			return await http.post(this.url, data, config);
+		}
+	},
 	uploadFile: {
 		url: `${config.API_URL}/uploadFile`,
 		name: "附件上传",

+ 40 - 0
src/api/model/store.js

@@ -0,0 +1,40 @@
+import config from "@/config";
+import http from "@/utils/request";
+
+export default {
+    list: {
+        url: `${config.API_URL}/agent/list`,
+        name: "-",
+        get: async function (data = {}) {
+            return await http.get(this.url, data);
+        }
+    },
+    save: {
+        url: `${config.API_URL}/agent/save`,
+        name: "-",
+        post: async function (data = {}) {
+            return await http.post(this.url, data);
+        },
+    },
+    del: {
+        url: `${config.API_URL}/agent/del`,
+        name: "-",
+        post: async function (data = {}) {
+            return await http.post(this.url, data);
+        },
+    },
+    batch: {
+        url: `${config.API_URL}/agent/batch`,
+        name: "-",
+        post: async function (data = {}) {
+            return await http.post(this.url, data);
+        },
+    },
+    time: {
+        url: `${config.API_URL}/agent/time`,
+        name: "-",
+        post: async function (data = {}) {
+            return await http.post(this.url, data);
+        },
+    },
+};

+ 33 - 0
src/api/model/user.js

@@ -0,0 +1,33 @@
+import config from "@/config";
+import http from "@/utils/request";
+
+export default {
+    list: {
+        url: `${config.API_URL}/user/list`,
+        name: "-",
+        get: async function (data = {}) {
+            return await http.get(this.url, data);
+        }
+    },
+    save: {
+        url: `${config.API_URL}/user/save`,
+        name: "-",
+        post: async function (data = {}) {
+            return await http.post(this.url, data);
+        },
+    },
+    del: {
+        url: `${config.API_URL}/user/del`,
+        name: "-",
+        post: async function (data = {}) {
+            return await http.post(this.url, data);
+        },
+    },
+    batch: {
+        url: `${config.API_URL}/user/batch`,
+        name: "-",
+        post: async function (data = {}) {
+            return await http.post(this.url, data);
+        },
+    },
+};

+ 2 - 1
src/layout/index.vue

@@ -67,7 +67,7 @@
 					<span>{{ baseData.title ? baseData.title : $CONFIG.APP_NAME }}</span>
 					<div class="ml10">
 						<el-tag v-if="userInfo.type==1">管理后台</el-tag>
-						<el-tooltip class="box-item" effect="dark" :content="userInfo.vip_end==0?'到期时间:永久':'到期时间:'+$TOOL.getTime(userInfo.vip_end,'YYYY年MM月DD日')" placement="right" v-else>
+						<el-tooltip class="box-item" effect="dark" :content="userInfo.vip_at==0?'到期时间:永久':'到期时间:'+$TOOL.getTime(userInfo.vip_at,'YYYY年MM月DD日')" placement="right" v-else>
 							<el-tag v-if="userInfo.type==2">代理-旗舰版</el-tag>
 							<el-tag v-if="userInfo.type==3">门店-旗舰版</el-tag>
 							<el-tag v-if="userInfo.type==4">工厂-旗舰版</el-tag>
@@ -266,6 +266,7 @@ export default {
 		var menu = this.$router.sc_getMenu();
 		this.menu = this.filterUrl(menu);
 		var userInfo = this.$TOOL.data.get("USER_INFO");
+		console.log(userInfo)
 		this.userInfo = userInfo;
 
 		this.userName = userInfo.truename;

+ 9 - 1
src/router/index.js

@@ -30,11 +30,19 @@ document.title = config.APP_NAME
 //判断是否已加载过动态/静态路由
 var isGetRouter = false;
 
+
+//设置标题
+let sysData = tool.data.get("SERVICE");
+var sysTitle = sysData ? sysData.title : config.APP_NAME;
+document.title = sysTitle;
+
 router.beforeEach(async (to, from, next) => {
 
 	NProgress.start()
 	//动态标题
-	document.title = to.meta.title ? `${to.meta.title} - ${config.APP_NAME}` : `${config.APP_NAME}`
+	document.title = to.meta.title
+		? `${to.meta.title} - ${sysTitle}`
+		: `${sysTitle}`;
 
 	let token = tool.cookie.get("TOKEN");
 

+ 253 - 0
src/views/manage/components/agent.vue

@@ -0,0 +1,253 @@
+<!--
+ * @Descripttion: 用户选择器
+ * @version: 1.0
+ * @Author: Zory
+ * @Date: 2024年1月10日21:46:29
+-->
+<template>
+    <el-dialog :title="titleMap[mode]" v-model="visible" :width="800" destroy-on-close @closed="$emit('closed')">
+        <div class="main">
+            <div class="main-left">
+                <div class="main-top">
+                    <el-form class="lv-form-inline" ref="searchForm" :model="searchKey" label-position="right">
+                        <el-row :gutter="10">
+                            <el-col :span="18" :xs="12">
+                                <el-form-item label=" " prop="truename">
+                                    <el-input v-model="searchKey.truename" placeholder="请输入代理名称" clearable
+                                        :style="{width: '100%'}"></el-input>
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="6" :xs="12">
+                                <el-form-item>
+                                    <div class="search-btn">
+                                        <el-button type="primary" @click="searchForm">搜索</el-button>
+                                    </div>
+                                </el-form-item>
+                            </el-col>
+                        </el-row>
+                    </el-form>
+                </div>
+                <div class="main-body-wrap" v-if="!multiple">
+                    <scTable ref="table" :apiObj="list.apiObj" :hideSetting="true" paginationLayout="total, prev, pager, next" :params="searchKey" @current-change="handleCurrentChange" highlight-current-row :row-key="getRowKeys" @sortChange="sortChange">
+                        <el-table-column width="50" fixed="left">
+                            <div class="checkbox"></div>
+                        </el-table-column>
+                        <el-table-column label="代理名称" width="150" fixed="left" prop="truename"></el-table-column>
+                        <el-table-column label="联系人" width="150" prop="contact"></el-table-column>
+                        <el-table-column label="代理ID" width="150" prop="agent_id"></el-table-column>
+                        <el-table-column label="主账号登录账号" prop="truename" width="200">
+                            <template #default="scope">
+                                <span v-if="scope.row.user">{{ scope.row.user.username?scope.row.user.username:'-' }}</span>
+                                <span class="status-danger" v-else>未设置</span>
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="手机号码" prop="mobile" width="150">
+                            <template #default="scope">
+                                <span v-if="scope.row.mobile">{{ scope.row.mobile }}</span>
+                                <span class="status-danger" v-else>-</span>
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="到期时间" prop="vip_at" width="220"></el-table-column>
+                        <el-table-column label="创建时间" prop="create_at" width="180"></el-table-column>
+                        <el-table-column label="状态" prop="status" width="120" align="center">
+                            <template #default="scope">
+                                <div class="status-success" v-if="scope.row.status==1"><sc-status-indicator type="success"></sc-status-indicator> 正常</div>
+                                <div class="status-danger" v-if="scope.row.status==2"><sc-status-indicator type="danger"></sc-status-indicator> 已冻结</div>
+                                <div class="status-danger" v-if="scope.row.status==3"><sc-status-indicator type="danger"></sc-status-indicator> 已到期</div>
+                            </template>
+                        </el-table-column>
+                    </scTable>
+                </div>
+                <div class="main-body-wrap" v-else>
+                    <scTable ref="table" :apiObj="list.apiObj" :hideSetting="true" paginationLayout="total, prev, pager, next" :params="searchKey" @selectionChange="selectionChange" row-key="id" @sortChange="sortChange">
+                        <el-table-column type="selection" width="50" fixed="left"></el-table-column>
+                        <el-table-column label="代理名称" width="150" fixed="left" prop="truename"></el-table-column>
+                        <el-table-column label="联系人" width="150" prop="contact"></el-table-column>
+                        <el-table-column label="代理ID" width="150" prop="agent_id"></el-table-column>
+                        <el-table-column label="主账号登录账号" prop="truename" width="200">
+                            <template #default="scope">
+                                <span v-if="scope.row.user">{{ scope.row.user.username?scope.row.user.username:'-' }}</span>
+                                <span class="status-danger" v-else>未设置</span>
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="手机号码" prop="mobile" width="150">
+                            <template #default="scope">
+                                <span v-if="scope.row.mobile">{{ scope.row.mobile }}</span>
+                                <span class="status-danger" v-else>-</span>
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="到期时间" prop="vip_at" width="220"></el-table-column>
+                        <el-table-column label="创建时间" prop="create_at" width="180"></el-table-column>
+                        <el-table-column label="状态" prop="status" width="120" align="center">
+                            <template #default="scope">
+                                <div class="status-success" v-if="scope.row.status==1"><sc-status-indicator type="success"></sc-status-indicator> 正常</div>
+                                <div class="status-danger" v-if="scope.row.status==2"><sc-status-indicator type="danger"></sc-status-indicator> 已冻结</div>
+                                <div class="status-danger" v-if="scope.row.status==3"><sc-status-indicator type="danger"></sc-status-indicator> 已到期</div>
+                            </template>
+                        </el-table-column>
+                    </scTable>
+                </div>
+            </div>
+        </div>
+		<template #footer>
+			<el-button @click="visible=false" >取 消</el-button>
+			<el-button v-if="mode!='show'" type="primary" :loading="isSaveing" @click="submit()">确 定</el-button>
+		</template>
+    </el-dialog>
+</template>
+
+<script>
+export default{
+    emits: ['success', 'closed'],
+    props: {
+        multiple: { type: Boolean, default: false },
+    },
+    data(){
+        return {
+            loading: false,
+            mode:"add",
+            titleMap:{
+                add:"选择代理",
+                edit:"选择代理"
+            },
+            list: {
+                apiObj: this.$API.agent.list
+            },
+            visible: false,
+            isSaveing: false,
+            formData:{},
+            searchKey:{},
+            selectData:[]
+        }
+    },
+    methods:{
+        sortChange(event){
+            if (event.order) {
+                var data = {
+                    "field":event.prop,
+                    "order":event.order
+                }
+                this.$refs.table.upData(data)
+            } else {
+                this.$refs.table.reload(this.searchKey)
+            }
+            return ;
+        },
+        submit(){
+            if (this.selectData.length == 0)
+            {
+                return this.$message.error("请选择数据");
+            }
+            this.isSaveing = false;
+            this.visible = false;
+            if (this.multiple){
+                this.$emit('success', this.selectData);
+            } else {
+                this.$emit('success', this.selectData[0]);
+            }
+        },
+        getRowKeys(data){
+            return data.id;
+        },
+        clearAll(){
+            this.selectData = [];
+        },
+        removeUser(index,name){
+            this.selectData.splice(index, 1);
+            console.log(name)
+        },
+        handleCurrentChange(data){
+            this.selectData = [data];
+        },
+        selectionChange(data){
+            this.selectData = data;
+        },
+        searchForm(){
+            this.$refs.table.upData(this.searchKey)
+        },
+        fristName(name){
+            return name.substring(0,1);
+        },
+        open(mode = 'add'){
+            this.mode = mode;
+            this.visible = true;
+            return this
+        },
+        //表单注入数据
+        setData(data){
+            this.formData = data;
+        },
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.main{
+    display: flex;
+    border: 1px solid #dfe1e6;
+}
+.main-left{
+    overflow: hidden;
+    flex: 1;
+    .main-body-wrap{
+        position: relative;
+        height: 380px;
+    }
+}
+.main-top{
+    position: relative;
+    padding: 10px 0;
+    border-bottom: 1px solid #dfe1e6;
+    &.is-right{
+        height:53px;
+        display:flex;
+        align-items:center;
+        padding:0 10px;
+        justify-content:space-between;
+    }
+}
+.main-body.is-right{
+    padding: 8px 16px;
+    overflow-y: auto;
+    position: relative;
+    height: calc(100% - 53px);
+    max-height: 380px;
+}
+.mx-1{
+    margin: 0 0.5rem 0.5rem 0;
+}
+.main-right{
+    flex: 0.4;
+}
+.el-form-item--default{
+    margin-bottom: 0;
+}
+.checkbox{
+    border:1px solid #dfe1e6;
+    width: 14px;
+    height: 14px;
+    border-radius: 2px;
+    background-color: #fff;
+    cursor: pointer;
+    position:relative
+}
+.current-row .checkbox{
+    background-color: var(--el-color-primary);
+    border-color: var(--el-color-primary);
+}
+.current-row .checkbox:after{
+    transform: rotate(45deg) scaleY(1);
+    box-sizing: content-box;
+    content: "";
+    border: 1px solid #fff;
+    border-left: 0;
+    border-top: 0;
+    height: 7px;
+    left: 4px;
+    position: absolute;
+    top: 1px;
+    width: 3px;
+    transition: transform .15s ease-in 50ms;
+    transform-origin: center;
+}
+</style>

+ 7 - 0
src/views/manage/user/factory/components/option.vue

@@ -0,0 +1,7 @@
+<template>
+    <div></div>
+</template>
+
+<script>
+
+</script>

+ 7 - 0
src/views/manage/user/factory/components/search.vue

@@ -0,0 +1,7 @@
+<template>
+    <div></div>
+</template>
+
+<script>
+
+</script>

+ 7 - 0
src/views/manage/user/factory/components/table.vue

@@ -0,0 +1,7 @@
+<template>
+    <div></div>
+</template>
+
+<script>
+
+</script>

+ 65 - 0
src/views/manage/user/factory/index.vue

@@ -0,0 +1,65 @@
+<template>
+    <el-container class="flex-column">
+        <div class="channel_menu">
+            <el-menu mode="horizontal" class="channel-tabs" :default-active="activeName" @select="handleClick">
+                <el-menu-item :index="item.key" v-for="(item,indx) in menuData" :key="indx">{{item.name}}</el-menu-item>
+            </el-menu>
+        </div>
+        <div class="table-search">
+            <search @success="handleSuccess"></search>
+            <optionBtn @success="handleSuccess" :dataSelect="dataSelect" :dataSelectFull="dataSelectFull" ></optionBtn>
+        </div>
+        <el-main class="nopadding">
+            <div class="table-container">
+                <tablePage ref="tablePage" @success="tableHandle" @successFull="tableHandleFull"></tablePage>
+            </div>
+        </el-main>
+    </el-container>  
+</template>
+
+<script>
+import search from './components/search';
+import optionBtn from './components/option';
+import tablePage from './components/table';
+export default {
+    components: {
+        search,tablePage,optionBtn
+    },
+    data(){
+        return {
+            activeName:"first",
+            menuData:[],
+            searchKey:{},
+            dataSelect:[],
+            dataSelectFull:[],
+        }
+    },
+    mounted(){
+        // this.getMenuData();
+    },
+    methods: {
+        tableHandle(data){
+            this.dataSelect = data;
+        },
+        tableHandleFull(data){
+            this.dataSelectFull = data;
+        },
+        handleSuccess(data){
+            this.$refs.tablePage.upData(data)
+        },
+        async getMenuData(){
+            var resp = await this.$API.common.menu.get({"type":"account"});
+            if (resp.code !== 1) {
+                return this.$message.error(resp.msg);
+            }
+            this.activeName = resp.data.default;
+            this.menuData = resp.data.menu;
+        },
+        handleClick(name){
+            this.activeName = name;
+            this.searchKey.type = name;
+            this.$refs.tablePage.upData(this.searchKey)
+        }
+    }
+}
+</script>

+ 236 - 0
src/views/manage/user/merchant/components/form.vue

@@ -0,0 +1,236 @@
+<template>
+    <el-dialog :title="titleMap[mode]" v-model="visible" :width="660" destroy-on-close @closed="$emit('closed')" :close-on-click-modal="false" :close-on-press-escape="false">
+        <el-form ref="dialogForm" :model="formData" :rules="rules" label-width="100px" label-position="top">
+            <fieldset>
+                <legend><el-tag>代理信息</el-tag></legend>
+                <el-row :gutter="10">
+                    <el-col :span="12">
+                        <el-form-item label="代理名称" prop="truename">
+                            <el-input v-model="formData.truename" clearable placeholder="请输入代理名称"></el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+                        <el-form-item label="联系人" prop="contact">
+                            <el-input v-model="formData.contact" clearable placeholder="请输入联系人"></el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12" v-if="mode=='add'">
+                        <el-form-item prop="mobile" :label="$t('login.mobilePlaceholder')">
+                            <el-input v-model="formData.mobile" clearable :placeholder="$t('login.mobilePlaceholder')">
+                                <template #prepend>+86</template>
+                            </el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12" v-if="mode=='add'">
+                        <el-form-item prop="yzm" :label="$t('login.smsPlaceholder')">
+                            <div class="login-msg-yzm">
+                                <el-input v-model="formData.yzm" clearable :placeholder="$t('login.smsPlaceholder')"></el-input>
+                                <el-button @click="getYzm" :disabled="disabled">{{this.$t('login.smsGet')}}<span v-if="disabled"> ({{time}})</span></el-button>
+                            </div>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12" v-if="mode=='add'">
+                        <el-form-item prop="captcha" :label="$t('login.code')">
+                            <div class="login-msg-yzm">
+                                <el-input v-model="formData.captcha" clearable :placeholder="$t('login.codeErr')"></el-input>
+                                <el-tooltip placement="top-start" :content="$t('login.codeTips')">
+                                    <div class="captcha" @click="getCaptcha"><img :src="captcha.base64" /></div>
+                                </el-tooltip>
+                            </div>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+                        <el-form-item label="到期时间" prop="vip_at">
+                            <el-date-picker v-model="formData.vip_at" :style="{width: '100%'}" placeholder="请选择" />
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+                        <el-form-item label="商城小程序权限" prop="mall_type">
+                            <el-radio-group class="radio-group" v-model="formData.mall_type">
+                                <el-radio border :label="0">系统</el-radio>
+                                <el-radio border :label="1">独立小程序</el-radio>
+                            </el-radio-group>
+                        </el-form-item>
+                    </el-col>
+                </el-row>
+            </fieldset>
+            <fieldset v-if="mode=='add'">
+                <legend><el-tag>主账号信息</el-tag></legend>
+                <el-row :gutter="10">
+                    <el-col :span="12">
+                        <el-form-item label="登录账号" prop="username">
+                            <el-input v-model="formData.username" clearable placeholder="请输入登录账号"></el-input>
+                            <div class="el-form-item-msg">不设置登录账号可以使用手机号码登录</div>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+                        <el-form-item label="登录密码" prop="password">
+                            <el-input type="password" v-model="formData.password" clearable show-password placeholder="请输入登录密码"></el-input>
+                        </el-form-item>
+                    </el-col>
+                    <el-col :span="12">
+                        <el-form-item label="确认密码" prop="password2">
+                            <el-input type="password" v-model="formData.password2" clearable show-password placeholder="请再次输入密码"></el-input>
+                        </el-form-item>
+                    </el-col>
+                </el-row>
+            </fieldset>
+        </el-form>
+		<template #footer>
+            <el-button @click="visible = false">取 消</el-button>
+			<el-button type="primary" :loading="isSaveing" @click="submit()">提交</el-button>
+		</template>
+    </el-dialog>
+</template>
+<script>
+export default{
+    data(){
+        return {
+            disabled:false,
+            stepActive:1,
+            loading: false,
+            mode:"add",
+            titleMap:{
+                add:"新增代理",
+                edit:"编辑代理"
+            },
+            captcha:{},
+            rules:{
+                truename: [
+                    {required: true, message: '请输入代理名称'}
+                ],
+                password: [
+                    {required: true, message: '请输入登录密码'}
+                ],
+                mall_type: [
+                    {required: true, message: '请选择'}
+                ],
+                password2: [
+                    {required: true, message: '请再次输入密码'},
+                    {validator: (rule, value, callback) => {
+                        if (value !== this.formData.password) {
+                            callback(new Error('两次输入密码不一致!'));
+                        }else{
+                            callback();
+                        }
+                    }}
+                ],
+                mobile: [
+                    { required: true, message: this.$t('login.mobileError'), trigger: 'blur' },
+                    {
+                        validator: (rule, value, callback) => {
+                            const phoneReg = /^1[3-9]\d{9}$/ // 手机号正则
+                            const landlineReg = /^(?:(?:\d{3}-)?\d{8}|^(?:\d{4}-)?\d{7,8})(?:-\d+)?$/
+                            if (!value) {
+                                callback(new Error('请输入联系方式'))
+                            } else if (!phoneReg.test(value) && !landlineReg.test(value)) {
+                                callback(new Error('请输入有效的手机号码号码'))
+                            } else {
+                                callback()
+                            }
+                        },
+                        trigger: 'blur'
+                    }
+                ],
+                yzm: [
+                    {required: true, message: this.$t('login.smsError')}
+                ],
+                captcha: [
+                    {required: true, message: this.$t('login.codeErr')}
+                ],
+                vip_at: [
+                    {required: true, message: "请选择到期时间",trigger: 'blur'}
+                ],
+            },
+            visible: false,
+            isSaveing: false,
+            formData:{"mall_type":0},
+            time:0,
+            submitState:false
+        }
+    },
+    methods:{
+        open(mode = 'add'){
+            this.mode = mode;
+            this.visible = true;
+            if (mode == 'add') {
+                this.getCaptcha();
+            }
+            return this
+        },
+        //表单注入数据
+        setData(data){
+            this.formData = data;
+        },
+        async getCaptcha(){
+            var resp = await this.$API.common.captcha.get();
+            if (resp.code == 0) {
+                return this.$message.error(resp.msg);
+            }
+            this.captcha = resp.data;
+        },
+        async getYzm(){
+			var field = ["mobile","captcha"];
+			this.$refs.dialogForm.validateField(field, async (valid) => {
+				if(!valid){
+					return false
+				}
+                var resp = await this.$API.common.sms.post({"mobile":this.formData.mobile,"code":this.formData.captcha,"key":this.captcha.key,"scene":"register"});
+                if (resp.code == 0) {
+                    this.getCaptcha();
+                    return this.$message.error(resp.msg);
+                }
+                this.$message.success(resp.msg)
+                this.disabled = true
+                this.time = 60
+                var t = setInterval(() => {
+                    this.time -= 1
+                    if(this.time < 1){
+                        clearInterval(t)
+                        this.disabled = false
+                        this.time = 0
+                    }
+                },1000)
+            });            
+        },
+        async submit(){
+            var validate = await this.$refs.dialogForm.validate().catch(()=>{});
+            if(!validate){ return false }
+            let submitData = JSON.parse(JSON.stringify(this.formData));
+            if (this.mode == 'add') {
+                submitData.password = this.$TOOL.crypto.MD5(this.formData.password)
+                submitData.password2 = this.$TOOL.crypto.MD5(this.formData.password2)
+                submitData.scene = "register";
+            }
+            if (this.formData.vip_at) {
+                submitData.vip_at = this.$TOOL.dateFormat(this.formData.vip_at, "yyyy-MM-dd");
+            }
+            this.isSaveing = true;
+            var resp = await this.$API.agent.save.post(submitData);
+            this.isSaveing = false;
+            if (resp.code == 0) {
+                return this.$message.error(resp.msg);
+            }
+            this.$message.success(resp.msg);
+            this.visible = false;
+            this.$emit("success");
+        }
+    }
+}
+</script>
+<style>
+.mt20 {margin-top: 20px;}
+.login-msg-yzm {display: flex;width: 100%;}
+.login-msg-yzm .el-button {margin-left: 10px;--el-button-size:42px;}
+.login-msg-yzm .captcha{
+	display: flex;
+	align-items: center;
+	cursor: pointer;
+    border: var(--el-border);
+    margin-left: 10px;
+	border-radius: 2px;
+}
+.captcha img{
+	height: 32px;
+}
+</style>

+ 66 - 0
src/views/manage/user/merchant/components/option.vue

@@ -0,0 +1,66 @@
+<template>
+    <fieldset>
+        <legend>
+            <el-tag type="info">按需操作</el-tag>
+        </legend>
+        <div class="op-header">
+            <div class="left-panel">
+                <el-button type="success" icon="el-icon-plus" @click="table_add()">新增代理</el-button>
+                <!-- <el-button icon="el-icon-delete" @click="table_del()" :disabled="dataSelect.length>0?false:true">删除</el-button> -->
+                <el-button icon="el-icon-document" @click="table_batch_status(1)" :disabled="dataSelect.length>0?false:true">启用</el-button>
+                <el-button icon="el-icon-lock" @click="table_batch_status(2)" :disabled="dataSelect.length>0?false:true">冻结</el-button>
+                <!-- <el-button type="primary" icon="el-icon-promotion" @click="table_batch_fee()" :disabled="dataSelect.length>0?false:true">续期</el-button> -->
+                <!-- <el-button type="primary" icon="el-icon-download" @click="table_export()">导出</el-button> -->
+            </div>
+        </div>
+    </fieldset>
+    <formMain ref="formMain" @success="handleSuccess"></formMain>
+    <feeMain ref="feeMain" @success="handleSuccess"></feeMain>
+</template>
+
+<script>
+import formMain from './form';
+import feeMain from './time';
+export default {
+    components: {
+        formMain,feeMain
+    },
+    props: {
+        type: { type: String, default: "1" },
+        dataSelect: { type: Array, default: () => [] },
+        dataSelectFull: { type: Array, default: () => [] }
+    },
+    data(){
+        return {
+
+        }
+    },
+    methods: {
+        handleSuccess(){
+            this.$emit("success");
+        },
+        async table_batch_status(status){
+            if (this.dataSelect.length == 0) {
+                return this.$message.error("请选择修改数据")
+            }
+            let submitData = {"id":this.dataSelect,"value":status,"field":"status","type":"batch"};
+            var resp = await this.$API.agent.batch.post(submitData);
+            if (resp.code == 0) {
+                return this.$message.error(resp.msg);
+            }
+            this.$message.success(resp.msg);
+            this.$emit("success");
+        },
+        table_batch_fee(){
+            this.$nextTick(() => {
+                this.$refs.feeMain.open().setData(this.dataSelect)
+            })
+        },
+        table_add(){
+            this.$nextTick(() => {
+                this.$refs.formMain.open()
+            })
+        },
+    }
+}
+</script>

+ 60 - 0
src/views/manage/user/merchant/components/search.vue

@@ -0,0 +1,60 @@
+<template>
+    <fieldset>
+        <legend>
+            <el-tag type="info">条件筛选</el-tag>
+        </legend>
+        <el-form class="lv-form-inline" ref="searchForm" :model="searchKey" label-position="right" label-width="100px">
+            <div class="search-form">
+                <div class="form-left">
+                    <el-row :gutter="10">
+                        <el-col :span="this.$store.state.global.ismobile?12:4">
+                            <el-input v-model="searchKey.truename" placeholder="代理名称" clearable :style="{ width: '100%' }" @keyup.enter="searchForm()">
+                                <template #prepend>代理名称</template>
+                            </el-input>
+                        </el-col>
+                        <el-col :span="this.$store.state.global.ismobile?12:4">
+                            <el-input v-model="searchKey.contact" placeholder="联系人" clearable :style="{ width: '100%' }" @keyup.enter="searchForm()">
+                                <template #prepend>联系人</template>
+                            </el-input>
+                        </el-col>
+                        <el-col :span="this.$store.state.global.ismobile?12:4">
+                            <el-input v-model="searchKey.mobile" placeholder="手机号码" clearable :style="{ width: '100%' }" @keyup.enter="searchForm()">
+                                <template #prepend>手机号码</template>
+                            </el-input>
+                        </el-col>
+                        <el-col :span="this.$store.state.global.ismobile?12:4">
+                            <el-select v-model="searchKey.status" clearable placeholder="请选择状态" @change="searchForm" :style="{width: '100%'}" class="diy-select">
+                                <el-option value="1" label="正常"></el-option>
+                                <el-option value="2" label="已冻结"></el-option>
+                                <el-option value="3" label="已过期"></el-option>
+                                <template #prefix>状态</template>
+                            </el-select>
+                        </el-col>
+                        <el-col :span="this.$store.state.global.ismobile?12:4">
+                            <el-date-picker v-model="searchKey.create" :style="{width: '100%'}" placeholder="请选择创建时间" start-placeholder="开始时间" end-placeholder="结束时间" type="daterange" range-separator="至" @change="searchForm" />
+                        </el-col>
+                    </el-row>
+                </div>
+                <div class="form-line"></div>
+                <div class="form-right">
+                    <el-button type="primary" icon="el-icon-search" @click="searchForm">搜索</el-button>
+                </div>
+            </div>
+        </el-form>
+    </fieldset>
+</template>
+
+<script>
+export default {
+    data(){
+        return {
+            searchKey:{}
+        }
+    },
+    methods: {
+        searchForm(){
+            this.$emit("success",this.searchKey);
+        }
+    }
+}
+</script>

+ 123 - 0
src/views/manage/user/merchant/components/table.vue

@@ -0,0 +1,123 @@
+<template>
+    <scTable ref="table" :apiObj="list.apiObj" :params="searchKey" @selectionChange="selectionChange" row-key="id">
+        <el-table-column type="selection" width="50" fixed="left"></el-table-column>
+        <el-table-column label="代理名称" width="150" fixed="left" prop="truename"></el-table-column>
+        <el-table-column label="联系人" width="150" prop="contact"></el-table-column>
+        <el-table-column label="代理ID" width="150" prop="agent_id"></el-table-column>
+        <el-table-column label="主账号登录账号" prop="truename" width="200">
+            <template #default="scope">
+                <span v-if="scope.row.user">{{ scope.row.user.username?scope.row.user.username:'-' }}</span>
+                <span class="status-danger" v-else>未设置</span>
+            </template>
+        </el-table-column>
+        <el-table-column label="手机号码" prop="mobile" width="150">
+            <template #default="scope">
+                <span v-if="scope.row.mobile">{{ scope.row.mobile }}</span>
+                <span class="status-danger" v-else>-</span>
+            </template>
+        </el-table-column>
+        <el-table-column label="到期时间" prop="vip_at" width="220"></el-table-column>
+        <el-table-column label="创建时间" prop="create_at" width="180"></el-table-column>
+        <el-table-column label="状态" prop="status" width="120" align="center">
+            <template #default="scope">
+                <div class="status-success" v-if="scope.row.status==1"><sc-status-indicator type="success"></sc-status-indicator> 正常</div>
+                <div class="status-danger" v-if="scope.row.status==2"><sc-status-indicator type="danger"></sc-status-indicator> 已冻结</div>
+                <div class="status-danger" v-if="scope.row.status==3"><sc-status-indicator type="danger"></sc-status-indicator> 已到期</div>
+            </template>
+        </el-table-column>
+        <el-table-column label="操作" width="200" align="right" fixed="right">
+            <template #default="scope">
+                <el-button-group>
+                    <el-button text size="small" @click="table_user(scope.row)">用户管理</el-button>
+                    <el-button text type="warning" size="small" @click="table_passwd(scope.row)">编辑</el-button>
+                    <el-popconfirm title="确定删除吗?" @confirm="table_del(scope.row, scope.$index)">
+                        <template #reference>
+                            <el-button text type="danger" size="small">删除</el-button>
+                        </template>
+                    </el-popconfirm>                    
+                </el-button-group>
+            </template>
+        </el-table-column>
+    </scTable>
+    <passwd ref="userPasswd"></passwd>
+    <formMain ref="formMain" @success="handleSuccess"></formMain>
+    <userMain ref="userMain" @success="handleSuccess"></userMain>
+</template>
+
+<script>
+import passwd from "@/views/manage/components/password";
+import formMain from './form';
+import userMain from '../user/list';
+export default {
+    components: {
+        passwd,formMain,userMain
+    },
+    props: {
+        type: { type: String, default: "1" }
+    },
+    data(){
+        return {
+            list: {
+                apiObj: this.$API.agent.list
+            },
+            dataSelect:[],
+            dataSelectFull:[],
+            searchKey:{}
+        }
+    },
+    methods: {
+        async table_del(data){
+            var resp = await this.$API.agent.del.post({"id":data.id});
+            if (resp.code == 0) {
+                return this.$message.warning(resp.msg);
+            }
+            this.$message.success(resp.msg);
+            this.$refs.table.refresh()
+        },
+        table_user(row){
+            this.$nextTick(() => {
+                this.$refs.userMain.open("edit").setData(row)
+            })
+        },
+        refresh(){
+            this.$refs.table.refresh()
+        },
+        upData(data){
+            this.$refs.table.upData(data)
+        },
+        handleSuccess(){
+            this.$refs.table.refresh()
+        },
+        sortChange(event){
+            if (event.order) {
+                var data = {
+                    "field":event.prop,
+                    "order":event.order
+                }
+                this.$refs.table.upData(data)
+            } else {
+                this.$refs.table.reload(this.searchKey)
+            }
+            return ;
+        },
+        selectionChange(event){
+            this.dataSelect = [];
+            var arr = [];
+            var arrCompany = [];
+            event.forEach(function(val,index){
+                arr[index] = val.id;
+                arrCompany[index] = val;
+            });
+            this.dataSelectFull = arrCompany;
+            this.dataSelect = arr;
+            this.$emit("success",this.dataSelect);
+            this.$emit("successFull",this.dataSelectFull);
+        },
+        table_passwd(row){
+            this.$nextTick(() => {
+                this.$refs.formMain.open("edit").setData(row)
+            })
+        },
+    }
+}
+</script>

+ 50 - 0
src/views/manage/user/merchant/components/time.vue

@@ -0,0 +1,50 @@
+<template>
+    <el-dialog :title="titleMap[mode]" v-model="visible" :width="660" destroy-on-close @closed="$emit('closed')" :close-on-click-modal="false" :close-on-press-escape="false">
+        <el-form ref="dialogForm" :model="formData" :rules="rules" label-width="100px" label-position="top">
+            <el-form-item label="续期时效" prop="val">
+                <el-select v-model="formData.val" clearable placeholder="请选择时效" :style="{width: '100%'}">
+                    <el-option value="1-year" label="一年"></el-option>
+                    <el-option value="2-year" label="两年"></el-option>
+                    <el-option value="7-day" label="7天"></el-option>
+                    <el-option value="15-day" label="15天"></el-option>
+                    <el-option value="30-day" label="30天"></el-option>
+                </el-select>
+                <div class="el-form-item-msg"></div>
+            </el-form-item>
+        </el-form>
+		<template #footer>
+            <el-button @click="visible = false">取 消</el-button>
+			<el-button type="primary" :loading="isSaveing" @click="submit()">提交</el-button>
+		</template>
+    </el-dialog>
+</template>
+<script>
+export default{
+    data(){
+        return {
+            disabled:false,
+            loading: false,
+            mode:"add",
+            titleMap:{
+                add:"代理续期",
+                edit:"代理续期"
+            },
+            visible: false,
+            isSaveing: false,
+            idData:[],
+            formData:{}
+        }
+    },
+    methods:{
+        open(mode = 'add'){
+            this.mode = mode;
+            this.visible = true;
+            return this
+        },
+        //表单注入数据
+        setData(data){
+            this.idData = data;
+        },
+    }
+}
+</script>

+ 65 - 0
src/views/manage/user/merchant/index.vue

@@ -0,0 +1,65 @@
+<template>
+    <el-container class="flex-column">
+        <div class="channel_menu">
+            <el-menu mode="horizontal" class="channel-tabs" :default-active="activeName" @select="handleClick">
+                <el-menu-item :index="item.key" v-for="(item,indx) in menuData" :key="indx">{{item.name}}</el-menu-item>
+            </el-menu>
+        </div>
+        <div class="table-search">
+            <search @success="handleSuccess"></search>
+            <optionBtn @success="handleSuccess" :dataSelect="dataSelect" :dataSelectFull="dataSelectFull" ></optionBtn>
+        </div>
+        <el-main class="nopadding">
+            <div class="table-container">
+                <tablePage ref="tablePage" @success="tableHandle" @successFull="tableHandleFull"></tablePage>
+            </div>
+        </el-main>
+    </el-container>  
+</template>
+
+<script>
+import search from './components/search';
+import optionBtn from './components/option';
+import tablePage from './components/table';
+export default {
+    components: {
+        search,tablePage,optionBtn
+    },
+    data(){
+        return {
+            activeName:"first",
+            menuData:[],
+            searchKey:{},
+            dataSelect:[],
+            dataSelectFull:[],
+        }
+    },
+    mounted(){
+        // this.getMenuData();
+    },
+    methods: {
+        tableHandle(data){
+            this.dataSelect = data;
+        },
+        tableHandleFull(data){
+            this.dataSelectFull = data;
+        },
+        handleSuccess(data){
+            this.$refs.tablePage.upData(data)
+        },
+        async getMenuData(){
+            var resp = await this.$API.common.menu.get({"type":"account"});
+            if (resp.code !== 1) {
+                return this.$message.error(resp.msg);
+            }
+            this.activeName = resp.data.default;
+            this.menuData = resp.data.menu;
+        },
+        handleClick(name){
+            this.activeName = name;
+            this.searchKey.type = name;
+            this.$refs.tablePage.upData(this.searchKey)
+        }
+    }
+}
+</script>

+ 196 - 0
src/views/manage/user/merchant/user/form.vue

@@ -0,0 +1,196 @@
+<template>
+    <el-dialog :title="titleMap[mode]" v-model="visible" :width="660" destroy-on-close @closed="$emit('closed')" :close-on-click-modal="false" :close-on-press-escape="false">
+        <el-form ref="dialogForm" :model="formData" :rules="rules" label-width="100px" label-position="top">
+            <el-row :gutter="10">
+                <el-col :span="12">
+                    <el-form-item label="账号名称" prop="truename">
+                        <el-input v-model="formData.truename" clearable placeholder="请输入"></el-input>
+                        <div class="el-form-item-msg"></div>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12" v-if="mode=='add'">
+                    <el-form-item label="登录账号" prop="username">
+                        <el-input v-model="formData.username" clearable placeholder="请输入登录账号"></el-input>
+                        <div class="el-form-item-msg">不设置登录账号可以使用手机号码登录</div>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12" v-if="mode=='edit'">
+                    <el-form-item label="登录账号">
+                        <el-input v-model="dataForm.username" :disabled="true" clearable placeholder="请输入登录账号"></el-input>
+                        <div class="el-form-item-msg">不设置登录账号可以使用手机号码登录</div>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12" v-if="mode=='add'">
+                    <el-form-item prop="mobile" :label="$t('login.mobilePlaceholder')">
+                        <el-input v-model="formData.mobile" clearable :placeholder="$t('login.mobilePlaceholder')">
+                            <template #prepend>+86</template>
+                        </el-input>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12" v-if="mode=='add'">
+                    <el-form-item prop="yzm" :label="$t('login.smsPlaceholder')">
+                        <div class="login-msg-yzm">
+                            <el-input v-model="formData.yzm" clearable :placeholder="$t('login.smsPlaceholder')"></el-input>
+                            <el-button @click="getYzm" :disabled="disabled">{{this.$t('login.smsGet')}}<span v-if="disabled"> ({{time}})</span></el-button>
+                        </div>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12" v-if="mode=='add'">
+                    <el-form-item prop="captcha" :label="$t('login.code')">
+                        <div class="login-msg-yzm">
+                            <el-input v-model="formData.captcha" clearable :placeholder="$t('login.codeErr')"></el-input>
+                            <el-tooltip placement="top-start" :content="$t('login.codeTips')">
+                                <div class="captcha" @click="getCaptcha"><img :src="captcha.base64" /></div>
+                            </el-tooltip>
+                        </div>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="登录密码" prop="password">
+                        <el-input type="password" v-model="formData.password" clearable show-password placeholder="请输入登录密码"></el-input>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="确认密码" prop="password2">
+                        <el-input type="password" v-model="formData.password2" clearable show-password placeholder="请再次输入密码"></el-input>
+                    </el-form-item>
+                </el-col>
+            </el-row>
+        </el-form>
+        <template #footer>
+            <el-button @click="visible = false">取 消</el-button>
+            <el-button type="primary" :loading="isSaveing" @click="submit()">提交</el-button>
+        </template>
+    </el-dialog>
+</template>
+
+<script>
+export default {
+    data(){
+        return {
+            loading: false,
+            mode:"add",
+            titleMap:{
+                add:"新增账号",
+                edit:"编辑账号"
+            },
+            rules:{
+                truename: [
+                    {required: true, message: '请输入'}
+                ],
+                password: [
+                    {required: true, message: '请输入登录密码'}
+                ],
+                password2: [
+                    {required: true, message: '请再次输入密码'},
+                    {validator: (rule, value, callback) => {
+                        if (value !== this.formData.password) {
+                            callback(new Error('两次输入密码不一致!'));
+                        }else{
+                            callback();
+                        }
+                    }}
+                ],
+                mobile: [
+                    { required: true, message: this.$t('login.mobileError'), trigger: 'blur' },
+                    {
+                        validator: (rule, value, callback) => {
+                            const phoneReg = /^1[3-9]\d{9}$/ // 手机号正则
+                            const landlineReg = /^(?:(?:\d{3}-)?\d{8}|^(?:\d{4}-)?\d{7,8})(?:-\d+)?$/
+                            if (!value) {
+                                callback(new Error('请输入联系方式'))
+                            } else if (!phoneReg.test(value) && !landlineReg.test(value)) {
+                                callback(new Error('请输入有效的手机号码号码'))
+                            } else {
+                                callback()
+                            }
+                        },
+                        trigger: 'blur'
+                    }
+                ],
+                yzm: [
+                    {required: true, message: this.$t('login.smsError')}
+                ],
+                captcha: [
+                    {required: true, message: this.$t('login.codeErr')}
+                ],
+            },
+            visible: false,
+            isSaveing: false,
+            formData:{},
+            captcha:{},
+            dataForm:{}
+        }
+    },
+    methods:{
+        open(mode = 'add'){
+            this.mode = mode;
+            this.visible = true;
+            if (mode == 'add') {
+                this.getCaptcha();
+            }
+            return this
+        },
+        async getCaptcha(){
+            var resp = await this.$API.common.captcha.get();
+            if (resp.code == 0) {
+                return this.$message.error(resp.msg);
+            }
+            this.captcha = resp.data;
+        },
+        async getYzm(){
+			var field = ["mobile","captcha"];
+			this.$refs.dialogForm.validateField(field, async (valid) => {
+				if(!valid){
+					return false
+				}
+                var resp = await this.$API.common.sms.post({"mobile":this.formData.mobile,"code":this.formData.captcha,"key":this.captcha.key,"scene":"register"});
+                if (resp.code == 0) {
+                    this.getCaptcha();
+                    return this.$message.error(resp.msg);
+                }
+                this.$message.success(resp.msg)
+                this.disabled = true
+                this.time = 60
+                var t = setInterval(() => {
+                    this.time -= 1
+                    if(this.time < 1){
+                        clearInterval(t)
+                        this.disabled = false
+                        this.time = 0
+                    }
+                },1000)
+            });            
+        },
+        //表单注入数据
+        setData(data){
+            if (this.mode == 'edit') {
+                this.formData.truename = data.truename;
+                this.formData.id = data.id;
+            }
+            this.dataForm = data;
+        },
+        async submit(){
+            var validate = await this.$refs.dialogForm.validate().catch(()=>{});
+            if(!validate){ return false }
+            let submitData = JSON.parse(JSON.stringify(this.formData));
+            submitData.password = this.$TOOL.crypto.MD5(this.formData.password)
+            submitData.password2 = this.$TOOL.crypto.MD5(this.formData.password2)
+            if (this.mode == 'add') {
+                submitData.scene = "register";
+                submitData.agent_id = this.dataForm.agent_id;
+                submitData.vip_at = this.$TOOL.dateFormat(this.dataForm.vip_at, "yyyy-MM-dd");
+            }
+            this.isSaveing = true;
+            var resp = await this.$API.user.save.post(submitData);
+            this.isSaveing = false;
+            if (resp.code == 0) {
+                return this.$message.error(resp.msg);
+            }
+            this.$message.success(resp.msg);
+            this.visible = false;
+            this.$emit("success");
+        }
+    }
+}
+</script>

+ 149 - 0
src/views/manage/user/merchant/user/list.vue

@@ -0,0 +1,149 @@
+<template>
+    <el-drawer :title="titleMap[mode]" :append-to-body="true" v-model="visible" :size="1000" destroy-on-close :close-on-click-modal="false" @closed="$emit('closed')" :with-header="false">
+        <el-container class="flex-column" v-loading="loading">
+            <div class="drawer-detail-main">
+                <div class="drawer-detail-header">
+                    <div class="drawer-detail-header-body">
+                        <div class="drawer-detail-header-left">{{ titleMap[mode] }} <span class="tips">{{ formData.truename }}</span></div>
+                        <div class="drawer-detail-header-left">
+                            <el-button type="default" icon="el-icon-close" @click="visible=false"></el-button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="table-search">
+                <search @success="handleSuccess"></search>
+                <optionBtn @success="handleSuccess" :agent="formData" :dataSelect="dataSelect" :dataSelectFull="dataSelectFull" ></optionBtn>
+            </div>
+            <el-main>
+                <scTable ref="table" :apiObj="list.apiObj" :params="searchKey" @selectionChange="selectionChange" row-key="id">
+                    <el-table-column type="selection" width="50" fixed="left"></el-table-column>
+                    <el-table-column label="登录账号" prop="truename" width="150" fixed="left">
+                        <template #default="scope">
+                            <span v-if="scope.row.username">{{ scope.row.username }}</span>
+                            <span class="status-danger" v-else>未设置</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="账号ID" prop="user_id" width="150"></el-table-column>
+                    <el-table-column label="账号名称" prop="truename" width="200">
+                        <template #default="scope">
+                            <span v-if="scope.row.truename">{{ scope.row.truename }}</span>
+                            <span class="status-danger" v-else>未设置</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="手机号码" prop="mobile" width="150">
+                        <template #default="scope">
+                            <span v-if="scope.row.mobile">{{ scope.row.mobile }}</span>
+                            <span class="status-danger" v-else>-</span>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="类型" prop="type" width="120" align="center">
+                        <template #default="scope">
+                            <div class="status-success" v-if="scope.row.type==2 && formData.agent_id == scope.row.user_id"><sc-status-indicator type="success"></sc-status-indicator> 主账号</div>
+                            <div class="status-success" v-if="scope.row.type==2 && formData.agent_id !== scope.row.user_id"><sc-status-indicator type="success"></sc-status-indicator> 子账号</div>
+                            <div class="status-danger" v-if="scope.row.type==3"><sc-status-indicator type="danger"></sc-status-indicator> 门店账号</div>
+                            <div class="status-danger" v-if="scope.row.type==4"><sc-status-indicator type="danger"></sc-status-indicator> 洗衣地址账号</div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="状态" prop="status" width="120" align="center">
+                        <template #default="scope">
+                            <div class="status-success" v-if="scope.row.status==1"><sc-status-indicator type="success"></sc-status-indicator> 正常</div>
+                            <div class="status-danger" v-if="scope.row.status==2"><sc-status-indicator type="danger"></sc-status-indicator> 已冻结</div>
+                        </template>
+                    </el-table-column>
+                    <el-table-column label="创建时间" prop="create_at" width="180"></el-table-column>
+                    <el-table-column label="操作" width="120" align="right" fixed="right">
+                        <template #default="scope">
+                            <el-button-group>
+                                <el-button text type="warning" size="small" @click="table_edit(scope.row)">编辑</el-button>
+                                <el-popconfirm title="确定删除吗?" @confirm="table_del(scope.row, scope.$index)">
+                                    <template #reference>
+                                        <el-button text type="danger" size="small">删除</el-button>
+                                    </template>
+                                </el-popconfirm>                    
+                            </el-button-group>
+                        </template>
+                    </el-table-column>
+                </scTable>
+            </el-main>
+            <el-footer>
+                <el-button @click="visible=false">关 闭</el-button>
+            </el-footer>
+        </el-container>
+    </el-drawer>
+    <formMain ref="formMain" @success="handleSuccess"></formMain>
+</template>
+
+<script>
+import search from './search';
+import optionBtn from './option';
+import formMain from './form';
+export default{
+    components: {
+        search,optionBtn,formMain
+    },
+    data(){
+        return {
+            loading: false,
+            mode:"add",
+            visible: false,
+            titleMap:{
+                add:"代理名下用户",
+                edit:"代理名下用户"
+            },
+            list: {
+                apiObj: this.$API.user.list
+            },
+            formData:{},
+            searchKey:{},
+            dataSelect:[],
+            dataSelectFull:[],
+        }
+    },
+    methods:{
+        async table_del(data){
+            var resp = await this.$API.user.del.post({"id":data.id});
+            if (resp.code == 0) {
+                return this.$message.warning(resp.msg);
+            }
+            this.$message.success(resp.msg);
+            this.$refs.table.refresh()
+        },
+        table_edit(row){
+            this.$nextTick(() => {
+                this.$refs.formMain.open("edit").setData(row)
+            })
+        },
+        open(mode = 'add'){
+            this.mode = mode;
+            this.visible = true;
+            return this
+        },
+        //表单注入数据
+        setData(data){
+            this.formData = data;
+            this.searchKey.agent = data.agent_id;
+        },
+        selectionChange(event){
+            this.dataSelect = [];
+            var arr = [];
+            var arrCompany = [];
+            event.forEach(function(val,index){
+                arr[index] = val.id;
+                arrCompany[index] = val;
+            });
+            this.dataSelectFull = arrCompany;
+            this.dataSelect = arr;
+        },
+        refresh(){
+            this.$refs.table.refresh()
+        },
+        upData(data){
+            this.$refs.table.upData(data)
+        },
+        handleSuccess(data){
+            this.$refs.table.upData(data)
+        },
+    }
+}
+</script>

+ 56 - 0
src/views/manage/user/merchant/user/option.vue

@@ -0,0 +1,56 @@
+<template>
+    <fieldset>
+        <legend>
+            <el-tag type="info">按需操作</el-tag>
+        </legend>
+        <div class="op-header">
+            <div class="left-panel">
+                <el-button type="success" icon="el-icon-plus" @click="table_add()">新增账号</el-button>
+                <el-button icon="el-icon-document" @click="table_batch_status(1)" :disabled="dataSelect.length>0?false:true">启用</el-button>
+                <el-button icon="el-icon-lock" @click="table_batch_status(2)" :disabled="dataSelect.length>0?false:true">冻结</el-button>
+            </div>
+        </div>
+    </fieldset>
+    <formMain ref="formMain" @success="handleSuccess"></formMain>
+</template>
+
+<script>
+import formMain from './form';
+export default {
+    components: {
+        formMain
+    },
+    props: {
+        agent: { type: Object, default: {} },
+        dataSelect: { type: Array, default: () => [] },
+        dataSelectFull: { type: Array, default: () => [] }
+    },
+    data(){
+        return {
+
+        }
+    },
+    methods: {
+        handleSuccess(){
+            this.$emit("success");
+        },
+        async table_batch_status(status){
+            if (this.dataSelect.length == 0) {
+                return this.$message.error("请选择修改数据")
+            }
+            let submitData = {"id":this.dataSelect,"value":status,"field":"status","type":"batch"};
+            var resp = await this.$API.user.batch.post(submitData);
+            if (resp.code == 0) {
+                return this.$message.error(resp.msg);
+            }
+            this.$message.success(resp.msg);
+            this.$emit("success");
+        },
+        table_add(){
+            this.$nextTick(() => {
+                this.$refs.formMain.open().setData(this.agent)
+            })
+        },
+    }
+}
+</script>

+ 54 - 0
src/views/manage/user/merchant/user/search.vue

@@ -0,0 +1,54 @@
+<template>
+    <fieldset>
+        <legend>
+            <el-tag type="info">条件筛选</el-tag>
+        </legend>
+        <el-form class="lv-form-inline" ref="searchForm" :model="searchKey" label-position="right" label-width="100px">
+            <div class="search-form">
+                <div class="form-left">
+                    <el-row :gutter="10">
+                        <el-col :span="this.$store.state.global.ismobile?12:12">
+                            <el-input v-model="searchKey.username" placeholder="登录账号" clearable :style="{ width: '100%' }" @keyup.enter="searchForm()">
+                                <template #prepend>登录账号</template>
+                            </el-input>
+                        </el-col>
+                        <el-col :span="this.$store.state.global.ismobile?12:12">
+                            <el-input v-model="searchKey.mobile" placeholder="手机号码" clearable :style="{ width: '100%' }" @keyup.enter="searchForm()">
+                                <template #prepend>手机号码</template>
+                            </el-input>
+                        </el-col>
+                        <el-col :span="this.$store.state.global.ismobile?12:12">
+                            <el-select v-model="searchKey.status" clearable placeholder="请选择状态" @change="searchForm" :style="{width: '100%'}" class="diy-select">
+                                <el-option value="2" label="正常"></el-option>
+                                <el-option value="3" label="已冻结"></el-option>
+                                <template #prefix>状态</template>
+                            </el-select>
+                        </el-col>
+                        <el-col :span="this.$store.state.global.ismobile?12:12">
+                            <el-date-picker v-model="searchKey.create" :style="{width: '100%'}" placeholder="请选择创建时间" start-placeholder="开始时间" end-placeholder="结束时间" type="daterange" range-separator="至" @change="searchForm" />
+                        </el-col>
+                    </el-row>
+                </div>
+                <div class="form-line"></div>
+                <div class="form-right">
+                    <el-button type="primary" icon="el-icon-search" @click="searchForm">搜索</el-button>
+                </div>
+            </div>
+        </el-form>
+    </fieldset>
+</template>
+
+<script>
+export default {
+    data(){
+        return {
+            searchKey:{}
+        }
+    },
+    methods: {
+        searchForm(){
+            this.$emit("success",this.searchKey);
+        }
+    }
+}
+</script>

+ 360 - 0
src/views/manage/user/store/components/form.vue

@@ -0,0 +1,360 @@
+<template>
+    <el-drawer :title="titleMap[mode]" :append-to-body="true" v-model="visible" :size="800" destroy-on-close :close-on-click-modal="false" @closed="$emit('closed')" :with-header="false">
+        <el-container class="flex-column" v-loading="loading">
+            <div class="drawer-detail-main">
+                <div class="drawer-detail-header">
+                    <div class="drawer-detail-header-body">
+                        <div class="drawer-detail-header-left">{{ titleMap[mode] }} <span class="tips"></span></div>
+                        <div class="drawer-detail-header-left">
+                            <el-button type="default" icon="el-icon-close" @click="visible=false"></el-button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <el-steps simple :active="stepActive" finish-status="success">
+                <el-step title="基础信息"></el-step>
+                <el-step title="其他信息"></el-step>
+                <el-step title="财务配置"></el-step>
+                <el-step title="角色账号"></el-step>
+            </el-steps>
+            <el-main>
+                <el-form ref="dialogForm" :model="formData" :rules="rules" label-width="100px" label-position="top">
+                    <template v-if="stepActive==1">
+                        <el-form-item label="所属代理" prop="agent_id">
+                            <el-input v-model="formData.agent_id" clearable placeholder="请选择代理" readonly :style="{ width: '100%' }" @click="selectUser">
+                                <template #append>
+                                    <el-tooltip
+                                        effect="dark"
+                                        content="点这里,清除选择"
+                                        placement="top-start"
+                                    >
+                                    <div class="remove-a" @click="clearUser">清除</div>
+                                    </el-tooltip>
+                                </template>
+                            </el-input>
+                        </el-form-item>
+                        <el-form-item label="门店编码" prop="store_code">
+                            <el-input v-model="formData.store_code" placeholder="根据编号规则自动生成" clearable :style="{ width: '100%' }">
+                                <template #append><el-button @click="generateRandomNumber">生成</el-button></template>
+                            </el-input>
+                        </el-form-item>
+                        <el-row :gutter="10">
+                            <el-col :span="12">
+                                <el-form-item label="门店名称" prop="truename">
+                                    <el-input v-model="formData.truename" clearable placeholder="请输入门店名称"></el-input>
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="12">
+                                <el-form-item label="店长名称" prop="store_mch">
+                                    <el-input v-model="formData.store_mch" clearable placeholder="请输入店长名称"></el-input>
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="12">
+                                <el-form-item label="门店类型" prop="store_type">
+                                    <el-select v-model="formData.store_type" placeholder="请选择门店类型">
+                                        <el-option label="洗护实体店" :value="1"></el-option>
+                                        <el-option label="洗护代收店" :value="2"></el-option>
+                                        <el-option label="洗护美团店" :value="3"></el-option>
+                                        <el-option label="洗护抖音店" :value="4"></el-option>
+                                        <el-option label="商城自提店" :value="5"></el-option>
+                                        <el-option label="洗护口碑店" :value="6"></el-option>
+                                    </el-select>
+                                </el-form-item>
+                            </el-col>
+                            <el-col :span="12">
+                                <el-form-item label="洗衣能力" prop="wash_type">
+                                    <el-radio-group v-model="formData.wash_type">
+                                        <el-radio border :label="1">门店自洗</el-radio>
+                                        <el-radio border :label="2">洗衣地址</el-radio>
+                                    </el-radio-group>
+                                </el-form-item>
+                            </el-col>
+                        </el-row>
+                        <el-form-item label="门店地址" prop="store_address">
+                            <el-input v-model="formData.store_address" clearable placeholder="请输入门店地址"></el-input>
+                        </el-form-item>
+                    </template>
+                    
+                    <template class="mt20" v-if="stepActive==2">
+                        <el-form-item label="营业执照" prop="license">
+                            <sc-upload accept="image/gif,image/jpeg,image/jpg,image/png" v-model="formData.license" title="大小不超过10M"></sc-upload>
+                        </el-form-item>
+                        <el-form-item label="门店状态" prop="store_status">
+                            <el-radio-group v-model="formData.store_status">
+                                <el-radio :label="1">已启用</el-radio>
+                                <el-radio :label="2">已失效</el-radio>
+                            </el-radio-group>
+                        </el-form-item>
+                        <el-form-item label="自建商品" prop="store_goods">
+                            <el-radio-group v-model="formData.store_goods">
+                                <el-radio :label="1">开启</el-radio>
+                                <el-radio :label="2">关闭</el-radio>
+                            </el-radio-group>
+                            <div class="el-form-item-msg">温馨提示:开启后,门店可自主创建、发布商品并售卖。总部可进行查看、上下架和删除等管理操作</div>
+                        </el-form-item>
+                        <el-form-item label="总部审核" prop="store_system">
+                            <el-radio-group v-model="formData.store_system">
+                                <el-radio :label="1">手动审核</el-radio>
+                                <el-radio :label="2">自动通过审核</el-radio>
+                            </el-radio-group>
+                            <div class="el-form-item-msg">温馨提示:手动审核时,总部需要审核通过店铺自主创建的商品后,店铺才能销售该商品</div>
+                        </el-form-item>
+                    </template>
+                    <template class="mt20" v-if="stepActive==3">
+                        <el-form-item label="独立财务" prop="store_order">
+                            <el-radio-group v-model="formData.store_order">
+                                <el-radio :label="1">关闭</el-radio>
+                                <el-radio :label="2">开启</el-radio>
+                            </el-radio-group>
+                            <div class="el-form-item-msg">温馨提示:开启独立财务后,该门店将实施单独扣费,费用不足时无法发送短信等功能</div>
+                        </el-form-item>
+                        <el-form-item label="短信收费" prop="store_sms" v-if="formData.store_order==2">
+                            <el-input v-model="formData.store_sms" clearable placeholder="请输入短信费用">
+                                <template #append>元/条</template>
+                            </el-input>
+                        </el-form-item>
+                        <el-form-item label="快递加价" prop="store_express" v-if="formData.store_order==2">
+                            <el-input v-model="formData.store_express" clearable placeholder="请输入快递溢价">
+                                <template #append>元/次</template>
+                            </el-input>
+                        </el-form-item>
+                        <el-form-item label="网单收费加价(短信、快递加价失效)" prop="store_inter_order" v-if="formData.store_order==2">
+                            <el-input v-model="formData.store_inter_order" clearable placeholder="请输入网单收费">
+                                <template #append>元/单</template>
+                            </el-input>
+                            <div class="el-form-item-msg"></div>
+                        </el-form-item>
+                    </template>
+                    <template class="mt20" v-if="stepActive==4">
+                        <el-form-item label="登录账号" prop="username">
+                            <el-input v-model="formData.username" clearable placeholder="请输入登录账号"></el-input>
+                            <div class="el-form-item-msg">不设置登录账号可以使用手机号码登录</div>
+                        </el-form-item>
+                        <el-form-item prop="mobile" :label="$t('login.mobilePlaceholder')">
+                            <el-input v-model="formData.mobile" clearable :placeholder="$t('login.mobilePlaceholder')">
+                                <template #prepend>+86</template>
+                            </el-input>
+                        </el-form-item>
+                        <el-form-item prop="yzm" :label="$t('login.smsPlaceholder')">
+                            <div class="login-msg-yzm">
+                                <el-input v-model="formData.yzm" clearable :placeholder="$t('login.smsPlaceholder')"></el-input>
+                                <el-button @click="getYzm" :disabled="disabled">{{this.$t('login.smsGet')}}<span v-if="disabled"> ({{time}})</span></el-button>
+                            </div>
+                        </el-form-item>
+                        <el-form-item prop="captcha" :label="$t('login.code')">
+                            <div class="login-msg-yzm">
+                                <el-input v-model="formData.captcha" clearable :placeholder="$t('login.codeErr')"></el-input>
+                                <el-tooltip placement="top-start" :content="$t('login.codeTips')">
+                                    <div class="captcha" @click="getCaptcha"><img :src="captcha.base64" /></div>
+                                </el-tooltip>
+                            </div>
+                        </el-form-item>
+                        <el-form-item label="登录密码" prop="password">
+                            <el-input type="password" v-model="formData.password" clearable show-password placeholder="请输入登录密码"></el-input>
+                        </el-form-item>
+                        <el-form-item label="确认密码" prop="password2">
+                            <el-input type="password" v-model="formData.password2" clearable show-password placeholder="请再次输入密码"></el-input>
+                        </el-form-item>
+                    </template>
+                </el-form>
+            </el-main>
+            <el-footer style="text-align: right;">
+                <el-button @click="cancel">取 消</el-button>
+                <el-button type="danger" :loading="isSaveing" @click="submitPre()" v-if="stepActive > 1 ">上一步</el-button>
+                <el-button type="primary" :loading="isSaveing" @click="submit(stepActive)">{{ stepActive==4?'提交':'下一步' }}</el-button>
+            </el-footer>
+        </el-container>
+    </el-drawer>
+    <agentData ref="agentData" :multiple="false" @success="handleSuccess"></agentData>
+</template>
+
+<script>
+import agentData from "@/views/manage/components/agent";
+export default {
+    components: {
+        agentData
+    },
+    data(){
+        return {
+            loading: false,
+            mode:"add",
+            visible: false,
+            titleMap:{
+                add:"新增门店",
+                edit:"编辑门店"
+            },
+            stepActive:1,
+            formData:{
+                license:"https://washmy.oss-cn-guangzhou.aliyuncs.com/storage/5e1a79764c588ff81d0e09ccc26d2c85c9a6425f.png", // https://washmy.oss-cn-guangzhou.aliyuncs.com/storage/5e1a79764c588ff81d0e09ccc26d2c85c9a6425f.png
+            },
+            rules:{
+                store_order: [
+                    {required: true, message: '请选择'}
+                ],
+                store_status: [
+                    {required: true, message: '请选择'}
+                ],
+                store_goods: [
+                    {required: true, message: '请选择'}
+                ],
+                store_system: [
+                    {required: true, message: '请选择'}
+                ],
+                agent_id: [
+                    {required: true, message: '请选择'}
+                ],
+                wash_type: [
+                    {required: true, message: '请选择'}
+                ],
+                truename: [
+                    {required: true, message: '请输入门店名称'}
+                ],
+                store_mch: [
+                    {required: true, message: '请输入店长名称'}
+                ],
+                store_type: [
+                    {required: true, message: '请选择门店类型'}
+                ],
+                store_address: [
+                    {required: true, message: '请输入门店地址'}
+                ],
+                password: [
+                    {required: true, message: '请输入登录密码'}
+                ],
+                password2: [
+                    {required: true, message: '请再次输入密码'},
+                    {validator: (rule, value, callback) => {
+                        if (value !== this.formData.password) {
+                            callback(new Error('两次输入密码不一致!'));
+                        }else{
+                            callback();
+                        }
+                    }}
+                ],
+                mobile: [
+                    { required: true, message: this.$t('login.mobileError'), trigger: 'blur' },
+                    {
+                        validator: (rule, value, callback) => {
+                            const phoneReg = /^1[3-9]\d{9}$/ // 手机号正则
+                            const landlineReg = /^(?:(?:\d{3}-)?\d{8}|^(?:\d{4}-)?\d{7,8})(?:-\d+)?$/
+                            if (!value) {
+                                callback(new Error('请输入联系方式'))
+                            } else if (!phoneReg.test(value) && !landlineReg.test(value)) {
+                                callback(new Error('请输入有效的手机号码号码'))
+                            } else {
+                                callback()
+                            }
+                        },
+                        trigger: 'blur'
+                    }
+                ],
+                yzm: [
+                    {required: true, message: this.$t('login.smsError')}
+                ],
+                captcha: [
+                    {required: true, message: this.$t('login.codeErr')}
+                ],
+                license: [
+                    {required: true, message: "请上传营业执照"}
+                ],
+            },
+            captcha:{}
+        }
+    },
+    methods: {
+        open(mode = 'add'){
+            this.mode = mode;
+            this.visible = true;
+            this.generateRandomNumber()
+            if (mode == 'add') {
+                this.getCaptcha();
+            }
+            return this
+        },
+        submitPre(){
+            this.stepActive--
+        },
+        async getCaptcha(){
+            var resp = await this.$API.common.captcha.get();
+            if (resp.code == 0) {
+                return this.$message.error(resp.msg);
+            }
+            this.captcha = resp.data;
+        },
+        async getYzm(){
+			var field = ["mobile","captcha"];
+			this.$refs.dialogForm.validateField(field, async (valid) => {
+				if(!valid){
+					return false
+				}
+                var resp = await this.$API.common.sms.post({"mobile":this.formData.mobile,"code":this.formData.captcha,"key":this.captcha.key,"scene":"register"});
+                if (resp.code == 0) {
+                    this.getCaptcha();
+                    return this.$message.error(resp.msg);
+                }
+                this.$message.success(resp.msg)
+                this.disabled = true
+                this.time = 60
+                var t = setInterval(() => {
+                    this.time -= 1
+                    if(this.time < 1){
+                        clearInterval(t)
+                        this.disabled = false
+                        this.time = 0
+                    }
+                },1000)
+            });            
+        },
+        generateRandomNumber() {
+            this.formData.store_code = "DF"+Math.random().toString().slice(2, 13);
+        },
+        //表单注入数据
+        setData(data){
+            this.formData = data;
+        },
+        cancel(){
+            this.formData = {store_system:2,store_goods:1,store_status:1};
+            this.stepActive = 1;
+            this.visible = false;
+        },
+        handleSuccess(data){
+            this.formData.agent_id = data.agent_id;
+        },
+        clearUser(){
+            this.formData.agent_id = "";
+        },
+        selectUser(){
+            this.$nextTick(() => {
+                this.$refs.agentData.open()
+            })
+        },
+        async submit(){
+            var validate = await this.$refs.dialogForm.validate().catch(()=>{});
+            if(!validate){ return false }
+            if (this.stepActive < 4) {
+                this.stepActive++;
+            } else {
+                this.submitState = true;
+            }
+            let submitData = JSON.parse(JSON.stringify(this.formData));
+            if (this.submitState) {
+				submitData.password = this.$TOOL.crypto.MD5(this.formData.password)
+				submitData.password2 = this.$TOOL.crypto.MD5(this.formData.password2)
+				submitData.scene = "register";
+                this.isSaveing = true;
+                var resp = await this.$API.store.save.post(submitData);
+                this.isSaveing = false;
+                if (resp.code == 0) {
+                    return this.$message.error(resp.msg);
+                }
+                this.$message.success(resp.msg);
+                this.visible = false;
+                this.formData = {};
+                this.stepActive = 1;
+                this.$emit("success");
+            }
+        }
+
+    }
+}
+</script>

+ 46 - 0
src/views/manage/user/store/components/option.vue

@@ -0,0 +1,46 @@
+<template>
+    <fieldset>
+        <legend>
+            <el-tag type="info">按需操作</el-tag>
+        </legend>
+        <div class="op-header">
+            <div class="left-panel">
+                <el-button type="success" icon="el-icon-plus" @click="table_add()">新增门店</el-button>
+                <el-button icon="el-icon-delete" @click="table_del()" :disabled="dataSelect.length>0?false:true">删除</el-button>
+                <el-button icon="el-icon-document" @click="table_batch_status(0)" :disabled="dataSelect.length>0?false:true">启用</el-button>
+                <el-button icon="el-icon-lock" @click="table_batch_status(3)" :disabled="dataSelect.length>0?false:true">禁用</el-button>
+                <!-- <el-button type="primary" icon="el-icon-download" @click="table_export()">导出</el-button> -->
+            </div>
+        </div>
+    </fieldset>
+    <formMain ref="formMain" @success="handleSuccess"></formMain>
+</template>
+
+<script>
+import formMain from './form';
+export default {
+    components: {
+        formMain
+    },
+    props: {
+        type: { type: String, default: "1" },
+        dataSelect: { type: Array, default: () => [] },
+        dataSelectFull: { type: Array, default: () => [] }
+    },
+    data(){
+        return {
+
+        }
+    },
+    methods: {
+        handleSuccess(){
+            this.$emit("success");
+        },
+        table_add(){
+            this.$nextTick(() => {
+                this.$refs.formMain.open()
+            })
+        },
+    }
+}
+</script>

+ 91 - 0
src/views/manage/user/store/components/search.vue

@@ -0,0 +1,91 @@
+<template>
+    <fieldset>
+        <legend>
+            <el-tag type="info">条件筛选</el-tag>
+        </legend>
+        <el-form class="lv-form-inline" ref="searchForm" :model="searchKey" label-position="right" label-width="100px">
+            <div class="search-form">
+                <div class="form-left">
+                    <el-row :gutter="10">
+                        <el-col :span="this.$store.state.global.ismobile?12:4">
+                            <el-input v-model="searchKey.agent" placeholder="选择代理" clearable readonly :style="{ width: '100%' }" @click="selectUser">
+                                <template #append>
+                                    <el-tooltip
+                                        effect="dark"
+                                        content="点这里,清除选择"
+                                        placement="top-start"
+                                    >
+                                    <div class="remove-a" @click="clearUser">清除</div>
+                                    </el-tooltip>
+                                </template>
+                                <template #prepend>所属代理</template>
+                            </el-input>
+                        </el-col>
+                        <el-col :span="this.$store.state.global.ismobile?12:4">
+                            <el-input v-model="searchKey.truename" placeholder="门店名称" clearable :style="{ width: '100%' }" @keyup.enter="searchForm()">
+                                <template #prepend>门店名称</template>
+                            </el-input>
+                        </el-col>
+                        <el-col :span="this.$store.state.global.ismobile?12:4">
+                            <el-input v-model="searchKey.contact" placeholder="联系人" clearable :style="{ width: '100%' }" @keyup.enter="searchForm()">
+                                <template #prepend>联系人</template>
+                            </el-input>
+                        </el-col>
+                        <el-col :span="this.$store.state.global.ismobile?12:4">
+                            <el-input v-model="searchKey.mobile" placeholder="手机号码" clearable :style="{ width: '100%' }" @keyup.enter="searchForm()">
+                                <template #prepend>手机号码</template>
+                            </el-input>
+                        </el-col>
+                        <el-col :span="this.$store.state.global.ismobile?12:4">
+                            <el-select v-model="searchKey.status" clearable placeholder="请选择状态" @change="searchForm" :style="{width: '100%'}" class="diy-select">
+                                <el-option value="1" label="正常"></el-option>
+                                <el-option value="2" label="已冻结"></el-option>
+                                <el-option value="3" label="已过期"></el-option>
+                                <template #prefix>状态</template>
+                            </el-select>
+                        </el-col>
+                        <el-col :span="this.$store.state.global.ismobile?12:4">
+                            <el-date-picker v-model="searchKey.create" :style="{width: '100%'}" placeholder="请选择创建时间" start-placeholder="开始时间" end-placeholder="结束时间" type="daterange" range-separator="至" @change="searchForm" />
+                        </el-col>
+                    </el-row>
+                </div>
+                <div class="form-line"></div>
+                <div class="form-right">
+                    <el-button type="primary" icon="el-icon-search" @click="searchForm">搜索</el-button>
+                </div>
+            </div>
+        </el-form>
+    </fieldset>
+    <agentData ref="agentData" :multiple="false" @success="handleSuccess"></agentData>
+</template>
+
+<script>
+import agentData from "@/views/manage/components/agent";
+export default {
+    components: {
+        agentData
+    },
+    data(){
+        return {
+            searchKey:{}
+        }
+    },
+    methods: {
+        handleSuccess(data){
+            this.searchKey.agent = data.agent_id;
+            this.$emit("success",this.searchKey);
+        },
+        clearUser(){
+            this.searchKey.agent = "";
+        },
+        selectUser(){
+            this.$nextTick(() => {
+                this.$refs.agentData.open()
+            })
+        },
+        searchForm(){
+            this.$emit("success",this.searchKey);
+        }
+    }
+}
+</script>

+ 7 - 0
src/views/manage/user/store/components/table.vue

@@ -0,0 +1,7 @@
+<template>
+    <div></div>
+</template>
+
+<script>
+
+</script>

+ 65 - 0
src/views/manage/user/store/index.vue

@@ -0,0 +1,65 @@
+<template>
+    <el-container class="flex-column">
+        <div class="channel_menu">
+            <el-menu mode="horizontal" class="channel-tabs" :default-active="activeName" @select="handleClick">
+                <el-menu-item :index="item.key" v-for="(item,indx) in menuData" :key="indx">{{item.name}}</el-menu-item>
+            </el-menu>
+        </div>
+        <div class="table-search">
+            <search @success="handleSuccess"></search>
+            <optionBtn @success="handleSuccess" :dataSelect="dataSelect" :dataSelectFull="dataSelectFull" ></optionBtn>
+        </div>
+        <el-main class="nopadding">
+            <div class="table-container">
+                <tablePage ref="tablePage" @success="tableHandle" @successFull="tableHandleFull"></tablePage>
+            </div>
+        </el-main>
+    </el-container>  
+</template>
+
+<script>
+import search from './components/search';
+import optionBtn from './components/option';
+import tablePage from './components/table';
+export default {
+    components: {
+        search,tablePage,optionBtn
+    },
+    data(){
+        return {
+            activeName:"first",
+            menuData:[],
+            searchKey:{},
+            dataSelect:[],
+            dataSelectFull:[],
+        }
+    },
+    mounted(){
+        // this.getMenuData();
+    },
+    methods: {
+        tableHandle(data){
+            this.dataSelect = data;
+        },
+        tableHandleFull(data){
+            this.dataSelectFull = data;
+        },
+        handleSuccess(data){
+            this.$refs.tablePage.upData(data)
+        },
+        async getMenuData(){
+            var resp = await this.$API.common.menu.get({"type":"account"});
+            if (resp.code !== 1) {
+                return this.$message.error(resp.msg);
+            }
+            this.activeName = resp.data.default;
+            this.menuData = resp.data.menu;
+        },
+        handleClick(name){
+            this.activeName = name;
+            this.searchKey.type = name;
+            this.$refs.tablePage.upData(this.searchKey)
+        }
+    }
+}
+</script>