zory 2 days ago
parent
commit
e12c210c75

BIN
public/img/新建项目.jpg


+ 12 - 0
src/api/model/mMember.js

@@ -0,0 +1,12 @@
+import config from "@/config";
+import http from "@/utils/request";
+
+export default {
+    detail: {
+        url: `${config.API_URL}/mer/renew/detail`,
+        name: "-",
+        get: async function (params) {
+            return await http.get(this.url, params);
+        },
+    },
+}

+ 47 - 0
src/api/model/mRenew.js

@@ -0,0 +1,47 @@
+import config from "@/config";
+import http from "@/utils/request";
+
+export default {
+    detail: {
+        url: `${config.API_URL}/mer/renew/detail`,
+        name: "-",
+        get: async function (params) {
+            return await http.get(this.url, params);
+        },
+    },
+    qrcode: {
+        url: `${config.API_URL}/mer/renew/qrcode`,
+        name: "-",
+        post: async function (params) {
+            return await http.post(this.url, params);
+        },
+    },
+    list: {
+        url: `${config.API_URL}/mer/renew/list`,
+        name: "-",
+        get: async function (params) {
+            return await http.get(this.url, params);
+        },
+    },
+    passwd: {
+        url: `${config.API_URL}/mer/staff/passwd`,
+        name: "-",
+        post: async function (params) {
+            return await http.post(this.url, params);
+        },
+    },
+    batch: {
+        url: `${config.API_URL}/mer/staff/batch`,
+        name: "-",
+        post: async function (params) {
+            return await http.post(this.url, params);
+        },
+    },
+    del: {
+        url: `${config.API_URL}/mer/staff/del`,
+        name: "-",
+        post: async function (params) {
+            return await http.post(this.url, params);
+        },
+    },
+}

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

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

+ 46 - 1
src/views/merchant/member/analysis/index.vue

@@ -1,3 +1,48 @@
 <template>
+    <el-container class="flex-column">
+        <div class="table-search">
+            <el-card shadow="never" header="会员卡数据" class="borderNone mt10">
+                <div class="user-card-body">
+                    <div class="card-item">
+                        <div class="card-num">0</div>
+                        <div class="card-tips">会员数量(个) <i class="layui-icon layui-icon-about" data-tips-text="扫描店铺二维码领取会员卡的人数"></i></div>
+                    </div>
+                    <div class="card-item">
+                        <div class="card-num">0</div>
+                        <div class="card-tips">充值人数(个)<i class="layui-icon layui-icon-about" data-tips-text="充值会员卡的人数"></i></div>
+                    </div>
+                    <div class="card-item">
+                        <div class="card-num">0.00</div>
+                        <div class="card-tips">充值总金额(元)<i class="layui-icon layui-icon-about" data-tips-text="会员卡充值金额总和"></i></div>
+                    </div>
+                    <div class="card-item">
+                        <div class="card-num">0.00</div>
+                        <div class="card-tips">剩余余额(元)<i class="layui-icon layui-icon-about" data-tips-text="会员卡剩余余额总和"></i></div>
+                    </div>
+                    <div class="card-item">
+                        <div class="card-num">0.00</div>
+                        <div class="card-tips">历史总金额(元)<i class="layui-icon layui-icon-about" data-tips-text="历史总金额 = 历史的会员充值金额总和 + 充值后的赠送金额总和"></i></div>
+                    </div>
+                    <div class="card-item">
+                        <div class="card-num">0.00</div>
+                        <div class="card-tips">剩余额度(元)<i class="layui-icon layui-icon-about" data-tips-text="店铺会员卡剩余可充值余额=会员卡额度-会员总余额。剩余余额为0时,会员卡将不能充值,需提升额度或会员卡金额消费后才能充值"></i></div>
+                    </div>
+                </div>
+            </el-card>
+        </div>
+        <el-main class="nopadding">
+        </el-main>
+    </el-container>
+</template>
 
-</template>
+<script>
+
+</script>
+
+<style>
+.user-card-body{display: flex;align-items: center;justify-content: space-around;padding: 10px 0;}
+.user-card-body .card-item{text-align: center;}
+.user-card-body .card-tips{font-size: 12px;color: #666;display: flex;align-items: center;}
+.user-card-body .card-tips i{font-style: normal;margin-left: 5px;}
+.user-card-body .card-num{font-size: 20px;font-weight: bold;}
+</style>

+ 86 - 0
src/views/merchant/shop/renew/components/table.vue

@@ -0,0 +1,86 @@
+<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="订单编号" prop="order_sn">
+            <template #default="scope">
+                {{scope.row.order_sn}}
+            </template>
+        </el-table-column>
+        <el-table-column label="套餐信息" prop="time">
+            <template #default="scope">
+                续费<span class="status-danger">{{scope.row.time}}天</span>
+            </template>
+        </el-table-column>
+        <el-table-column label="套餐金额" prop="money">
+            <template #default="scope">
+                {{ scope.row.money }}元
+            </template>
+        </el-table-column>
+        <el-table-column label="支付状态" prop="certificate_id">
+            <template #default="scope">
+                <div class="status-danger" v-if="scope.row.status==0"><sc-status-indicator type="danger"></sc-status-indicator> 待支付</div>
+                <div class="status-success" v-if="scope.row.status==1"><sc-status-indicator type="success"></sc-status-indicator>已完成</div>
+            </template>
+        </el-table-column>
+        <el-table-column label="支付时间" prop="pay_at">
+            <template #default="scope">
+                {{ scope.row.pay_at?scope.row.pay_at:'-' }}
+            </template>
+        </el-table-column>
+        <el-table-column label="创建时间" prop="create_at">
+            <template #default="scope">
+                {{ scope.row.create_at }}
+            </template>
+        </el-table-column>
+    </scTable>
+</template>
+
+<script>
+export default {
+    props: {
+        type: { type: String, default: "1" }
+    },
+    data(){
+        return {
+            colorData:['','彩色','黑白'],
+            duplexData:['','单面','双面'],
+            list: {
+                apiObj: this.$API.mRenew.list
+            },
+            visible:false,
+            dataSelect:[],
+            dataSelectFull:[],
+            searchKey:{
+                type:this.type
+            }
+        }
+    },
+    methods:{
+        table_edit(data){
+            this.$nextTick(() => {
+                this.$refs.formMain.open("edit",this.type).setData(data)
+            })
+        },
+        table_del(data){
+            this.$confirm("确定要删除该数据吗?","删除确认",{type: 'warning'}).then(async ()=>{
+                var resp = await this.$API.mPrice.del.post({"id":data.id,"type":""});
+                if (resp.code == 0) {
+                    return this.$message.error(resp.msg)
+                }
+                this.$message.success(resp.msg)
+                this.$refs.table.refresh()
+            }).catch(()=>{});
+        },
+        refresh(){
+            this.$refs.table.refresh()
+        },
+        upData(data){
+            this.$refs.table.upData(data)
+        },
+        handleSuccess(){
+            this.$refs.table.refresh()
+        },
+    }
+}
+</script>

+ 184 - 1
src/views/merchant/shop/renew/index.vue

@@ -1,3 +1,186 @@
 <template>
+    <el-container class="flex-column">
+        <div class="table-search">
+            <el-tabs v-model="activeName" class="demo-tabs" @tab-change="tabClick">
+                <el-tab-pane label="套餐购买" name="1"></el-tab-pane>
+                <el-tab-pane label="购买记录" name="2"></el-tab-pane>
+            </el-tabs>
+        </div>
+        <el-main class="nopadding">
+            <div class="table-container">
+                <div class="renew-buy" v-if="activeName==1" v-loading="isLoading">
+                    <div class="shop-info">
+                        <div class="info-item">店铺名称:{{ shopData.shop_name }}</div>
+                        <div class="info-item">服务有效期:{{ shopData.vip_end }}</div>
+                        <div class="info-item">
+                            <el-tooltip effect="dark" content="套餐购买时间:从之前套餐到期的时间开始叠加计算" placement="top-start">
+                                <el-icon><el-icon-question-filled /></el-icon>
+                            </el-tooltip>
+                        </div>
+                    </div>
+                    <div class="shop-recharge">
+                        <div class="title">选择服务套餐</div>
+                        <div class="recharge-list">
+                            <div :class="payIndex==indx?'recharge-item active':'recharge-item'" v-for="(item,indx) in comboData" :key="indx" @click="checkPay(indx)">
+                                <div class="name">{{ item.name }}</div>
+                                <div class="price"><span>¥</span>{{ item.f_money }}<i>¥{{ item.f_old_money }}</i></div>
+                                <div class="time">{{ item.time }}{{ item.unit==1?'天':'年' }}</div>
+                                <div class="sale">已优惠{{ item.diff }}元</div>
+                                <div class="check"><el-icon><el-icon-select /></el-icon></div>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="margin-top-15 checkbox-form">
+                        <el-checkbox v-model="privacy" @change="showPrivacy">
+                            <template #default>
+                                <div class="privacy">同意并接受<span>《订购及服务协议》</span></div>
+                            </template>
+                        </el-checkbox>
+                    </div>
+                    <div data-rule-type="1">
+                        <div class="pay-qrcode">
+                            <div class="name">扫码支付</div>
+                            <div class="qrcode-body">
+                                <div class="qrcode-img">
+                                    <div class="img"><img :src="payQrcode"></div>
+                                    <div class="pay-tips">
+                                        <i class="layui-icon layui-icon-login-wechat"></i>扫码支付
+                                    </div>
+                                </div>
+                                <div class="qrcode-money">
+                                    <div class="money"><span>实付:</span>{{ payMoney }}<span>元</span></div>
+                                    <p class="h">温馨提示</p>
+                                    <p>付款后服务立即生效</p>
+                                    <p>多次购买套餐,可叠加服务时间</p>
+                                    <p>开通后,如需发票,请联系客户经理 如有</p>
+                                    <p>其它问题欢迎随时联系客服</p>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <tablePage ref="tablePage" @success="tableHandle" @successFull="tableHandleFull" v-if="activeName==2"></tablePage>
+            </div>
+        </el-main>
+    </el-container>
+	<el-dialog title="订购及服务协议" v-model="visible" :width="680" destroy-on-close :close-on-click-modal="false" :show-close="false">
+		<div class="showPrivacy">
+			<div v-html="privacyTxt"></div>
+		</div>
+		<template #footer>
+			<el-button type="primary" @click="showPrivacyState">我已阅读并同意</el-button>
+		</template>
+	</el-dialog>
+</template>
 
-</template>
+<script>
+import tablePage from './components/table';
+export default {
+    components: {
+        tablePage
+    },
+    data() {
+        return {
+            activeName:"1",
+            isLoading:false,
+            shopData:{},
+            comboData:[],
+            payIndex:0,
+            visible:false,
+            privacy:false,
+            privacyTxt:"",
+            payMoney:0,
+            payQrcode:"https://inmei-print.oss-cn-guangzhou.aliyuncs.com/e2/7ade2a30e1bd50f02b5c245a6d4a28.jpg"
+        }
+    },
+    mounted(){
+        this.getRenewData()
+    },
+    methods: {
+        checkPay(index){
+            this.payIndex = index;
+            this.payMoney = this.comboData[index].f_money
+            this.privacy = false;
+            this.payQrcode = "https://inmei-print.oss-cn-guangzhou.aliyuncs.com/e2/7ade2a30e1bd50f02b5c245a6d4a28.jpg"
+        },
+		showPrivacy(){
+			this.visible = true;
+            this.privacy = false;
+		},
+		async showPrivacyState(){
+			this.visible = false;
+            var comboId = this.comboData[this.payIndex].id;
+            var loading = this.$loading();
+            var resp = await this.$API.mRenew.qrcode.post({"comboId":comboId});
+            loading.close()
+            if (resp.code == 0) {
+                return this.$message.error(resp.msg)
+            }
+            this.payQrcode = resp.data.qrcode;
+			if (this.privacy == false) {
+				this.privacy = true;
+			}
+		},
+        tabClick(event){
+            this.activeName = event;
+        },
+        async getRenewData() {
+            this.isLoading = true;
+            var resp = await this.$API.mRenew.detail.get();
+            this.isLoading = false;
+            if (resp.code == 0) {
+                return this.$message.error(resp.msg)
+            }
+            this.shopData = resp.data.shop;
+            this.comboData = resp.data.combo;
+            this.privacyTxt = resp.data.privacy;
+            this.payMoney = this.comboData[0].f_money
+        }
+    }
+}
+</script>
+
+<style>
+.privacy {
+	color: #333;
+}
+.privacy span {
+	color: #f00;
+}
+.showPrivacy {
+	max-height: 500px;
+	overflow: hidden;
+	overflow-y: scroll;
+	line-height: 1.5;
+}
+.margin-top-15{margin-top: 15px;}
+.shop-info{background-color: #f7f7fa;border-radius: 5px;padding: 15px 25px;display: flex;align-items: center;gap: 20px;font-size: 14px;}
+.shop-info .info-item{display: flex;align-items: center;}
+.shop-recharge .title{font-size: 16px;color: #252631;font-weight: 500;margin: 20px 0;}
+.recharge-list{display: flex;align-items: center;gap: 20px;}
+.recharge-item{border: 1px solid #dedede;border-radius: 10px;width: 298px;height: 160px;position: relative;cursor: pointer;}
+.recharge-item.active{background: #c5e4ff;border: 1px solid #005bac;}
+.recharge-item .name{padding: 24px 20px 16px;font-size: 14px;color: #252631;}
+.recharge-item .price{text-align: center;color: #005bac;font-weight: 600;font-size: 36px;}
+.recharge-item .price span{font-size: 18px;}
+.recharge-item .price i{font-style: normal;font-size: 14px;color: #7c7c7e;text-decoration: line-through;padding-left: 10px;}
+.recharge-item .time{font-size: 18px;color: #005bac;text-align: center;margin: 20px 0;}
+.recharge-item .sale{position: absolute;width: 117px;height: 34px;line-height: 34px;text-align: center;border-radius: 17px 17px 17px 0;box-shadow: 0 2px 11px 0 #ffcbbb;color: #fff;font-size: 14px;font-weight: 500;top: 0;transform: translateY(-50%);right: 0;background: linear-gradient(90deg, #fba67d, #fe7a5f);}
+.recharge-item .check{position: absolute;right: -1px;bottom: -1px;background-color: #005bac;color: #fff;width: 40px;height: 40px;line-height: 40px;text-align: center;border-radius: 10px 0 10px 0;display: none;}
+.recharge-item.active .check{display: block;}
+.recharge-item .check i{font-size: 24px;font-style: normal;font-weight: bold;}
+.checkbox-form{display: flex;align-items: center;}
+.checkbox-form .layui-form-checkbox[lay-skin=primary]>div{padding-right: 0;}
+.pay-qrcode{margin-top: 20px;background-color: #f7f7fa;border-radius: 5px;padding: 15px 25px;}
+.pay-qrcode .name{font-size: 18px;color: #333;margin-bottom: 10px;}
+.qrcode-body{display: flex;align-items: flex-end;}
+.qrcode-img{border: 1px solid #dedede;padding: 10px;border-radius: 10px;background-color: #fff;width: 230px;margin-right: 20px;}
+.qrcode-img .pay-tips{text-align: center;font-size: 14px;color: #333;display: flex;align-items: center;justify-content: center;margin: 20px 0;}
+.qrcode-img .img{height: 230px;display: flex;align-items: center;justify-content: center;}
+.qrcode-img img{width: 100%;height: 100%;}
+.qrcode-img .pay-tips i{padding-right: 5px;color: #1cae5b;font-size: 24px;}
+.qrcode-money .money{font-size: 36px;color: #f00;font-weight: bold;margin-bottom: 20px;}
+.qrcode-money .money span{font-size: 18px;}
+.qrcode-money .h{font-weight: bold;font-size: 14px;}
+.qrcode-money p{font-size: 14px;color: #0C0C0C;line-height: 32px;}
+</style>

+ 148 - 0
src/views/merchant/shop/user/components/form.vue

@@ -0,0 +1,148 @@
+<template>
+    <el-dialog :title="titleMap[mode]" v-model="visible" :width="600" 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="15">
+                    <el-col :span="24" v-if="type == 3">
+                    <el-form-item label="所属店铺" prop="store_id">
+                        <el-input v-model="formData.store_id" 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>
+                        </el-input>
+                    </el-form-item>
+                </el-col>
+                    <el-col :span="12">
+                        <el-form-item label="联系人" prop="contact_name">
+                            <el-input v-model="formData.contact_name" 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="contact_mobile">
+                            <el-input v-model="formData.contact_mobile" clearable placeholder="请输入联系电话"></el-input>
+                            <div class="el-form-item-msg"></div>
+                        </el-form-item>
+                    </el-col>
+                </el-row>
+            </fieldset>
+            <fieldset v-if="mode=='add'">
+                <legend><el-tag>账号信息</el-tag></legend>
+                <el-row :gutter="15">
+                    <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="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">
+                        <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 {
+    components: {
+        
+    },
+    data(){
+        return {
+            stepActive:1,
+            loading: false,
+            mode:"add",
+            titleMap:{
+                add:"新增员工账号",
+                edit:"编辑员工账号",
+            },
+            visible: false,
+            isSaveing: false,
+            formData:{},
+            type:2,
+            submitState:false,
+            disabled:false,
+            rules:{
+                username: [
+                    {required: true, message: '请输入登录账号'}
+                ],
+                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();
+                        }
+                    }}
+                ],
+            }
+        }
+    },
+    methods:{
+        open(mode = 'add'){
+            this.mode = mode;
+            this.visible = true;
+            return this
+        },
+        //表单注入数据
+        setData(data){
+            this.formData = data;
+        },
+        async submit(){
+            var validate = await this.$refs.dialogForm.validate().catch(()=>{});
+            if(!validate){ return false }
+            this.isSaveing = true;
+            let submitData = JSON.parse(JSON.stringify(this.formData));
+            submitData.password = this.$TOOL.crypto.MD5(submitData.password)
+            submitData.password2 = this.$TOOL.crypto.MD5(submitData.password2)
+            var resp = await this.$API.mStaff.save.post(submitData);
+            this.isSaveing = false;
+            if (resp.code !== 1) {
+                return this.$message.error(resp.msg);
+            }
+            this.$message.success(resp.msg);
+            this.visible = false;
+            this.formData = {};
+            this.submitState = 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;}
+</style>

+ 57 - 0
src/views/merchant/shop/user/components/option.vue

@@ -0,0 +1,57 @@
+<template>
+    <fieldset>
+        <legend>
+            <el-tag type="info">按需操作</el-tag>
+        </legend>
+        <div class="op-header">
+            <div class="left-panel">
+                <el-button type="primary" icon="el-icon-plus" @click="table_add(2)">新增员工账号</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(0)" :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: {
+        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.mStaff.batch.post(submitData);
+            if (resp.code == 0) {
+                return this.$message.error(resp.msg);
+            }
+            this.$message.success(resp.msg);
+            this.$emit("success");
+        },
+        handleSuccess(){
+            this.$emit("success");
+        },
+        table_add(type){
+            this.$nextTick(() => {
+                this.$refs.formMain.open("add")
+            })
+        },
+    }
+}
+</script>

+ 96 - 0
src/views/merchant/shop/user/components/password.vue

@@ -0,0 +1,96 @@
+<template>
+    <el-dialog :title="titleMap[mode]" v-model="visible" :width="500" destroy-on-close @closed="$emit('closed')">
+        <el-form :model="formData" :rules="rules" :disabled="mode=='show'" ref="dialogForm" label-position="top" label-width="120px">
+            <el-form-item label="登录账号">
+				<el-input v-model="formData.username" disabled></el-input>
+			</el-form-item>
+            <el-form-item label="账号昵称">
+				<el-input v-model="formData.truename" disabled></el-input>
+			</el-form-item>
+            <el-form-item label="新密码" prop="password">
+                <el-input type="password" v-model="formData.password" clearable show-password></el-input>
+            </el-form-item>
+            <el-form-item label="确认新密码" prop="password2">
+                <el-input type="password" v-model="formData.password2" clearable show-password></el-input>
+            </el-form-item>
+        </el-form>
+		<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>
+import scPasswordStrength from '@/components/scPasswordStrength'
+export default{
+    components: {
+        scPasswordStrength
+    },
+    data(){
+        return {
+            loading: false,
+            mode:"edit",
+            titleMap:{
+                edit:"修改密码"
+            },
+            visible: false,
+            isSaveing: false,
+            formData:{},
+            rules:{
+                password: [
+                    {required: true, message: '请输入登录密码'}
+                ],
+                password2: [
+                    {required: true, message: '请再次输入密码'},
+                    {validator: (rule, value, callback) => {
+                        if (value !== this.formData.password) {
+                            callback(new Error('两次输入密码不一致!'));
+                        }else{
+                            callback();
+                        }
+                    }}
+                ],
+            }
+        }
+    },
+    methods:{
+        open(mode = 'edit'){
+            this.mode = mode;
+            this.visible = true;
+            return this
+        },
+        //表单注入数据
+        setData(data){
+            data.password = "";
+            data.password2 = "";
+            this.formData = data;
+        },
+        submit(){
+            this.isSaveing = true;
+            this.$refs.dialogForm.validate(async (valid) => {
+                if (valid) {
+                    let password = this.$TOOL.crypto.MD5(this.formData.password);
+                    var result = await this.$API.mStaff.passwd.post({password:password,id:this.formData.id});
+                    if(result.code !== 1){
+                        this.$message.warning(result.msg)
+                        this.isSaveing = false;
+                        return false;
+                    }
+                    this.$message.success(result.msg)
+                    this.isSaveing = false;
+                    this.visible = false;
+                    this.formData = {};
+                }else{
+                    this.isSaveing = false;
+                    return false;
+                }
+            });
+        }
+    }
+}
+</script>
+
+<style lang="less" scoped>
+
+</style>

+ 46 - 0
src/views/merchant/shop/user/components/search.vue

@@ -0,0 +1,46 @@
+<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.name" 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>
+                                <template #prefix>状态</template>
+                            </el-select>
+                        </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>

+ 127 - 0
src/views/merchant/shop/user/components/table.vue

@@ -0,0 +1,127 @@
+<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="登录账号" 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="账号昵称" prop="truename" width="150">
+            <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="status" width="120">
+            <template #default="scope">
+                <div class="status-success" v-if="scope.row.type==2"><sc-status-indicator type="success"></sc-status-indicator> 员工账号</div>
+                <div class="status-danger" v-else><sc-status-indicator type="danger"></sc-status-indicator> 店铺账号</div>
+            </template>
+        </el-table-column>
+        <el-table-column label="登录时间" prop="login_at" width="180">
+            <template #default="scope">
+                {{scope.row.login_at?scope.row.login_at:'-'}}
+            </template>
+        </el-table-column>
+        <el-table-column label="登录IP" prop="login_ip" width="180">
+            <template #default="scope">
+                {{scope.row.login_ip?scope.row.login_ip:'-'}}
+            </template>
+        </el-table-column>
+        <el-table-column label="注册时间" prop="create_at" width="180"></el-table-column>
+        <el-table-column label="注册IP" prop="create_ip" 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-else><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 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>
+</template>
+
+<script>
+import passwd from "./password";
+export default {
+    components: {
+        passwd
+    },
+    data(){
+        return {
+            list: {
+                apiObj: this.$API.mStaff.list
+            },
+            dataSelect:[],
+            dataSelectFull:[],
+            searchKey:{}
+        }
+    },
+    methods: {
+        async table_del(data){
+            var resp = await this.$API.mStaff.del.post({"id":data.id});
+            if (resp.code == 0) {
+                return this.$message.error(resp.msg)
+            }
+            this.$message.success(resp.msg)
+            this.$refs.table.refresh()
+        },
+        table_view(data){
+            this.$nextTick(() => {
+                this.$refs.detailMain.open().setData(data)
+            })
+        },
+        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.userPasswd.open("edit").setData(row)
+            })
+        },
+    }
+}
+</script>

+ 45 - 1
src/views/merchant/shop/user/index.vue

@@ -1,3 +1,47 @@
 <template>
+    <el-container class="flex-column">
+        <div class="table-search">
+            <search @success="handleSuccess"></search>
+            <optionBtn @success="handleSuccess" :dataSelect="dataSelect" :dataSelectFull="dataSelectFull" type="3"></optionBtn>
+        </div>
+        <el-main class="nopadding">
+            <div class="table-container">
+                <tablePage ref="tablePage" @success="tableHandle" @successFull="tableHandleFull" type="3"></tablePage>
+            </div>
+        </el-main>
+    </el-container>  
+</template>
 
-</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 {
+            searchKey:{},
+            dataSelect:[],
+            dataSelectFull:[],
+        }
+    },
+    methods: {
+        tableHandle(data){
+            this.dataSelect = data;
+        },
+        tableHandleFull(data){
+            this.dataSelectFull = data;
+        },
+        handleSuccess(data){
+            this.$refs.tablePage.upData(data)
+        },
+        handleClick(name){
+            this.activeName = name;
+            this.searchKey.type = name;
+            this.$refs.tablePage.upData(this.searchKey)
+        }
+    }
+}
+</script>