diff --git a/db/schema_phase3.sql b/db/schema_phase3.sql
new file mode 100644
index 0000000..87733f8
--- /dev/null
+++ b/db/schema_phase3.sql
@@ -0,0 +1,70 @@
+-- ============================================================================
+-- 优匠优服 · Phase 3 商家(企业账号)
+-- 纯新增表,不改动既有表结构与数据
+-- ============================================================================
+SET NAMES utf8mb4;
+
+-- 商家入驻档案
+CREATE TABLE IF NOT EXISTS `fa_merchant` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `user_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '关联 fa_user.id',
+ `name` varchar(100) NOT NULL DEFAULT '' COMMENT '企业/商户名称',
+ `license_no` varchar(50) NOT NULL DEFAULT '' COMMENT '统一社会信用代码',
+ `license_image` varchar(255) NOT NULL DEFAULT '' COMMENT '营业执照图',
+ `legal_person` varchar(50) NOT NULL DEFAULT '' COMMENT '法人代表',
+ `contact` varchar(50) NOT NULL DEFAULT '' COMMENT '联系人',
+ `mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '联系电话',
+ `province` varchar(50) NOT NULL DEFAULT '',
+ `city` varchar(50) NOT NULL DEFAULT '',
+ `district` varchar(50) NOT NULL DEFAULT '',
+ `address` varchar(255) NOT NULL DEFAULT '' COMMENT '经营地址',
+ `invoice_title` varchar(100) NOT NULL DEFAULT '' COMMENT '发票抬头',
+ `invoice_tax_no` varchar(50) NOT NULL DEFAULT '' COMMENT '纳税人识别号',
+ `invoice_bank` varchar(100) NOT NULL DEFAULT '' COMMENT '开户行',
+ `invoice_account` varchar(50) NOT NULL DEFAULT '' COMMENT '银行账号',
+ `settle_type` enum('prepay','monthly') NOT NULL DEFAULT 'prepay' COMMENT '预付/月结',
+ `verify_status` enum('pending','pass','reject') NOT NULL DEFAULT 'pending',
+ `audit_msg` varchar(255) NOT NULL DEFAULT '',
+ `order_count` int(11) NOT NULL DEFAULT '0',
+ `total_amount` decimal(12,2) NOT NULL DEFAULT '0.00',
+ `createtime` bigint(16) DEFAULT NULL,
+ `updatetime` bigint(16) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `user_id` (`user_id`),
+ KEY `verify_status` (`verify_status`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商家档案';
+
+-- 商家订单归属(批次对账用,不侵入 fa_order)
+CREATE TABLE IF NOT EXISTS `fa_merchant_order` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `merchant_id` int(10) unsigned NOT NULL DEFAULT '0',
+ `order_id` int(10) unsigned NOT NULL DEFAULT '0',
+ `batch_no` varchar(32) NOT NULL DEFAULT '' COMMENT '批次号(批量下单)',
+ `createtime` bigint(16) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `order_id` (`order_id`),
+ KEY `merchant_id` (`merchant_id`),
+ KEY `batch_no` (`batch_no`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商家订单归属';
+
+-- 开票申请
+CREATE TABLE IF NOT EXISTS `fa_invoice` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `merchant_id` int(10) unsigned NOT NULL DEFAULT '0',
+ `user_id` int(10) unsigned NOT NULL DEFAULT '0',
+ `amount` decimal(10,2) NOT NULL DEFAULT '0.00',
+ `type` enum('normal','special') NOT NULL DEFAULT 'normal' COMMENT '普票/专票',
+ `title` varchar(100) NOT NULL DEFAULT '',
+ `tax_no` varchar(50) NOT NULL DEFAULT '',
+ `email` varchar(100) NOT NULL DEFAULT '',
+ `remark` varchar(255) NOT NULL DEFAULT '',
+ `status` enum('wait','issued','reject') NOT NULL DEFAULT 'wait',
+ `invoice_no` varchar(50) NOT NULL DEFAULT '',
+ `createtime` bigint(16) DEFAULT NULL,
+ `updatetime` bigint(16) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `merchant_id` (`merchant_id`),
+ KEY `status` (`status`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='开票申请';
+
+-- 回滚:DROP TABLE IF EXISTS `fa_invoice`,`fa_merchant_order`,`fa_merchant`;
diff --git a/manifest.json b/manifest.json
index 84c7fbc..fa99eb3 100644
--- a/manifest.json
+++ b/manifest.json
@@ -50,7 +50,7 @@
"quickapp" : {},
/* 小程序特有相关 */
"mp-weixin" : {
- "appid" : "",
+ "appid" : "wx40ca4b02d4d1cb58",
"setting" : {
"urlCheck" : false
},
diff --git a/pages.json b/pages.json
index e59a1be..ee7f627 100644
--- a/pages.json
+++ b/pages.json
@@ -66,6 +66,22 @@
"path": "pages/mine/mine",
"style": { "navigationStyle": "custom", "backgroundColor": "#F5F6F8" }
},
+ {
+ "path": "pages/merchant/apply",
+ "style": { "navigationBarTitleText": "商家入驻" }
+ },
+ {
+ "path": "pages/merchant/workbench",
+ "style": { "navigationBarTitleText": "商家工作台" }
+ },
+ {
+ "path": "pages/merchant/batch",
+ "style": { "navigationBarTitleText": "批量下单" }
+ },
+ {
+ "path": "pages/merchant/invoice",
+ "style": { "navigationBarTitleText": "开具发票" }
+ },
{
"path": "pages/master/orders",
"style": {
diff --git a/pages/login/login.vue b/pages/login/login.vue
index 6d29112..b5ce727 100644
--- a/pages/login/login.vue
+++ b/pages/login/login.vue
@@ -10,13 +10,9 @@
-
- 我是业主
- 下单找师傅
-
-
- 我是师傅
- 接单赚收入
+
+ {{ r.name }}
+ {{ r.desc }}
@@ -25,6 +21,17 @@
{{ loading ? '微信授权中...' : '微信一键登录' }}
+
+
+ {{ showPhone ? '收起手机号登录' : '微信授权失败?改用手机号登录' }}
+
+
+
+
+ 手机号登录 / 注册
+
+
+
授权仅用于账号识别,不会获取你的其他信息
登录即代表同意《用户服务协议》与《隐私政策》
@@ -41,6 +48,15 @@
const role = ref('user');
const loading = ref(false);
const showBack = ref(false);
+ const showPhone = ref(false);
+ const mobile = ref('');
+ const code = ref('');
+
+ const roles = [
+ { key: 'user', name: '我是业主', desc: '下单找师傅' },
+ { key: 'master', name: '我是师傅', desc: '接单赚收入' },
+ { key: 'merchant', name: '我是商家', desc: '企业批量下单' }
+ ];
function toast(t) { uni.showToast({ title: t, icon: 'none' }); }
@@ -83,11 +99,39 @@
});
}
+ function phoneLogin() {
+ if (loading.value) return;
+ if (!/^1\d{10}$/.test(mobile.value)) { toast('请输入正确的手机号'); return; }
+ if (!code.value) { toast('请输入验证码'); return; }
+ loading.value = true;
+ api.login({ mobile: mobile.value, code: code.value }).then((data) => {
+ loading.value = false;
+ setToken(data.token);
+ setUser(data.userinfo);
+ setRole(role.value);
+ toast('登录成功');
+ setTimeout(() => routeAfterLogin(), 500);
+ }).catch((e) => {
+ loading.value = false;
+ toast(e.message || '登录失败');
+ });
+ }
+
function routeAfterLogin() {
if (role.value === 'user') {
uni.reLaunch({ url: '/YJYF/YJYF' });
return;
}
+ if (role.value === 'merchant') {
+ api.merchantInfo().then((res) => {
+ if (!res.applied || res.merchant.verify_status !== 'pass') {
+ uni.redirectTo({ url: '/pages/merchant/apply' });
+ } else {
+ uni.redirectTo({ url: '/pages/merchant/workbench' });
+ }
+ }).catch(() => uni.redirectTo({ url: '/pages/merchant/apply' }));
+ return;
+ }
api.masterInfo().then((res) => {
if (!res.applied || res.master.verify_status !== 'pass') {
uni.redirectTo({ url: '/pages/master/apply' });
@@ -112,12 +156,19 @@
.brand { position: relative; display: block; font-size: 52rpx; font-weight: 700; color: #fff; letter-spacing: 6rpx; text-shadow: 0 3rpx 12rpx rgba(180,80,10,.3); }
.slogan { position: relative; display: block; margin-top: 14rpx; font-size: 26rpx; color: rgba(255,255,255,.88); letter-spacing: 2rpx; }
.card { position: relative; margin: -140rpx 40rpx 0; padding: 40rpx 34rpx 34rpx; background: #fff; border-radius: 24rpx; box-shadow: 0 16rpx 40rpx rgba(226,120,26,.16); }
- .role { display: flex; margin-bottom: 36rpx; }
- .role-item { flex: 1; padding: 22rpx 0; border-radius: 16rpx; background: #F7F7F7; display: flex; flex-direction: column; align-items: center; border: 2rpx solid transparent; }
+ .role { display: flex; margin-bottom: 34rpx; }
+ .role-item { flex: 1; margin-right: 12rpx; padding: 18rpx 0; border-radius: 16rpx; background: #F7F7F7; display: flex; flex-direction: column; align-items: center; border: 2rpx solid transparent; }
+ .role-item:last-child { margin-right: 0; }
.role-item.on { background: linear-gradient(135deg, #FFF8EE 0%, #FFE9D2 100%); border-color: #F9A65B; }
- .role-name { font-size: 30rpx; font-weight: 600; color: #333; }
+ .role-name { font-size: 26rpx; font-weight: 600; color: #333; }
.role-item.on .role-name { color: #C4580A; }
- .role-desc { margin-top: 6rpx; font-size: 22rpx; color: #9A9A9A; }
+ .role-desc { margin-top: 4rpx; font-size: 19rpx; color: #9A9A9A; }
+ .fallback { margin-top: 20rpx; }
+ .fb-toggle { text-align: center; padding: 12rpx 0; }
+ .fb-toggle-t { font-size: 22rpx; color: #9A9A9A; text-decoration: underline; }
+ .fb-body { margin-top: 10rpx; }
+ .fb-input { height: 88rpx; margin-bottom: 14rpx; padding: 0 24rpx; background: #F7F7F7; border-radius: 14rpx; font-size: 28rpx; color: #222; }
+ .fb-btn { height: 84rpx; display: flex; align-items: center; justify-content: center; border-radius: 42rpx; background: #FFF3E6; color: #E36B0C; font-size: 28rpx; font-weight: 600; }
.wx-btn { height: 96rpx; display: flex; align-items: center; justify-content: center; border-radius: 48rpx; background: linear-gradient(135deg, #4BC86A 0%, #2FA84F 100%); box-shadow: 0 10rpx 24rpx rgba(47,168,79,.28); }
.wx-btn.disabled { opacity: .7; }
.wx-icon { width: 44rpx; height: 44rpx; border-radius: 50%; background: #fff; display: flex; align-items: center; justify-content: center; margin-right: 14rpx; }
diff --git a/pages/merchant/apply.vue b/pages/merchant/apply.vue
new file mode 100644
index 0000000..8d4a5ec
--- /dev/null
+++ b/pages/merchant/apply.vue
@@ -0,0 +1,139 @@
+
+
+
+ 商家入驻
+ 企业账号可批量下单、按月对账、开具发票
+
+
+
+ 当前状态:{{ statusText }}
+ 审核意见:{{ info.merchant.audit_msg }}
+
+
+
+ 企业信息
+ 企业名称
+ 信用代码
+ 法人代表
+
+ 联系方式
+ 联系人
+ 联系电话
+ 经营地址
+
+ 开票与结算
+ 发票抬头
+ 税号
+ 结算方式
+
+ 预付
+ 月结
+
+
+
+ 营业执照照片上传将在正式版接入 chooseMedia(当前以文本占位)
+ {{ submitting ? '提交中...' : '提交审核' }}
+
+
+
+ 企业名称{{ info.merchant.name }}
+ 信用代码{{ info.merchant.license_no }}
+ 联系人{{ info.merchant.contact }} {{ info.merchant.mobile }}
+ 经营地址{{ info.merchant.address }}
+ 累计订单{{ info.merchant.order_count }} 单
+ 累计金额¥{{ info.merchant.total_amount }}
+ 进入商家工作台 ›
+
+
+
+
+
+
+
+
diff --git a/pages/merchant/batch.vue b/pages/merchant/batch.vue
new file mode 100644
index 0000000..ff28265
--- /dev/null
+++ b/pages/merchant/batch.vue
@@ -0,0 +1,189 @@
+
+
+
+ 选择服务
+
+ 服务类目
+
+ {{ catNames[catIdx] || '请选择' }} ›
+
+
+
+ 服务项目
+
+ {{ svcNames[svcIdx] || '请选择' }} ›
+
+
+ 单价 {{ svc.price_text }} · {{ svc.price_type_text }}
+
+
+
+
+ 服务地址({{ rows.length }} 个)
+ + 添加
+
+
+
+ #{{ i + 1 }}
+ 删除
+
+
+
+
+
+
+
+
+
+ 共 {{ rows.length }} 单¥{{ estimate }}
+ {{ submitting ? '提交中...' : '批量提交并支付' }}
+
+
+
+
+
+
+
+
diff --git a/pages/merchant/invoice.vue b/pages/merchant/invoice.vue
new file mode 100644
index 0000000..26198ec
--- /dev/null
+++ b/pages/merchant/invoice.vue
@@ -0,0 +1,117 @@
+
+
+
+ 开票信息修改 ›
+ 发票抬头{{ title || '未设置' }}
+ 税号{{ taxNo || '未设置' }}
+ 可开票金额¥{{ available }}
+
+
+
+ 申请开票
+ 开票金额
+ 发票类型
+
+ 普通发票
+ 专用发票
+
+
+ 接收邮箱
+ {{ submitting ? '提交中...' : '提交开票申请' }}
+
+
+
+ 开票记录{{ list.length }} 条
+
+
+ {{ i.type_text }}
+ ¥{{ i.amount }}
+
+ {{ i.title }} · {{ i.time_text }}
+ {{ i.status_text }}{{ i.invoice_no ? '(' + i.invoice_no + ')' : '' }}
+
+ 暂无开票记录
+
+
+
+
+
+
+
diff --git a/pages/merchant/workbench.vue b/pages/merchant/workbench.vue
new file mode 100644
index 0000000..d2ac3da
--- /dev/null
+++ b/pages/merchant/workbench.vue
@@ -0,0 +1,145 @@
+
+
+
+
+
+
+ {{ g.icon }}
+ {{ g.name }}
+
+
+
+
+ 按月账单刷新
+
+ {{ m.month }}
+ {{ m.cnt }} 单
+ ¥{{ m.amount }}
+
+ 暂无账单
+
+
+
+ 近期订单全部 ›
+
+
+ {{ o.service_name }}
+ {{ o.order_no }} · {{ o.time_text }}
+
+
+ ¥{{ o.pay_amount }}
+ {{ o.status_text }}
+
+
+ 暂无订单
+
+
+ 切换到业主身份
+
+
+
+
+
+
+
diff --git a/pages/mine/mine.vue b/pages/mine/mine.vue
index fa1d21d..73eeeeb 100644
--- a/pages/mine/mine.vue
+++ b/pages/mine/mine.vue
@@ -39,6 +39,14 @@
{{ masterCard.btn }}
+
+
+ {{ merchantCard.title }}
+ {{ merchantCard.desc }}
+
+ {{ merchantCard.btn }}
+
+