小程序提交
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
.cursorindexingignore
|
||||
.specstory/
|
||||
node_modules/
|
||||
uni_modules/
|
||||
unpackage/
|
||||
16
.hbuilderx/launch.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
|
||||
// launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
|
||||
"version": "0.0",
|
||||
"configurations": [{
|
||||
"default" :
|
||||
{
|
||||
"launchtype" : "local"
|
||||
},
|
||||
"mp-weixin" :
|
||||
{
|
||||
"launchtype" : "local"
|
||||
},
|
||||
"type" : "uniCloud"
|
||||
}
|
||||
]
|
||||
}
|
||||
34
App.vue
Normal file
@@ -0,0 +1,34 @@
|
||||
<script>
|
||||
export default {
|
||||
onLaunch: function() {
|
||||
console.warn('当前组件仅支持 uni_modules 目录结构 ,请升级 HBuilderX 到 3.1.0 版本以上!')
|
||||
console.log('App Launch')
|
||||
},
|
||||
onShow: function() {
|
||||
console.log('App Show')
|
||||
},
|
||||
onHide: function() {
|
||||
console.log('App Hide')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "uview-ui/index.scss";
|
||||
/*每个页面公共css */
|
||||
@import '@/uni_modules/uni-scss/index.scss';
|
||||
/* #ifndef APP-NVUE */
|
||||
@import '@/static/customicons.css';
|
||||
|
||||
// 设置整个项目的背景色
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
.example-info {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
36
README.en.md
@@ -1,36 +0,0 @@
|
||||
# 存客宝小程序
|
||||
|
||||
#### Description
|
||||
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
|
||||
|
||||
#### Software Architecture
|
||||
Software architecture description
|
||||
|
||||
#### Installation
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Instructions
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Contribution
|
||||
|
||||
1. Fork the repository
|
||||
2. Create Feat_xxx branch
|
||||
3. Commit your code
|
||||
4. Create Pull Request
|
||||
|
||||
|
||||
#### Gitee Feature
|
||||
|
||||
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
|
||||
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
|
||||
4. The most valuable open source project [GVP](https://gitee.com/gvp)
|
||||
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
|
||||
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
39
README.md
@@ -1,39 +0,0 @@
|
||||
# 存客宝小程序
|
||||
|
||||
#### 介绍
|
||||
{**以下是 Gitee 平台说明,您可以替换此简介**
|
||||
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
|
||||
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
|
||||
|
||||
#### 软件架构
|
||||
软件架构说明
|
||||
|
||||
|
||||
#### 安装教程
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### 使用说明
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### 参与贡献
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
||||
|
||||
|
||||
#### 特技
|
||||
|
||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
|
||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
|
||||
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
|
||||
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
||||
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
7
config.js
Normal file
@@ -0,0 +1,7 @@
|
||||
// config.js
|
||||
export default {
|
||||
apiUrl: 'https://api.ckb.quwanzhi.com',
|
||||
apiUrl2: 'https://ckbapi.quwanzhi.com',
|
||||
//apiUrl2: 'http://www.yishi.com',
|
||||
// 其他全局配置项
|
||||
}
|
||||
20
index.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
<title></title>
|
||||
<!--preload-links-->
|
||||
<!--app-context-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
<script type="module" src="/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
42
main.js
Normal file
@@ -0,0 +1,42 @@
|
||||
// #ifndef VUE3
|
||||
import Vue from 'vue'
|
||||
import App from './App'
|
||||
import config from './config.js'
|
||||
|
||||
|
||||
import authMixin from './mixins/auth-mixin';
|
||||
Vue.mixin(authMixin);
|
||||
|
||||
Vue.config.productionTip = false
|
||||
Vue.prototype.$config = config
|
||||
|
||||
//兼容旧版
|
||||
Vue.prototype.$wxAppId = 'wx789850448e26c91d';
|
||||
Vue.prototype.$wxApi = 'https://api.quwanzhi.com';
|
||||
Vue.prototype.$settingData = [];
|
||||
Vue.prototype.$userInfo = {};
|
||||
|
||||
|
||||
import uView from "uview-ui";
|
||||
Vue.use(uView);
|
||||
|
||||
App.mpType = 'app'
|
||||
|
||||
const app = new Vue({
|
||||
...App
|
||||
})
|
||||
app.$mount()
|
||||
// #endif
|
||||
|
||||
// #ifdef VUE3
|
||||
import {
|
||||
createSSRApp
|
||||
} from 'vue'
|
||||
import App from './App.vue'
|
||||
export function createApp() {
|
||||
const app = createSSRApp(App)
|
||||
return {
|
||||
app
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
63
manifest.json
Normal file
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"name" : "存客宝",
|
||||
"appid" : "__UNI__505D381",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
"transformPx" : false,
|
||||
"app-plus" : {
|
||||
/* 5+App特有相关 */
|
||||
"usingComponents" : true,
|
||||
"nvueCompiler" : "uni-app",
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : true,
|
||||
"waiting" : true,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
"modules" : {},
|
||||
/* 模块配置 */
|
||||
"distribute" : {
|
||||
/* 应用发布信息 */
|
||||
"android" : {
|
||||
/* android打包配置 */
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
]
|
||||
},
|
||||
"ios" : {},
|
||||
/* ios打包配置 */
|
||||
"sdkConfigs" : {}
|
||||
}
|
||||
},
|
||||
/* SDK配置 */
|
||||
"quickapp" : {},
|
||||
/* 快应用特有相关 */
|
||||
"mp-weixin" : {
|
||||
/* 小程序特有相关 */
|
||||
"appid" : "wx789850448e26c91d",
|
||||
"setting" : {
|
||||
"urlCheck" : false,
|
||||
"minified" : true,
|
||||
"postcss" : true,
|
||||
"es6" : true
|
||||
},
|
||||
"usingComponents" : true
|
||||
},
|
||||
"vueVersion" : "2"
|
||||
}
|
||||
69
mixins/auth-mixin.js
Normal file
@@ -0,0 +1,69 @@
|
||||
export default {
|
||||
methods: {
|
||||
checkLogin() {
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1];
|
||||
let fullPath = '';
|
||||
let queryString = '';
|
||||
|
||||
// #ifdef H5
|
||||
fullPath = window.location.hash ? window.location.hash.substring(1) : window.location.pathname;
|
||||
queryString = window.location.search;
|
||||
// #endif
|
||||
|
||||
// #ifdef MP
|
||||
fullPath = `/${currentPage.route}`; // 在小程序中使用route
|
||||
// Combine existing options with the scene parameter if it exists
|
||||
const options = {
|
||||
...currentPage.options
|
||||
};
|
||||
|
||||
queryString = this.objectToQueryString(options);
|
||||
|
||||
if (this.$root.$mp.query.scene) {
|
||||
queryString += "&" + decodeURIComponent(this.$root.$mp.query.scene)
|
||||
}
|
||||
|
||||
// #endif
|
||||
|
||||
const redirectUrl = fullPath + "?" + queryString;
|
||||
|
||||
|
||||
// 如果当前已经在登录页,则不进行跳转
|
||||
if (
|
||||
fullPath.includes('pages/login/login') ||
|
||||
fullPath.includes('pages/index/index') ||
|
||||
fullPath.includes('pages/index/site') ||
|
||||
fullPath.includes('pages/poster/index') ||
|
||||
fullPath.includes('pages/form/input')||
|
||||
fullPath.includes('pages/login/privatememo')||
|
||||
fullPath.includes('pages/login/usermemo') ||
|
||||
fullPath.includes('pages/channel/add')||
|
||||
fullPath.includes('pages/channel/login')||
|
||||
fullPath.includes('pages/channel/statistics')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
// 未登录则跳转到登录页
|
||||
else if (!this.isLoggedIn()) {
|
||||
uni.redirectTo({
|
||||
url: '/pages/login/login?redirect=' + encodeURIComponent(redirectUrl),
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
isLoggedIn() {
|
||||
const token = uni.getStorageSync('token');
|
||||
return !!token;
|
||||
},
|
||||
|
||||
// 将对象转换为查询字符串
|
||||
objectToQueryString(obj) {
|
||||
return Object.keys(obj).map(key => `${key}=${encodeURIComponent(obj[key])}`).join('&');
|
||||
},
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.checkLogin();
|
||||
},
|
||||
};
|
||||
27
package-lock.json
generated
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "ckb_mini",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"uview-ui": "^2.0.36"
|
||||
}
|
||||
},
|
||||
"node_modules/uview-ui": {
|
||||
"version": "2.0.36",
|
||||
"resolved": "https://registry.npmjs.org/uview-ui/-/uview-ui-2.0.36.tgz",
|
||||
"integrity": "sha512-ASSZT6M8w3GTO1eFPbsgEFV0U5UujK+8pTNr+MSUbRNcRMC1u63DDTLJVeArV91kWM0bfAexK3SK9pnTqF9TtA==",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"uview-ui": {
|
||||
"version": "2.0.36",
|
||||
"resolved": "https://registry.npmjs.org/uview-ui/-/uview-ui-2.0.36.tgz",
|
||||
"integrity": "sha512-ASSZT6M8w3GTO1eFPbsgEFV0U5UujK+8pTNr+MSUbRNcRMC1u63DDTLJVeArV91kWM0bfAexK3SK9pnTqF9TtA=="
|
||||
}
|
||||
}
|
||||
}
|
||||
5
package.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"uview-ui": "^2.0.36"
|
||||
}
|
||||
}
|
||||
181
pages.json
Normal file
@@ -0,0 +1,181 @@
|
||||
{
|
||||
"pages": [
|
||||
{
|
||||
"path": "pages/index/site",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enableShareAppMessage": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/poster/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enableShareAppMessage": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/poster/index2",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enableShareAppMessage": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/about/about",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enableShareAppMessage": true
|
||||
}
|
||||
}, {
|
||||
"path": "pages/login/login",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
}, {
|
||||
"path": "pages/home/home",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
}, {
|
||||
"path": "pages/ucenter/ucenter",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
}, {
|
||||
"path": "pages/form/input",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/form/input2",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/form/list",
|
||||
"style": {
|
||||
"navigationBarTitleText": "",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/channel/list",
|
||||
"style": {
|
||||
"navigationBarTitleText": "渠道管理",
|
||||
"enablePullDownRefresh": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/channel/add",
|
||||
"style": {
|
||||
"navigationBarTitleText": "新增渠道",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/channel/login",
|
||||
"style": {
|
||||
"navigationBarTitleText": "渠道登录",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/channel/project-select",
|
||||
"style": {
|
||||
"navigationBarTitleText": "选择项目",
|
||||
"enablePullDownRefresh": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/channel/statistics",
|
||||
"style": {
|
||||
"navigationBarTitleText": "分销获客统计",
|
||||
"enablePullDownRefresh": true
|
||||
}
|
||||
}
|
||||
],
|
||||
// "tabBar": {
|
||||
// "color": "#7A7E83",
|
||||
// "selectedColor": "#007AFF",
|
||||
// "borderStyle": "black",
|
||||
// "backgroundColor": "#FFFFFF",
|
||||
// "list": [{
|
||||
// "pagePath": "pages/home/home",
|
||||
// "iconPath": "static/tabbar/list.png",
|
||||
// "selectedIconPath": "static/tabbar/list_active.png",
|
||||
// "text": "主页"
|
||||
// }, {
|
||||
// "pagePath": "pages/ucenter/ucenter",
|
||||
// "iconPath": "static/tabbar/me.png",
|
||||
// "selectedIconPath": "static/tabbar/me_active.png",
|
||||
// "text": "我的"
|
||||
// }]
|
||||
// },
|
||||
"globalStyle": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "uni-app",
|
||||
"navigationBarBackgroundColor": "#F8F8F8",
|
||||
"backgroundColor": "#F8F8F8",
|
||||
"app-plus": {
|
||||
"background": "#efeff4"
|
||||
}
|
||||
},
|
||||
"easycom": {
|
||||
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
|
||||
},
|
||||
"condition": { //模式配置,仅开发期间生效
|
||||
"current": 1, //当前激活的模式(list 的索引项)
|
||||
"list": [{
|
||||
"name": "首页", //模式名称
|
||||
"path": "pages/index/index", //启动页面,必选
|
||||
"query": "" //启动参数,在页面的onLoad函数里面得到
|
||||
},
|
||||
{
|
||||
"name": "webview", //模式名称
|
||||
"path": "pages/index/site", //启动页面,必选
|
||||
"query": "" //启动参数,在页面的onLoad函数里面得到
|
||||
},
|
||||
{
|
||||
"name": "旧版海报页", //模式名称
|
||||
"path": "pages/about/about", //启动页面,必选
|
||||
"query": "taskId=491" //启动参数,在页面的onLoad函数里面得到
|
||||
},
|
||||
{
|
||||
"name": "新版海报页", //模式名称
|
||||
"path": "pages/poster/index", //启动页面,必选
|
||||
"query": "" //启动参数,在页面的onLoad函数里面得到
|
||||
},
|
||||
{
|
||||
"name": "登录页", //模式名称
|
||||
"path": "pages/login/login", //启动页面,必选
|
||||
"query": "" //启动参数,在页面的onLoad函数里面得到
|
||||
},
|
||||
{
|
||||
"name": "我的", //模式名称
|
||||
"path": "pages/ucenter/ucenter", //启动页面,必选
|
||||
"query": "" //启动参数,在页面的onLoad函数里面得到
|
||||
},
|
||||
{
|
||||
"name": "表单", //模式名称
|
||||
"path": "pages/form/input", //启动页面,必选
|
||||
"query": "id=505" //启动参数,在页面的onLoad函数里面得到
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
119
pages/about/about.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<button style="padding: 0;margin-left: 0; text-align: left;" class="nullBtn" open-type="getPhoneNumber"
|
||||
@getphonenumber="getPhoneNumber">
|
||||
<image class="posterImg" :src="poster.sUrl" mode="widthFix"></image>
|
||||
</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
taskid: '',
|
||||
token: "test",
|
||||
task: null,
|
||||
poster: null
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
let scene = options.scene;
|
||||
let taskId = options.taskId;
|
||||
|
||||
if (scene != undefined) {
|
||||
this.taskid = scene;
|
||||
} else if (taskId != undefined) {
|
||||
this.taskid = taskId;
|
||||
}
|
||||
|
||||
this.getPosterData()
|
||||
},
|
||||
methods: {
|
||||
getPosterData() {
|
||||
let that = this;
|
||||
uni.request({
|
||||
method: 'POST',
|
||||
header: {
|
||||
'content-type': 'application/x-www-form-urlencoded', //自定义请求头信息
|
||||
'token': that.token
|
||||
},
|
||||
url: that.$config.apiUrl + '/v1/frontend/business/poster/getone',
|
||||
data: {
|
||||
id: that.taskid,
|
||||
},
|
||||
success: (res) => {
|
||||
if (res.data.code == 10000) {
|
||||
that.poster = res.data.data.poster
|
||||
that.task = res.data.data.task
|
||||
|
||||
//修改标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: that.task.sName
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// 获取用户手机号
|
||||
getPhoneNumber(res) {
|
||||
let that = this;
|
||||
if (res.detail.errMsg == "getPhoneNumber:ok") {
|
||||
uni.showLoading({
|
||||
title: '请求中...',
|
||||
mask: true
|
||||
})
|
||||
uni.request({
|
||||
method: 'POST',
|
||||
header: {
|
||||
'content-type': 'application/x-www-form-urlencoded', //自定义请求头信息
|
||||
'token': that.token
|
||||
},
|
||||
url: that.$config.apiUrl + '/v1/frontend/business/poster/decryptphone',
|
||||
data: {
|
||||
id: that.taskid,
|
||||
code: res.detail.code
|
||||
},
|
||||
success: (res) => {
|
||||
uni.hideLoading();
|
||||
if (res.data.code == 10000) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: that.task.sTip,
|
||||
success: function(res) {
|
||||
console.log(res)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.page {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.posterImg {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
801
pages/channel/add.vue
Normal file
@@ -0,0 +1,801 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<!-- 验证中提示 -->
|
||||
<view v-if="validating" class="validating-container">
|
||||
<view class="validating-content">
|
||||
<uni-icons type="spinner-cycle" size="40" color="#6366f1"></uni-icons>
|
||||
<text class="validating-text">正在验证...</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 错误提示页面 -->
|
||||
<view v-if="!validating && !tokenValid && errorMessage" class="error-container">
|
||||
<view class="error-content">
|
||||
<view class="error-icon-wrapper">
|
||||
<uni-icons type="closeempty" size="80" color="#ef4444"></uni-icons>
|
||||
</view>
|
||||
<text class="error-title">验证失败</text>
|
||||
<text class="error-message">{{ errorMessage }}</text>
|
||||
<button class="error-button" @click="goBack">返回</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 创建方式选择 -->
|
||||
<view class="method-selector" v-if="tokenValid && !validating && !errorMessage">
|
||||
<view class="selector-item" :class="{'active': createMethod === 'manual'}" @click="createMethod = 'manual'">
|
||||
<view class="selector-dot" v-if="createMethod === 'manual'"></view>
|
||||
<text class="selector-text">手动创建</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 表单内容 -->
|
||||
<view class="form-container" v-if="tokenValid && !validating && !errorMessage">
|
||||
<view class="form-header">
|
||||
<text class="form-title">填写渠道信息</text>
|
||||
<text class="form-subtitle">请完善下方信息以手动添加新的分销渠道。</text>
|
||||
</view>
|
||||
|
||||
<view class="form-body">
|
||||
<!-- 渠道名称 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<uni-icons type="shop" size="18" color="#6366f1"></uni-icons>
|
||||
<text class="label-text">渠道名称</text>
|
||||
<text class="required-mark">必填</text>
|
||||
</view>
|
||||
<view class="input-wrapper">
|
||||
<input
|
||||
class="form-input"
|
||||
v-model="form.channelName"
|
||||
placeholder="请输入渠道名称"
|
||||
maxlength="50"
|
||||
:focus="focusChannelName"
|
||||
@blur="focusChannelName = false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 联系电话 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<uni-icons type="phone" size="18" color="#6366f1"></uni-icons>
|
||||
<text class="label-text">手机号</text>
|
||||
<text class="required-mark">必填</text>
|
||||
</view>
|
||||
<view class="input-wrapper">
|
||||
<input
|
||||
class="form-input"
|
||||
v-model="form.contactPhone"
|
||||
placeholder="请输入手机号"
|
||||
type="number"
|
||||
maxlength="11"
|
||||
:focus="focusContactPhone"
|
||||
@blur="focusContactPhone = false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 微信号 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<uni-icons type="chat" size="18" color="#6366f1"></uni-icons>
|
||||
<text class="label-text">微信号</text>
|
||||
</view>
|
||||
<view class="input-wrapper">
|
||||
<input
|
||||
class="form-input"
|
||||
v-model="form.wechatId"
|
||||
placeholder="请输入微信号"
|
||||
maxlength="50"
|
||||
:focus="focusWechatId"
|
||||
@blur="focusWechatId = false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 备注 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<uni-icons type="info" size="18" color="#6366f1"></uni-icons>
|
||||
<text class="label-text">备注</text>
|
||||
</view>
|
||||
<view class="input-wrapper">
|
||||
<textarea
|
||||
class="form-textarea"
|
||||
v-model="form.remark"
|
||||
placeholder="请输入备注信息 (选填)"
|
||||
maxlength="200"
|
||||
:auto-height="true"
|
||||
:focus="focusRemark"
|
||||
@blur="focusRemark = false"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<view class="button-container" v-if="tokenValid && !validating && !errorMessage">
|
||||
<button class="cancel-button" @click="cancel">取消</button>
|
||||
<button class="submit-button" :class="{'loading': isSubmitting}" @click="submit" :disabled="isSubmitting || !tokenValid">
|
||||
<uni-icons v-if="!isSubmitting" type="checkmarkempty" size="20" color="#fff"></uni-icons>
|
||||
<text class="button-text">{{ isSubmitting ? '提交中...' : '创建' }}</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from '@/config';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
token: '',
|
||||
createMethod: 'manual',
|
||||
form: {
|
||||
channelName: '',
|
||||
contactPhone: '',
|
||||
wechatId: '',
|
||||
remark: ''
|
||||
},
|
||||
focusChannelName: false,
|
||||
focusContactPhone: false,
|
||||
focusWechatId: false,
|
||||
focusRemark: false,
|
||||
isSubmitting: false,
|
||||
tokenValid: false,
|
||||
validating: true,
|
||||
errorMessage: ''
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
// 获取参数
|
||||
let scene = options.scene;
|
||||
let token = options.token;
|
||||
|
||||
console.log('页面参数:', { scene, token });
|
||||
|
||||
// 小程序端解析 scene 参数
|
||||
// #ifdef MP-WEIXIN
|
||||
if (scene != undefined) {
|
||||
// 先对 scene 进行 URL 解码(处理 %2C 等编码字符)
|
||||
try {
|
||||
scene = decodeURIComponent(scene);
|
||||
} catch (e) {
|
||||
console.warn('scene 解码失败,使用原始值:', e);
|
||||
}
|
||||
|
||||
// scene 中可能包含 token,或者直接就是 token
|
||||
// 如果 scene 包含逗号,可能需要分割(根据实际业务需求调整)
|
||||
if (scene.includes(',')) {
|
||||
// 如果 scene 包含逗号,取第一部分作为 token
|
||||
const parts = scene.split(',');
|
||||
this.token = parts[0] || '';
|
||||
} else {
|
||||
// 如果不包含逗号,scene 本身就是 token
|
||||
this.token = scene;
|
||||
}
|
||||
} else if (token != undefined) {
|
||||
// 兼容直接传 token 参数
|
||||
this.token = token;
|
||||
} else {
|
||||
// 没有参数,显示错误
|
||||
this.token = '';
|
||||
}
|
||||
// #endif
|
||||
|
||||
// H5 端兼容处理
|
||||
// #ifdef H5
|
||||
if (token != undefined) {
|
||||
// H5 端优先使用 token 参数
|
||||
this.token = token;
|
||||
} else if (scene != undefined) {
|
||||
// H5 也可能有 scene 参数(从分享链接等)
|
||||
// 先对 scene 进行 URL 解码
|
||||
try {
|
||||
scene = decodeURIComponent(scene);
|
||||
} catch (e) {
|
||||
console.warn('scene 解码失败,使用原始值:', e);
|
||||
}
|
||||
|
||||
if (scene.includes(',')) {
|
||||
const parts = scene.split(',');
|
||||
this.token = parts[0] || '';
|
||||
} else {
|
||||
this.token = scene;
|
||||
}
|
||||
} else {
|
||||
// 没有参数,显示错误
|
||||
this.token = '';
|
||||
}
|
||||
// #endif
|
||||
|
||||
console.log('解析结果:', { token: this.token });
|
||||
|
||||
if (!this.token) {
|
||||
this.validating = false;
|
||||
this.tokenValid = false;
|
||||
this.errorMessage = '缺少token参数,请重新扫码';
|
||||
return;
|
||||
}
|
||||
|
||||
uni.setNavigationBarTitle({
|
||||
title: '新增渠道'
|
||||
});
|
||||
|
||||
// 验证token有效性
|
||||
this.validateToken();
|
||||
|
||||
// H5和小程序兼容处理
|
||||
// #ifdef H5
|
||||
// H5端回车键提交
|
||||
document.onkeydown = (event) => {
|
||||
const e = event || window.event;
|
||||
if (e && e.keyCode === 13) {
|
||||
this.submit();
|
||||
}
|
||||
};
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
// 验证token有效性
|
||||
validateToken() {
|
||||
this.validating = true;
|
||||
uni.showLoading({
|
||||
title: '验证中...',
|
||||
mask: true
|
||||
});
|
||||
|
||||
uni.request({
|
||||
method: 'GET',
|
||||
url: config.apiUrl2 + '/v1/frontend/distribution/channel/register',
|
||||
data: {
|
||||
token: this.token
|
||||
},
|
||||
header: {
|
||||
'content-type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
success: (response) => {
|
||||
uni.hideLoading();
|
||||
this.validating = false;
|
||||
|
||||
if (response.data.code === 10000 || response.data.code === 200) {
|
||||
this.tokenValid = true;
|
||||
this.errorMessage = '';
|
||||
// token验证成功,可以填写表单
|
||||
} else {
|
||||
this.tokenValid = false;
|
||||
this.errorMessage = response.data.message || 'token无效或已过期,请重新扫码';
|
||||
}
|
||||
},
|
||||
fail: (error) => {
|
||||
uni.hideLoading();
|
||||
this.validating = false;
|
||||
this.tokenValid = false;
|
||||
console.error('验证token失败:', error);
|
||||
this.errorMessage = '网络错误,请检查网络连接后重试';
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 表单验证
|
||||
validateForm() {
|
||||
if (!this.form.channelName || !this.form.channelName.trim()) {
|
||||
this.focusChannelName = true;
|
||||
uni.showToast({
|
||||
title: '请输入渠道名称',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// 手机号必填验证
|
||||
if (!this.form.contactPhone || !this.form.contactPhone.trim()) {
|
||||
this.focusContactPhone = true;
|
||||
uni.showToast({
|
||||
title: '请输入手机号',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// 验证手机号格式
|
||||
const phoneReg = /^1[3-9]\d{9}$/;
|
||||
if (!phoneReg.test(this.form.contactPhone.trim())) {
|
||||
this.focusContactPhone = true;
|
||||
uni.showToast({
|
||||
title: '请输入正确的手机号',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
// 提交表单
|
||||
submit() {
|
||||
if (this.isSubmitting) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.validateForm()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.tokenValid) {
|
||||
uni.showToast({
|
||||
title: 'token无效,请重新扫码',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.isSubmitting = true;
|
||||
|
||||
const data = {
|
||||
token: this.token,
|
||||
name: this.form.channelName.trim(),
|
||||
phone: this.form.contactPhone.trim(),
|
||||
wechatId: this.form.wechatId ? this.form.wechatId.trim() : '',
|
||||
remarks: this.form.remark ? this.form.remark.trim() : ''
|
||||
};
|
||||
|
||||
uni.request({
|
||||
method: 'POST',
|
||||
url: config.apiUrl2 + '/v1/frontend/distribution/channel/register',
|
||||
data: data,
|
||||
header: {
|
||||
'content-type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
success: (response) => {
|
||||
this.isSubmitting = false;
|
||||
|
||||
if (response.data.code === 10000 || response.data.code === 200) {
|
||||
// 获取返回的companyId
|
||||
const responseData = response.data.data || {};
|
||||
const companyId = responseData.companyId || '';
|
||||
|
||||
console.log('渠道创建成功,返回数据:', responseData);
|
||||
console.log('获取到的companyId:', companyId);
|
||||
|
||||
uni.showToast({
|
||||
title: '提交成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
// 如果有companyId,跳转到渠道登录页
|
||||
if (companyId) {
|
||||
uni.redirectTo({
|
||||
url: `/pages/channel/login?companyId=${companyId}`
|
||||
});
|
||||
} else {
|
||||
// 如果没有companyId,返回上一页
|
||||
uni.navigateBack();
|
||||
}
|
||||
}, 1500);
|
||||
} else {
|
||||
// 显示后端返回的错误信息
|
||||
const errorMsg = response.data.message || response.data.msg || response.data.error || '提交失败,请重试';
|
||||
uni.showToast({
|
||||
title: errorMsg,
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (error) => {
|
||||
this.isSubmitting = false;
|
||||
console.error('提交失败:', error);
|
||||
uni.showToast({
|
||||
title: '网络错误,请重试',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 取消
|
||||
cancel() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
||||
// 返回
|
||||
goBack() {
|
||||
uni.navigateBack();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
padding-bottom: 160rpx;
|
||||
}
|
||||
|
||||
/* 创建方式选择器 */
|
||||
.method-selector {
|
||||
padding: 30rpx;
|
||||
background-color: #fff;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.selector-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx;
|
||||
background-color: #f9fafb;
|
||||
border-radius: 12rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.selector-item.active {
|
||||
background-color: #f0f4ff;
|
||||
}
|
||||
|
||||
.selector-dot {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
background-color: #6366f1;
|
||||
border-radius: 50%;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.selector-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 表单容器 */
|
||||
.form-container {
|
||||
background-color: #fff;
|
||||
margin: 20rpx;
|
||||
border-radius: 16rpx;
|
||||
padding: 40rpx 30rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.form-header {
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.form-title {
|
||||
display: block;
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.form-subtitle {
|
||||
display: block;
|
||||
font-size: 26rpx;
|
||||
color: #999;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.label-text {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.required-mark {
|
||||
font-size: 24rpx;
|
||||
color: #ef4444;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
padding: 0 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
background-color: #f9fafb;
|
||||
border: 2rpx solid #e5e7eb;
|
||||
border-radius: 12rpx;
|
||||
box-sizing: border-box;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
/* #ifdef H5 */
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: #6366f1;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0 0 4rpx rgba(99, 102, 241, 0.1);
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
/* #ifdef MP-WEIXIN */
|
||||
&:focus {
|
||||
border-color: #6366f1;
|
||||
background-color: #fff;
|
||||
}
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.form-input::placeholder {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
width: 100%;
|
||||
min-height: 160rpx;
|
||||
padding: 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
background-color: #f9fafb;
|
||||
border: 2rpx solid #e5e7eb;
|
||||
border-radius: 12rpx;
|
||||
box-sizing: border-box;
|
||||
line-height: 1.6;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
/* #ifdef H5 */
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: #6366f1;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0 0 4rpx rgba(99, 102, 241, 0.1);
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
/* #ifdef MP-WEIXIN */
|
||||
&:focus {
|
||||
border-color: #6366f1;
|
||||
background-color: #fff;
|
||||
}
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.form-textarea::placeholder {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 底部按钮容器 */
|
||||
.button-container {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
/* #ifdef H5 */
|
||||
box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
/* #endif */
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.cancel-button {
|
||||
flex: 1;
|
||||
height: 88rpx;
|
||||
background-color: #f5f5f5;
|
||||
border: none;
|
||||
border-radius: 12rpx;
|
||||
color: #666;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
|
||||
/* #ifdef H5 */
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: #e5e5e5;
|
||||
}
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
flex: 2;
|
||||
height: 88rpx;
|
||||
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
|
||||
border: none;
|
||||
border-radius: 12rpx;
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 8rpx 24rpx rgba(99, 102, 241, 0.3);
|
||||
|
||||
/* #ifdef H5 */
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
transform: translateY(-2rpx);
|
||||
box-shadow: 0 12rpx 32rpx rgba(99, 102, 241, 0.4);
|
||||
}
|
||||
|
||||
&:active:not(:disabled) {
|
||||
transform: translateY(0);
|
||||
}
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.submit-button.loading {
|
||||
opacity: 0.7;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.submit-button:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.button-text {
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
/* H5适配 */
|
||||
/* #ifdef H5 */
|
||||
.page-container {
|
||||
padding-bottom: 180rpx;
|
||||
}
|
||||
|
||||
.button-container {
|
||||
padding: 30rpx 40rpx;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
/* 小程序适配 */
|
||||
/* #ifdef MP-WEIXIN */
|
||||
.button-container {
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
/* 验证中容器 */
|
||||
.validating-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.validating-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.validating-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 错误容器 */
|
||||
.error-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
padding: 40rpx;
|
||||
}
|
||||
|
||||
.error-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
max-width: 600rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.error-icon-wrapper {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #fef2f2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 40rpx;
|
||||
border: 4rpx solid #fee2e2;
|
||||
}
|
||||
|
||||
.error-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
font-size: 28rpx;
|
||||
color: #6b7280;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 60rpx;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.error-button {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
|
||||
border: none;
|
||||
border-radius: 12rpx;
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 8rpx 24rpx rgba(99, 102, 241, 0.3);
|
||||
|
||||
/* #ifdef H5 */
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2rpx);
|
||||
box-shadow: 0 12rpx 32rpx rgba(99, 102, 241, 0.4);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
/* 响应式适配 */
|
||||
@media (max-width: 375px) {
|
||||
.form-container {
|
||||
padding: 30rpx 20rpx;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
319
pages/channel/list.vue
Normal file
@@ -0,0 +1,319 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<!-- 列表内容 -->
|
||||
<view class="list-container">
|
||||
<u-list @scrolltolower="scrolltolower">
|
||||
<u-list-item v-for="(item, index) in channelList" :key="index" class="list-item">
|
||||
<view class="item-content" @click="editChannel(item)">
|
||||
<view class="item-header">
|
||||
<view class="item-title">{{ item.channelName || '未命名渠道' }}</view>
|
||||
<view class="item-status" :class="{'status-active': item.status === 1}">
|
||||
{{ item.status === 1 ? '启用' : '禁用' }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="item-info">
|
||||
<view class="info-row" v-if="item.contactPhone">
|
||||
<uni-icons type="phone" size="16" color="#999"></uni-icons>
|
||||
<text class="info-text">{{ item.contactPhone }}</text>
|
||||
</view>
|
||||
<view class="info-row" v-if="item.wechatId">
|
||||
<uni-icons type="chat" size="16" color="#999"></uni-icons>
|
||||
<text class="info-text">{{ item.wechatId }}</text>
|
||||
</view>
|
||||
<view class="info-row" v-if="item.remark">
|
||||
<uni-icons type="info" size="16" color="#999"></uni-icons>
|
||||
<text class="info-text">{{ item.remark }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item-footer">
|
||||
<text class="item-time">{{ formatTime(item.createTime) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</u-list-item>
|
||||
<u-loadmore :status="loadStatus" />
|
||||
</u-list>
|
||||
</view>
|
||||
|
||||
<!-- 底部添加按钮 -->
|
||||
<view class="fab-container">
|
||||
<button class="fab-button" @click="addChannel">
|
||||
<uni-icons type="plus" size="24" color="#fff"></uni-icons>
|
||||
<text class="fab-text">新增渠道</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
request
|
||||
} from '@/utils/request';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
channelList: [],
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
loadStatus: 'loadmore', // loadmore | loading | nomore
|
||||
total: 0
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
uni.setNavigationBarTitle({
|
||||
title: '渠道管理'
|
||||
});
|
||||
this.loadChannelList();
|
||||
},
|
||||
onShow() {
|
||||
// 从新增/编辑页返回时刷新列表
|
||||
if (this.page === 1) {
|
||||
this.loadChannelList();
|
||||
}
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
// #ifdef MP-WEIXIN
|
||||
this.page = 1;
|
||||
this.channelList = [];
|
||||
this.loadChannelList();
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
// 加载渠道列表
|
||||
loadChannelList() {
|
||||
this.loadStatus = 'loading';
|
||||
request({
|
||||
url: '/v1/frontend/business/channel/list',
|
||||
data: {
|
||||
page: this.page,
|
||||
limit: this.pageSize
|
||||
}
|
||||
}).then((response) => {
|
||||
// #ifdef MP-WEIXIN
|
||||
uni.stopPullDownRefresh();
|
||||
// #endif
|
||||
|
||||
if (response.data.code === 10000 || response.data.code === 200) {
|
||||
const list = response.data.data.list || response.data.data.records || [];
|
||||
if (this.page === 1) {
|
||||
this.channelList = list;
|
||||
} else {
|
||||
this.channelList = [...this.channelList, ...list];
|
||||
}
|
||||
this.total = response.data.data.total || 0;
|
||||
|
||||
if (this.channelList.length >= this.total) {
|
||||
this.loadStatus = 'nomore';
|
||||
} else {
|
||||
this.loadStatus = 'loadmore';
|
||||
}
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: response.data.message || '加载失败',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
this.loadStatus = 'loadmore';
|
||||
}
|
||||
}).catch((error) => {
|
||||
// #ifdef MP-WEIXIN
|
||||
uni.stopPullDownRefresh();
|
||||
// #endif
|
||||
|
||||
console.error('加载渠道列表失败:', error);
|
||||
uni.showToast({
|
||||
title: '网络错误,请重试',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
this.loadStatus = 'loadmore';
|
||||
});
|
||||
},
|
||||
|
||||
// 滚动到底部加载更多
|
||||
scrolltolower() {
|
||||
if (this.loadStatus === 'loadmore') {
|
||||
this.page++;
|
||||
this.loadChannelList();
|
||||
}
|
||||
},
|
||||
|
||||
// 新增渠道
|
||||
addChannel() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/channel/add'
|
||||
});
|
||||
},
|
||||
|
||||
// 编辑渠道
|
||||
editChannel(item) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/channel/add?id=${item.id || item.lId}`
|
||||
});
|
||||
},
|
||||
|
||||
// 格式化时间
|
||||
formatTime(time) {
|
||||
if (!time) return '';
|
||||
const date = new Date(time);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
padding-bottom: 100rpx;
|
||||
}
|
||||
|
||||
.list-container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
margin-bottom: 20rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.item-content {
|
||||
padding: 30rpx;
|
||||
}
|
||||
|
||||
.item-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.item-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.item-status {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
padding: 8rpx 16rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.status-active {
|
||||
color: #22c55e;
|
||||
background-color: #f0fdf4;
|
||||
}
|
||||
|
||||
.item-info {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.info-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
margin-left: 12rpx;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.item-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding-top: 20rpx;
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.item-time {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 底部悬浮按钮 */
|
||||
.fab-container {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
border-top: 1rpx solid #f0f0f0;
|
||||
/* #ifdef H5 */
|
||||
box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
/* #endif */
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.fab-button {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
|
||||
border: none;
|
||||
border-radius: 12rpx;
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 8rpx 24rpx rgba(99, 102, 241, 0.3);
|
||||
|
||||
/* #ifdef H5 */
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-2rpx);
|
||||
box-shadow: 0 12rpx 32rpx rgba(99, 102, 241, 0.4);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.fab-text {
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
|
||||
/* H5适配 */
|
||||
/* #ifdef H5 */
|
||||
.page-container {
|
||||
padding-bottom: 120rpx;
|
||||
}
|
||||
|
||||
.fab-container {
|
||||
padding: 30rpx 40rpx;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
/* 小程序适配 */
|
||||
/* #ifdef MP-WEIXIN */
|
||||
.fab-container {
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
|
||||
336
pages/channel/login.vue
Normal file
@@ -0,0 +1,336 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<view class="hero">
|
||||
<view class="hero-title">渠道登录</view>
|
||||
<view class="hero-subtitle">登录后进入数据面板</view>
|
||||
</view>
|
||||
|
||||
<!-- 账号密码登录(H5 + 小程序通用) -->
|
||||
<view class="card">
|
||||
<view class="card-title">账号密码登录</view>
|
||||
<uni-forms ref="h5Form" :modelValue="form">
|
||||
<uni-forms-item name="phone">
|
||||
<uni-easyinput
|
||||
v-model="form.phone"
|
||||
placeholder="请输入手机号"
|
||||
type="number"
|
||||
maxlength="11"
|
||||
:inputBorder="false"
|
||||
class="input"
|
||||
/>
|
||||
</uni-forms-item>
|
||||
<uni-forms-item name="password">
|
||||
<uni-easyinput
|
||||
v-model="form.password"
|
||||
placeholder="请输入密码"
|
||||
:inputBorder="false"
|
||||
type="password"
|
||||
class="input"
|
||||
/>
|
||||
</uni-forms-item>
|
||||
</uni-forms>
|
||||
<view class="login-tip">
|
||||
<text>默认初始密码为 </text>
|
||||
<text class="login-tip-strong">123456</text>
|
||||
<text>,登录后请及时修改。</text>
|
||||
</view>
|
||||
<button class="primary-btn" :disabled="isSubmitting" @click="handleH5Login">
|
||||
<text>{{ isSubmitting ? '登录中...' : '登录' }}</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from '@/config'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
phone: '',
|
||||
password: ''
|
||||
},
|
||||
isSubmitting: false,
|
||||
companyId: ''
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
// 获取参数
|
||||
let scene = options.scene;
|
||||
let companyId = options.companyId;
|
||||
|
||||
console.log('页面参数:', { scene, companyId });
|
||||
|
||||
// 小程序端解析 scene 参数
|
||||
// #ifdef MP-WEIXIN
|
||||
if (scene != undefined) {
|
||||
// 先对 scene 进行 URL 解码(处理 %2C 等编码字符)
|
||||
try {
|
||||
scene = decodeURIComponent(scene);
|
||||
} catch (e) {
|
||||
console.warn('scene 解码失败,使用原始值:', e);
|
||||
}
|
||||
|
||||
// scene 中可能包含 companyId,或者直接就是 companyId
|
||||
// 如果 scene 包含逗号,可能需要分割(根据实际业务需求调整)
|
||||
if (scene.includes(',')) {
|
||||
// 如果 scene 包含逗号,取第一部分作为 companyId
|
||||
const parts = scene.split(',');
|
||||
this.companyId = parts[0] || '';
|
||||
} else {
|
||||
// 如果不包含逗号,scene 本身就是 companyId
|
||||
this.companyId = scene;
|
||||
}
|
||||
} else if (companyId != undefined) {
|
||||
// 兼容直接传 companyId 参数
|
||||
this.companyId = companyId;
|
||||
} else {
|
||||
// 尝试从本地存储获取(之前可能保存过)
|
||||
const storedCompanyId = uni.getStorageSync('channelCompanyId');
|
||||
if (storedCompanyId) {
|
||||
this.companyId = storedCompanyId;
|
||||
console.log('从本地存储获取companyId:', storedCompanyId);
|
||||
} else {
|
||||
this.companyId = '';
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
|
||||
// H5 端兼容处理
|
||||
// #ifdef H5
|
||||
if (companyId != undefined) {
|
||||
// H5 端优先使用 companyId 参数
|
||||
this.companyId = companyId;
|
||||
} else if (scene != undefined) {
|
||||
// H5 也可能有 scene 参数(从分享链接等)
|
||||
// 先对 scene 进行 URL 解码
|
||||
try {
|
||||
scene = decodeURIComponent(scene);
|
||||
} catch (e) {
|
||||
console.warn('scene 解码失败,使用原始值:', e);
|
||||
}
|
||||
|
||||
if (scene.includes(',')) {
|
||||
const parts = scene.split(',');
|
||||
this.companyId = parts[0] || '';
|
||||
} else {
|
||||
this.companyId = scene;
|
||||
}
|
||||
} else {
|
||||
// 尝试从本地存储获取
|
||||
const storedCompanyId = uni.getStorageSync('channelCompanyId');
|
||||
if (storedCompanyId) {
|
||||
this.companyId = storedCompanyId;
|
||||
console.log('从本地存储获取companyId:', storedCompanyId);
|
||||
} else {
|
||||
this.companyId = '';
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
|
||||
console.log('解析结果:', { companyId: this.companyId });
|
||||
},
|
||||
methods: {
|
||||
// 账号密码登录(H5 + 小程序)
|
||||
handleH5Login() {
|
||||
if (this.isSubmitting) return
|
||||
if (!this.form.phone || !this.form.password) {
|
||||
uni.showToast({ title: '请输入手机号和密码', icon: 'none', duration: 2000 })
|
||||
return
|
||||
}
|
||||
if (!this.companyId) {
|
||||
uni.showToast({ title: '缺少companyId参数', icon: 'none', duration: 2000 })
|
||||
return
|
||||
}
|
||||
this.isSubmitting = true
|
||||
|
||||
// 使用和列表接口一样的请求方式和参数格式
|
||||
uni.request({
|
||||
method: 'POST',
|
||||
url: config.apiUrl2 + '/v1/frontend/distribution/user/login',
|
||||
data: {
|
||||
companyId: this.companyId,
|
||||
phone: this.form.phone,
|
||||
password: this.form.password
|
||||
},
|
||||
header: {
|
||||
'content-type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
success: (res) => {
|
||||
this.isSubmitting = false
|
||||
console.log('登录接口完整返回:', res)
|
||||
console.log('登录接口返回数据:', res.data)
|
||||
|
||||
if (res.data.code === 10000 || res.data.code === 200) {
|
||||
const data = res.data.data || {}
|
||||
const token = data.token || ''
|
||||
const channelInfo = data.channelInfo || {}
|
||||
|
||||
console.log('解析后的data:', data)
|
||||
console.log('解析后的token:', token)
|
||||
console.log('解析后的channelInfo:', channelInfo)
|
||||
|
||||
// 保存token
|
||||
if (token) {
|
||||
uni.setStorageSync('channelToken', token)
|
||||
console.log('已保存token到本地存储')
|
||||
} else {
|
||||
console.error('token为空,无法保存')
|
||||
}
|
||||
|
||||
// 保存完整的登录数据(备用)
|
||||
uni.setStorageSync('channelLoginData', JSON.stringify(data))
|
||||
console.log('已保存完整登录数据到本地存储')
|
||||
|
||||
// 保存渠道信息 - 从channelInfo中获取
|
||||
if (channelInfo.channelCode) {
|
||||
uni.setStorageSync('channelCode', channelInfo.channelCode)
|
||||
console.log('已保存channelCode:', channelInfo.channelCode)
|
||||
} else {
|
||||
console.warn('channelInfo.channelCode为空,无法保存')
|
||||
}
|
||||
|
||||
if (channelInfo.channelName) {
|
||||
uni.setStorageSync('channelName', channelInfo.channelName)
|
||||
console.log('已保存channelName:', channelInfo.channelName)
|
||||
} else {
|
||||
console.warn('channelInfo.channelName为空,无法保存')
|
||||
}
|
||||
|
||||
// 验证保存是否成功
|
||||
const savedCode = uni.getStorageSync('channelCode')
|
||||
const savedName = uni.getStorageSync('channelName')
|
||||
const savedToken = uni.getStorageSync('channelToken')
|
||||
console.log('验证保存结果:', { savedCode, savedName, savedToken })
|
||||
|
||||
if (!savedCode) {
|
||||
console.error('警告:channelCode保存失败!')
|
||||
uni.showToast({
|
||||
title: '渠道编码保存失败,请重试',
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
this.toStatistics()
|
||||
} else {
|
||||
const msg = res.data.message || res.data.msg || '登录失败'
|
||||
console.error('登录失败:', msg)
|
||||
uni.showToast({ title: msg, icon: 'none', duration: 3000 })
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('登录失败', err)
|
||||
this.isSubmitting = false
|
||||
uni.showToast({ title: '网络错误,请重试', icon: 'none', duration: 2000 })
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
toStatistics() {
|
||||
uni.redirectTo({
|
||||
url: '/pages/channel/statistics'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-container {
|
||||
min-height: 100vh;
|
||||
background: linear-gradient(180deg, #f5f7ff 0%, #f8f8f8 100%);
|
||||
padding: 40rpx 30rpx 80rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.hero {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: 44rpx;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
margin-top: 8rpx;
|
||||
font-size: 26rpx;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 32rpx 28rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #111827;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
background: #f5f6fa;
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.login-tip {
|
||||
margin-top: 16rpx;
|
||||
margin-bottom: 8rpx;
|
||||
font-size: 24rpx;
|
||||
color: #6b7280;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.login-tip-strong {
|
||||
font-weight: 600;
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
.primary-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
|
||||
border: none;
|
||||
border-radius: 12rpx;
|
||||
color: #fff;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 12rpx;
|
||||
box-shadow: 0 8rpx 24rpx rgba(99, 102, 241, 0.25);
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin-top: 16rpx;
|
||||
font-size: 24rpx;
|
||||
color: #6b7280;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* #ifdef H5 */
|
||||
.primary-btn {
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
&:hover {
|
||||
transform: translateY(-2rpx);
|
||||
box-shadow: 0 10rpx 28rpx rgba(99, 102, 241, 0.3);
|
||||
}
|
||||
&:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
|
||||
177
pages/channel/project-select.vue
Normal file
@@ -0,0 +1,177 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<view class="header">
|
||||
<view class="title">选择项目</view>
|
||||
<view class="subtitle">请选择要查看的渠道项目</view>
|
||||
</view>
|
||||
|
||||
<view v-if="loading" class="loading">
|
||||
<uni-icons type="spinner-cycle" size="32" color="#6366f1"></uni-icons>
|
||||
<text class="loading-text">加载中...</text>
|
||||
</view>
|
||||
|
||||
<view v-else-if="projects.length === 0" class="empty">
|
||||
<uni-icons type="info" size="40" color="#ccc"></uni-icons>
|
||||
<text class="empty-text">暂无可选项目</text>
|
||||
</view>
|
||||
|
||||
<view v-else class="list">
|
||||
<view
|
||||
v-for="(item, index) in projects"
|
||||
:key="index"
|
||||
class="project-card"
|
||||
@click="selectProject(item)"
|
||||
>
|
||||
<view class="project-main">
|
||||
<view class="project-name">{{ item.name || '未命名项目' }}</view>
|
||||
<view class="project-code">编码:{{ item.code || '--' }}</view>
|
||||
</view>
|
||||
<uni-icons type="arrowright" size="20" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from '@/config'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
projects: []
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
this.fetchProjects()
|
||||
},
|
||||
methods: {
|
||||
fetchProjects() {
|
||||
const token = uni.getStorageSync('channelToken')
|
||||
if (!token) {
|
||||
uni.showToast({ title: '请先登录', icon: 'none', duration: 2000 })
|
||||
uni.redirectTo({ url: '/pages/channel/login' })
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
uni.request({
|
||||
method: 'GET',
|
||||
url: config.apiUrl2 + '/v1/frontend/distribution/channel/projects',
|
||||
header: {
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
token
|
||||
},
|
||||
success: (res) => {
|
||||
this.loading = false
|
||||
if (res.data.code === 10000 || res.data.code === 200) {
|
||||
this.projects = res.data.data?.list || res.data.data || []
|
||||
} else {
|
||||
const msg = res.data.message || res.data.msg || '加载失败'
|
||||
uni.showToast({ title: msg, icon: 'none', duration: 3000 })
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('加载项目失败', err)
|
||||
this.loading = false
|
||||
uni.showToast({ title: '网络错误,请重试', icon: 'none', duration: 2000 })
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
selectProject(item) {
|
||||
const name = encodeURIComponent(item.name || '')
|
||||
const code = encodeURIComponent(item.code || '')
|
||||
uni.navigateTo({
|
||||
url: `/pages/channel/statistics?name=${name}&code=${code}`
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-container {
|
||||
min-height: 100vh;
|
||||
background: #f5f6fb;
|
||||
padding: 32rpx 28rpx 60rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 38rpx;
|
||||
font-weight: 700;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
margin-top: 8rpx;
|
||||
font-size: 26rpx;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.loading,
|
||||
.empty {
|
||||
margin-top: 120rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.loading-text,
|
||||
.empty-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.project-card {
|
||||
background: #fff;
|
||||
border-radius: 14rpx;
|
||||
padding: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
box-shadow: 0 4rpx 14rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.project-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.project-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.project-code {
|
||||
font-size: 26rpx;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
/* #ifdef H5 */
|
||||
.project-card {
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
&:hover {
|
||||
transform: translateY(-2rpx);
|
||||
box-shadow: 0 8rpx 18rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
|
||||
2183
pages/channel/statistics.vue
Normal file
421
pages/form/input.vue
Normal file
@@ -0,0 +1,421 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<!-- 表单内容 -->
|
||||
<view class="form-container">
|
||||
<!-- 计划名称 -->
|
||||
<view class="form-group">
|
||||
<text class="form-label">计划名称</text>
|
||||
<view class="form-value">
|
||||
<text class="value-text">{{taskname}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 手机号输入 -->
|
||||
<view class="form-group">
|
||||
<text class="form-label required">手机号/微信号</text>
|
||||
<view class="input-wrapper">
|
||||
<textarea
|
||||
class="form-input"
|
||||
v-model="form.phone"
|
||||
:placeholder="phonePlaceholder"
|
||||
:maxlength="500"
|
||||
:auto-height="true"
|
||||
></textarea>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-wrapper">
|
||||
<button
|
||||
class="submit-button"
|
||||
:class="{loading: isSubmitting, success: submitSuccess}"
|
||||
@click="submit"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<text class="button-text">
|
||||
{{submitSuccess ? '提交成功' : (isSubmitting ? '提交中...' : '提交')}}
|
||||
</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
phone: ""
|
||||
},
|
||||
// 多行 placeholder 需要放在 data 中,避免模板字符串里直接换行导致小程序编译错误
|
||||
phonePlaceholder: '请输入手机号或微信号,如有备注请用逗号隔开,多个用换行隔开,格式如下:18888888888,张三',
|
||||
taskid: '',
|
||||
taskname: '',
|
||||
cid: '',
|
||||
isSubmitting: false,
|
||||
submitSuccess: false
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
let taskId = options.id;
|
||||
let cid = options.channelId;
|
||||
//h5
|
||||
if (taskId != undefined) {
|
||||
this.taskid = taskId;
|
||||
this.cid = cid;
|
||||
} else {
|
||||
let paramsArr = decodeURIComponent(options.scene).split('&');
|
||||
this.taskid = paramsArr[0].split('=')[1];
|
||||
this.cid = paramsArr[1].split('=')[1];
|
||||
}
|
||||
//修改标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: "表单录入"
|
||||
});
|
||||
|
||||
this.getPosterData();
|
||||
},
|
||||
methods: {
|
||||
getPosterData() {
|
||||
let that = this;
|
||||
uni.request({
|
||||
method: 'POST',
|
||||
url: that.$config.apiUrl2 + '/v1/frontend/business/poster/getone',
|
||||
data: {
|
||||
oldId: this.taskid
|
||||
},
|
||||
success: (res) => {
|
||||
console.log(res)
|
||||
if (res.data.code == 200) {
|
||||
that.taskname = res.data.data.name
|
||||
that.taskid = res.data.data.task.id
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
submit() {
|
||||
let that = this;
|
||||
|
||||
// 防止重复提交
|
||||
if (that.isSubmitting) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!that.form.phone.length) {
|
||||
return uni.showToast({
|
||||
title: '请输入手机号或微信号',
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
});
|
||||
}
|
||||
|
||||
// 开始提交
|
||||
that.isSubmitting = true;
|
||||
|
||||
let data = {
|
||||
id: that.taskid,
|
||||
cid: that.cid,
|
||||
phone: that.form.phone,
|
||||
}
|
||||
uni.request({
|
||||
method: 'POST',
|
||||
url: that.$config.apiUrl2 + '/v1/frontend/business/form/importsave',
|
||||
data: data,
|
||||
success: (res) => {
|
||||
console.log(res)
|
||||
if (res.data.code == 200) {
|
||||
// 处理响应数据
|
||||
that.submitSuccess = true;
|
||||
that.form.phone = ""
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
});
|
||||
// 3秒后重置成功状态
|
||||
setTimeout(() => {
|
||||
that.submitSuccess = false;
|
||||
}, 3000);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error('提交失败:', error);
|
||||
uni.showToast({
|
||||
title: '网络错误,请重试',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
},
|
||||
complete: () => {
|
||||
// 无论成功失败都重置提交状态
|
||||
that.isSubmitting = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 页面容器 */
|
||||
.page-container {
|
||||
min-height: 100vh;
|
||||
background: #fff;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/* 表单容器 */
|
||||
.form-container {
|
||||
padding: 40px 24px;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background: #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 表单项 */
|
||||
.form-group {
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: block;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
margin-bottom: 12px;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
.form-label.required {
|
||||
color: #e74c3c;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-label.required::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: -8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background: #e74c3c;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/* 计划名称显示 */
|
||||
.form-value {
|
||||
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 12px;
|
||||
padding: 16px 20px;
|
||||
min-height: 52px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.form-value::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
}
|
||||
|
||||
.value-text {
|
||||
font-size: 16px;
|
||||
color: #2c3e50;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
/* 输入框包装器 */
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
min-height: 120px;
|
||||
padding: 20px;
|
||||
font-size: 16px;
|
||||
color: #2c3e50;
|
||||
background: #fff;
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 12px;
|
||||
outline: none;
|
||||
resize: none;
|
||||
line-height: 1.6;
|
||||
transition: all 0.3s ease;
|
||||
font-family: inherit;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.1);
|
||||
transform: translateY(-2px);
|
||||
background: #fafbfc;
|
||||
}
|
||||
|
||||
.form-input::placeholder {
|
||||
color: #95a5a6;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
/* 提交按钮区域 */
|
||||
.submit-wrapper {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
width: 100%;
|
||||
height: 56px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border: none;
|
||||
border-radius: 16px;
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
letter-spacing: 0.5px;
|
||||
box-shadow: 0 8px 24px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.submit-button::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||
transition: left 0.5s;
|
||||
}
|
||||
|
||||
.submit-button:hover:not(:disabled) {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 12px 32px rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.submit-button:active:not(:disabled) {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.submit-button:active::before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
.submit-button.loading {
|
||||
background: linear-gradient(135deg, #95a5a6 0%, #7f8c8d 100%);
|
||||
pointer-events: none;
|
||||
box-shadow: 0 8px 24px rgba(149, 165, 166, 0.3);
|
||||
}
|
||||
|
||||
.submit-button.success {
|
||||
background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%);
|
||||
box-shadow: 0 8px 24px rgba(39, 174, 96, 0.3);
|
||||
}
|
||||
|
||||
.submit-button:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.button-text {
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 375px) {
|
||||
.form-container {
|
||||
padding: 32px 20px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.submit-wrapper {
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
height: 50px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 优雅的动画效果 */
|
||||
.form-container {
|
||||
animation: slideInUp 0.6s ease-out;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
animation: fadeInUp 0.5s ease-out;
|
||||
}
|
||||
|
||||
.form-group:nth-child(1) {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.form-group:nth-child(2) {
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.submit-wrapper {
|
||||
animation: fadeInUp 0.5s ease-out 0.6s both;
|
||||
}
|
||||
|
||||
@keyframes slideInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
424
pages/form/input2.vue
Normal file
@@ -0,0 +1,424 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<!-- 表单内容 -->
|
||||
<view class="form-container">
|
||||
<!-- 计划名称 -->
|
||||
<view class="form-group">
|
||||
<text class="form-label">计划名称</text>
|
||||
<view class="form-value">
|
||||
<text class="value-text">{{taskname}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 手机号输入 -->
|
||||
<view class="form-group">
|
||||
<text class="form-label required">手机号/微信号</text>
|
||||
<view class="input-wrapper">
|
||||
<textarea
|
||||
class="form-input"
|
||||
v-model="form.phone"
|
||||
:placeholder="phonePlaceholder"
|
||||
:maxlength="500"
|
||||
:auto-height="true"
|
||||
></textarea>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-wrapper">
|
||||
<button
|
||||
class="submit-button"
|
||||
:class="{loading: isSubmitting, success: submitSuccess}"
|
||||
@click="submit"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<text class="button-text">
|
||||
{{submitSuccess ? '提交成功' : (isSubmitting ? '提交中...' : '提交')}}
|
||||
</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
request
|
||||
} from '@/utils/request';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
phone: ""
|
||||
},
|
||||
// 多行 placeholder 需要放在 data 中,避免模板字符串里直接换行导致小程序编译错误
|
||||
phonePlaceholder: '请输入手机号或微信号,如有备注请用逗号隔开,多个用换行隔开,格式如下:18888888888,张三',
|
||||
token: "test",
|
||||
taskid: '',
|
||||
taskname: '',
|
||||
cid: '',
|
||||
isSubmitting: false,
|
||||
submitSuccess: false
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
let taskId = options.id;
|
||||
let cid = options.channelId;
|
||||
//h5
|
||||
if (taskId != undefined) {
|
||||
this.taskid = taskId;
|
||||
this.cid = cid;
|
||||
} else {
|
||||
let paramsArr = decodeURIComponent(options.scene).split('&');
|
||||
this.taskid = paramsArr[0].split('=')[1];
|
||||
this.cid = paramsArr[1].split('=')[1];
|
||||
}
|
||||
//修改标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: "表单录入"
|
||||
});
|
||||
|
||||
this.getPosterData();
|
||||
},
|
||||
methods: {
|
||||
getPosterData() {
|
||||
let that = this;
|
||||
uni.request({
|
||||
method: 'POST',
|
||||
url: that.$config.apiUrl2 + '/v1/frontend/business/poster/getone',
|
||||
data: {
|
||||
id: that.taskid,
|
||||
},
|
||||
success: (res) => {
|
||||
console.log(res)
|
||||
if (res.data.code == 200) {
|
||||
that.taskname = res.data.data.name
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
submit() {
|
||||
let that = this;
|
||||
|
||||
// 防止重复提交
|
||||
if (that.isSubmitting) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!that.form.phone.length) {
|
||||
return uni.showToast({
|
||||
title: '请输入手机号或微信号',
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
});
|
||||
}
|
||||
|
||||
// 开始提交
|
||||
that.isSubmitting = true;
|
||||
|
||||
let data = {
|
||||
id: that.taskid,
|
||||
cid: that.cid,
|
||||
phone: that.form.phone,
|
||||
}
|
||||
uni.request({
|
||||
method: 'POST',
|
||||
url: that.$config.apiUrl2 + '/v1/frontend/business/form/importsave',
|
||||
data: data,
|
||||
success: (res) => {
|
||||
console.log(res)
|
||||
if (res.data.code == 200) {
|
||||
// 处理响应数据
|
||||
that.submitSuccess = true;
|
||||
that.form.phone = ""
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
});
|
||||
// 3秒后重置成功状态
|
||||
setTimeout(() => {
|
||||
that.submitSuccess = false;
|
||||
}, 3000);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error('提交失败:', error);
|
||||
uni.showToast({
|
||||
title: '网络错误,请重试',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
},
|
||||
complete: () => {
|
||||
// 无论成功失败都重置提交状态
|
||||
that.isSubmitting = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 页面容器 */
|
||||
.page-container {
|
||||
min-height: 100vh;
|
||||
background: #fff;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/* 表单容器 */
|
||||
.form-container {
|
||||
padding: 40px 24px;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background: #fff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 表单项 */
|
||||
.form-group {
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: block;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
margin-bottom: 12px;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
.form-label.required {
|
||||
color: #e74c3c;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-label.required::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: -8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background: #e74c3c;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/* 计划名称显示 */
|
||||
.form-value {
|
||||
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 12px;
|
||||
padding: 16px 20px;
|
||||
min-height: 52px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.form-value::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
}
|
||||
|
||||
.value-text {
|
||||
font-size: 16px;
|
||||
color: #2c3e50;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
/* 输入框包装器 */
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
min-height: 120px;
|
||||
padding: 20px;
|
||||
font-size: 16px;
|
||||
color: #2c3e50;
|
||||
background: #fff;
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 12px;
|
||||
outline: none;
|
||||
resize: none;
|
||||
line-height: 1.6;
|
||||
transition: all 0.3s ease;
|
||||
font-family: inherit;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 0 0 4px rgba(102, 126, 234, 0.1);
|
||||
transform: translateY(-2px);
|
||||
background: #fafbfc;
|
||||
}
|
||||
|
||||
.form-input::placeholder {
|
||||
color: #95a5a6;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
/* 提交按钮区域 */
|
||||
.submit-wrapper {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
width: 100%;
|
||||
height: 56px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border: none;
|
||||
border-radius: 16px;
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
letter-spacing: 0.5px;
|
||||
box-shadow: 0 8px 24px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.submit-button::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||
transition: left 0.5s;
|
||||
}
|
||||
|
||||
.submit-button:hover:not(:disabled) {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 12px 32px rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.submit-button:active:not(:disabled) {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.submit-button:active::before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
.submit-button.loading {
|
||||
background: linear-gradient(135deg, #95a5a6 0%, #7f8c8d 100%);
|
||||
pointer-events: none;
|
||||
box-shadow: 0 8px 24px rgba(149, 165, 166, 0.3);
|
||||
}
|
||||
|
||||
.submit-button.success {
|
||||
background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%);
|
||||
box-shadow: 0 8px 24px rgba(39, 174, 96, 0.3);
|
||||
}
|
||||
|
||||
.submit-button:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.button-text {
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 375px) {
|
||||
.form-container {
|
||||
padding: 32px 20px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.submit-wrapper {
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
height: 50px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 优雅的动画效果 */
|
||||
.form-container {
|
||||
animation: slideInUp 0.6s ease-out;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
animation: fadeInUp 0.5s ease-out;
|
||||
}
|
||||
|
||||
.form-group:nth-child(1) {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.form-group:nth-child(2) {
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.submit-wrapper {
|
||||
animation: fadeInUp 0.5s ease-out 0.6s both;
|
||||
}
|
||||
|
||||
@keyframes slideInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
113
pages/form/list.vue
Normal file
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<view class="u-page">
|
||||
<u-list @scrolltolower="scrolltolower">
|
||||
<u-list-item v-for="(item, index) in dataList" :key="index" class="custom-list-item">
|
||||
<view class="list-item-content">
|
||||
<u-cell :title="item.sPhoneOrWechatId" class="cell-item" :border="false" />
|
||||
<view class="additional-info">
|
||||
<text class="item-time">{{ item.dNewTime }}</text>
|
||||
<text class="item-status">{{ item.status }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</u-list-item>
|
||||
<u-loadmore :status="status" />
|
||||
</u-list>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
request
|
||||
} from '@/utils/request';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
status: "",
|
||||
page: 1,
|
||||
limit: 20,
|
||||
dataList: []
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
scrolltolower() {
|
||||
this.page++
|
||||
this.loadmore()
|
||||
},
|
||||
loadmore() {
|
||||
this.status = "loading"
|
||||
request({
|
||||
url: '/v1/frontend/business/form/listdata',
|
||||
data: {
|
||||
page: this.page,
|
||||
limit: this.limit
|
||||
},
|
||||
// ...
|
||||
}).then((response) => {
|
||||
for (let i = 0; i < response.data.data.list.length; i++) {
|
||||
let data = response.data.data.list[i]
|
||||
data.status = "333"
|
||||
this.dataList.push(data)
|
||||
}
|
||||
|
||||
if (response.data.data.list.length == 0) {
|
||||
this.status = "nomore"
|
||||
} else {
|
||||
this.status = ""
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
// 处理错误
|
||||
});
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
uni.setNavigationBarTitle({
|
||||
title: "我的表单"
|
||||
});
|
||||
|
||||
this.loadmore()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.custom-list-item {
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.list-item-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.cell-item {
|
||||
border-bottom: none;
|
||||
font-size: 16px;
|
||||
/* 标题字体大小 */
|
||||
color: #333;
|
||||
/* 标题字体颜色 */
|
||||
}
|
||||
|
||||
.additional-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.item-time {
|
||||
color: #666;
|
||||
/* 时间的颜色 */
|
||||
font-size: 12px;
|
||||
/* 时间的字体大小 */
|
||||
}
|
||||
|
||||
.item-status {
|
||||
color: #1989fa;
|
||||
/* 状态的颜色,可根据实际需求调整 */
|
||||
font-size: 14px;
|
||||
/* 状态的字体大小 */
|
||||
}
|
||||
</style>
|
||||
22
pages/home/home.vue
Normal file
@@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
912
pages/index/index.vue
Normal file
@@ -0,0 +1,912 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- Header Navigation -->
|
||||
<view class="header-nav">
|
||||
<view class="nav-content">
|
||||
<view class="nav-title">存客宝</view>
|
||||
<view class="nav-avatar" @click="goToLogin">
|
||||
<image class="avatar-img" src="/static/tabbar/me.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- Hero Section -->
|
||||
<view class="hero-section">
|
||||
<view class="hero-content">
|
||||
<view class="badge">场景化客户留存 SaaS 工具</view>
|
||||
<view class="hero-title">
|
||||
<text class="title-main">存客宝</text>
|
||||
<text class="title-sub">私域流量运营专家</text>
|
||||
</view>
|
||||
<view class="hero-desc">
|
||||
专注于场景化客户留存的私域流量运营工具,帮助中小企业将多平台公域流量高效转化为私域客户资产,通过数据驱动的精细化运营提升客户粘性和生命周期价值
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 立即体验按钮 -->
|
||||
<view class="cta-button-section">
|
||||
<button class="cta-button" @click="showDialogBtn">
|
||||
<text class="button-text">立即体验</text>
|
||||
<text class="arrow">→</text>
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- Core Values Section -->
|
||||
<view class="section values-section">
|
||||
<view class="section-header">
|
||||
<view class="section-title">核心价值与优势</view>
|
||||
<view class="section-desc">通过统一管理、智能触达和数据驱动,全面提升企业私域运营效率</view>
|
||||
</view>
|
||||
|
||||
<view class="values-grid">
|
||||
<view class="value-card">
|
||||
<view class="card-icon users-icon">👥</view>
|
||||
<view class="card-title">统一管理 (存客)</view>
|
||||
<view class="card-desc">一站式平台统一存储、管理和追踪来自各渠道的客户数据及关联的微信号状态,告别数据分散管理困难</view>
|
||||
</view>
|
||||
|
||||
<view class="value-card">
|
||||
<view class="card-icon target-icon">🎯</view>
|
||||
<view class="card-title">智能触达 (获客)</view>
|
||||
<view class="card-desc">场景化获客配置打通线上线下流量入口,利用AI智能内容库和多平台工作台高效触达转化客户</view>
|
||||
</view>
|
||||
|
||||
<view class="value-card">
|
||||
<view class="card-icon chart-icon">📊</view>
|
||||
<view class="card-title">数据驱动 (宝)</view>
|
||||
<view class="card-desc">通过数据统计与分析量化运营效果,优化营销策略,实现营销活动的标准化和数据化决策</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Functional Modules Section -->
|
||||
<view class="section modules-section">
|
||||
<view class="section-header">
|
||||
<view class="section-title">五大核心功能模块</view>
|
||||
<view class="section-desc">从数据概览到客户获取,从内容管理到多平台运营,全方位覆盖私域运营需求</view>
|
||||
</view>
|
||||
|
||||
<view class="modules-grid">
|
||||
<view class="module-card primary-border">
|
||||
<view class="module-header">
|
||||
<view class="module-icon primary-bg">📊</view>
|
||||
<view class="module-title">数据概览</view>
|
||||
</view>
|
||||
<view class="module-desc">实时展示微信号总数、健康度、新增好友数等关键指标,提供运营全局概览和数据可视化分析</view>
|
||||
</view>
|
||||
|
||||
<view class="module-card secondary-border">
|
||||
<view class="module-header">
|
||||
<view class="module-icon secondary-bg">🌐</view>
|
||||
<view class="module-title">场景化获客</view>
|
||||
</view>
|
||||
<view class="module-desc">标准化多渠道获客入口配置,支持抖音、小红书、公众号、海报、付款码等多种获客场景</view>
|
||||
</view>
|
||||
|
||||
<view class="module-card accent-border">
|
||||
<view class="module-header">
|
||||
<view class="module-icon accent-bg">🧠</view>
|
||||
<view class="module-title">智能内容库</view>
|
||||
</view>
|
||||
<view class="module-desc">多源内容采集、智能分类标签、AI分析改写,提供内容集中管理和API接口开放能力</view>
|
||||
</view>
|
||||
|
||||
<view class="module-card orange-border">
|
||||
<view class="module-header">
|
||||
<view class="module-icon orange-bg">⚡</view>
|
||||
<view class="module-title">运营工作台</view>
|
||||
</view>
|
||||
<view class="module-desc">社交矩阵运营操作中心,支持多渠道内容推送、跨设备同步、智能优化建议和任务调度</view>
|
||||
</view>
|
||||
|
||||
<view class="module-card red-border">
|
||||
<view class="module-header">
|
||||
<view class="module-icon red-bg">⚙️</view>
|
||||
<view class="module-title">设备监控</view>
|
||||
</view>
|
||||
<view class="module-desc">实时监控设备状态、微信号健康度,支持微信号替换后的数据继承和异常预警机制</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Scenario Examples Section -->
|
||||
<view class="section scenarios-section">
|
||||
<view class="section-header">
|
||||
<view class="section-title">应用场景示例</view>
|
||||
<view class="section-desc">不同行业和业务场景下的实际应用案例</view>
|
||||
</view>
|
||||
|
||||
<view class="scenarios-grid">
|
||||
<view class="scenario-card">
|
||||
<view class="scenario-badge">电商零售</view>
|
||||
<view class="scenario-title">多平台流量整合</view>
|
||||
<view class="scenario-desc">某服装品牌通过存客宝整合抖音、小红书、微信公众号等多平台流量,统一管理客户数据,通过场景化获客配置提升转化率30%,客户复购率提升45%。</view>
|
||||
<view class="scenario-tags">
|
||||
<text class="tag">抖音获客</text>
|
||||
<text class="tag">内容分发</text>
|
||||
<text class="tag">客户留存</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="scenario-card">
|
||||
<view class="scenario-badge">教育培训</view>
|
||||
<view class="scenario-title">智能内容运营</view>
|
||||
<view class="scenario-desc">某在线教育机构利用AI内容改写功能,将课程内容智能适配不同平台特点,内容生产效率提升60%,学员互动率提升35%,课程转化率显著提升。</view>
|
||||
<view class="scenario-tags">
|
||||
<text class="tag">AI改写</text>
|
||||
<text class="tag">多平台推送</text>
|
||||
<text class="tag">数据分析</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- CTA Section -->
|
||||
<view class="cta-section">
|
||||
<view class="cta-content">
|
||||
<view class="cta-title">开始您的私域运营之旅</view>
|
||||
<view class="cta-desc">加入数千家企业的选择,用存客宝提升您的客户留存和运营效率</view>
|
||||
|
||||
<button class="cta-main-button" @click="showDialogBtn">
|
||||
<text class="button-text" style='color:#333;'>立即体验</text>
|
||||
<text class="arrow" style='color:#333;'>→</text>
|
||||
</button>
|
||||
|
||||
<button class="cta-secondary-button" @click="goToSite">
|
||||
<text class="button-text">访问老游条电竞学院</text>
|
||||
<text class="arrow">→</text>
|
||||
</button>
|
||||
|
||||
<view class="stats-grid">
|
||||
<view class="stat-item">
|
||||
<view class="stat-number">1000+</view>
|
||||
<view class="stat-label">企业用户</view>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<view class="stat-number">50万+</view>
|
||||
<view class="stat-label">管理客户</view>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<view class="stat-number">30%</view>
|
||||
<view class="stat-label">转化提升</view>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<view class="stat-number">24/7</view>
|
||||
<view class="stat-label">技术支持</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Footer -->
|
||||
<view class="footer">
|
||||
<view class="footer-text">© {{currentYear}} 存客宝. 保留所有权利 | 遵循"事事有回应,件件有结果,日日精进"的服务理念</view>
|
||||
</view>
|
||||
|
||||
<!-- 弹窗遮罩 -->
|
||||
<view v-if="showDialog" class="dialog-overlay" @click="hideDialog">
|
||||
<view class="dialog-content" @click.stop>
|
||||
<view class="dialog-header">
|
||||
<view class="dialog-title">申请体验存客宝</view>
|
||||
<view class="dialog-desc">我们的客服团队将在24小时内为您创建专属体验账号,并提供一对一的产品演示和使用指导。</view>
|
||||
</view>
|
||||
|
||||
<view class="dialog-form">
|
||||
<view class="form-item">
|
||||
<view class="form-label">手机号</view>
|
||||
<input class="form-input" v-model="phoneNumber" placeholder="请输入手机号" type="number" maxlength="11" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="dialog-buttons">
|
||||
<button class="dialog-button cancel-button" @click="hideDialog">取消</button>
|
||||
<button class="dialog-button confirm-button" @click="confirmBtn">确认</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 成功提示 -->
|
||||
<view v-if="showSuccessMessage" class="success-toast">
|
||||
<text class="success-text">申请已提交</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
showDialog: false,
|
||||
showSuccessMessage: false,
|
||||
taskid: 127,
|
||||
currentYear: new Date().getFullYear(),
|
||||
phoneNumber: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showDialogBtn() {
|
||||
this.showDialog = true
|
||||
},
|
||||
hideDialog() {
|
||||
this.showDialog = false
|
||||
},
|
||||
goToLogin() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/login/login'
|
||||
})
|
||||
},
|
||||
|
||||
goToSite() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/index/site'
|
||||
})
|
||||
},
|
||||
|
||||
confirmBtn() {
|
||||
let that = this;
|
||||
if (!this.phoneNumber) {
|
||||
uni.showToast({
|
||||
title: '请输入手机号',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
return
|
||||
}else{
|
||||
uni.showLoading({
|
||||
title: '请求中...',
|
||||
mask: true
|
||||
})
|
||||
uni.request({
|
||||
method: 'POST',
|
||||
header: {
|
||||
'content-type': 'application/x-www-form-urlencoded', //自定义请求头信息
|
||||
'token': that.token
|
||||
},
|
||||
url: that.$config.apiUrl2 + '/v1/frontend/business/poster/decryptphones',
|
||||
data: {
|
||||
id: that.taskid,
|
||||
phone: this.phoneNumber
|
||||
},
|
||||
success: (res) => {
|
||||
uni.hideLoading();
|
||||
if (res.data.code == 200) {
|
||||
this.showDialog = false
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '申请成功',
|
||||
success: function(res) {
|
||||
console.log(res)
|
||||
}
|
||||
})
|
||||
this.showDialog = false
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '申请失败',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 获取用户手机号
|
||||
getPhoneNumber(res) {
|
||||
let that = this;
|
||||
if (res.detail.errMsg == "getPhoneNumber:ok") {
|
||||
uni.showLoading({
|
||||
title: '请求中...',
|
||||
mask: true
|
||||
})
|
||||
uni.request({
|
||||
method: 'POST',
|
||||
header: {
|
||||
'content-type': 'application/x-www-form-urlencoded', //自定义请求头信息
|
||||
'token': that.token
|
||||
},
|
||||
url: that.$config.apiUrl2 + '/v1/frontend/business/poster/decryptphone',
|
||||
data: {
|
||||
id: that.taskid,
|
||||
code: res.detail.code
|
||||
},
|
||||
success: (res) => {
|
||||
uni.hideLoading();
|
||||
if (res.data.code == 10000) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: that.task.sTip,
|
||||
success: function(res) {
|
||||
console.log(res)
|
||||
}
|
||||
})
|
||||
this.showDialog = false
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
/* Header Navigation */
|
||||
.header-nav {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(10rpx);
|
||||
border-bottom: 1rpx solid rgba(0, 0, 0, 0.1);
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.nav-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx 32rpx;
|
||||
height: 88rpx;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #6366f1;
|
||||
}
|
||||
|
||||
.nav-avatar {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
border: 2rpx solid #e5e7eb;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.avatar-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* Hero Section */
|
||||
.hero-section {
|
||||
margin-top: calc(88rpx + var(--status-bar-height));
|
||||
background: linear-gradient(135deg, rgba(99, 102, 241, 0.05) 0%, #ffffff 50%, rgba(168, 85, 247, 0.05) 100%);
|
||||
padding: 80rpx 32rpx 120rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
max-width: 1200rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
background-color: rgba(99, 102, 241, 0.1);
|
||||
color: #6366f1;
|
||||
padding: 12rpx 24rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.title-main {
|
||||
display: block;
|
||||
font-size: 80rpx;
|
||||
font-weight: bold;
|
||||
color: #1f2937;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.title-sub {
|
||||
display: block;
|
||||
font-size: 64rpx;
|
||||
font-weight: bold;
|
||||
color: #6366f1;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.hero-desc {
|
||||
font-size: 32rpx;
|
||||
color: #6b7280;
|
||||
line-height: 1.6;
|
||||
max-width: 1000rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* CTA Button Section */
|
||||
.cta-button-section {
|
||||
padding: 64rpx 32rpx;
|
||||
text-align: center;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.cta-button {
|
||||
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 12rpx;
|
||||
padding: 24rpx 64rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 8rpx 32rpx rgba(99, 102, 241, 0.3);
|
||||
}
|
||||
|
||||
.button-text {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
margin-left: 16rpx;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Section Styles */
|
||||
.section {
|
||||
padding: 120rpx 32rpx;
|
||||
}
|
||||
|
||||
.values-section {
|
||||
background-color: rgba(249, 250, 251, 0.5);
|
||||
}
|
||||
|
||||
.section-header {
|
||||
text-align: center;
|
||||
margin-bottom: 80rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 64rpx;
|
||||
font-weight: bold;
|
||||
color: #1f2937;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.section-desc {
|
||||
font-size: 32rpx;
|
||||
color: #6b7280;
|
||||
line-height: 1.6;
|
||||
max-width: 800rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Values Grid */
|
||||
.values-grid {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 48rpx;
|
||||
}
|
||||
|
||||
.value-card {
|
||||
background: white;
|
||||
border-radius: 16rpx;
|
||||
padding: 48rpx 32rpx;
|
||||
text-align: center;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto 24rpx;
|
||||
font-size: 48rpx;
|
||||
}
|
||||
|
||||
.users-icon {
|
||||
background-color: rgba(99, 102, 241, 0.1);
|
||||
}
|
||||
|
||||
.target-icon {
|
||||
background-color: rgba(168, 85, 247, 0.1);
|
||||
}
|
||||
|
||||
.chart-icon {
|
||||
background-color: rgba(34, 197, 94, 0.1);
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #1f2937;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.card-desc {
|
||||
font-size: 28rpx;
|
||||
color: #6b7280;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Modules Grid */
|
||||
.modules-grid {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 32rpx;
|
||||
}
|
||||
|
||||
.module-card {
|
||||
background: white;
|
||||
border-radius: 12rpx;
|
||||
padding: 32rpx;
|
||||
border-left: 8rpx solid;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.primary-border { border-left-color: #6366f1; }
|
||||
.secondary-border { border-left-color: #8b5cf6; }
|
||||
.accent-border { border-left-color: #22c55e; }
|
||||
.orange-border { border-left-color: #f97316; }
|
||||
.red-border { border-left-color: #ef4444; }
|
||||
|
||||
.module-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 24rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.module-icon {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.primary-bg { background-color: rgba(99, 102, 241, 0.1); }
|
||||
.secondary-bg { background-color: rgba(139, 92, 246, 0.1); }
|
||||
.accent-bg { background-color: rgba(34, 197, 94, 0.1); }
|
||||
.orange-bg { background-color: rgba(249, 115, 22, 0.1); }
|
||||
.red-bg { background-color: rgba(239, 68, 68, 0.1); }
|
||||
|
||||
.module-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.module-desc {
|
||||
font-size: 26rpx;
|
||||
color: #6b7280;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Scenarios Section */
|
||||
.scenarios-section {
|
||||
background-color: rgba(249, 250, 251, 0.5);
|
||||
}
|
||||
|
||||
.scenarios-grid {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 48rpx;
|
||||
}
|
||||
|
||||
.scenario-card {
|
||||
background: white;
|
||||
border-radius: 16rpx;
|
||||
padding: 48rpx 32rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.scenario-badge {
|
||||
display: inline-block;
|
||||
background-color: rgba(168, 85, 247, 0.1);
|
||||
color: #8b5cf6;
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 12rpx;
|
||||
font-size: 22rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.scenario-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
color: #1f2937;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.scenario-desc {
|
||||
font-size: 28rpx;
|
||||
color: #6b7280;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.scenario-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.tag {
|
||||
background-color: rgba(99, 102, 241, 0.1);
|
||||
color: #6366f1;
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 12rpx;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
/* CTA Section */
|
||||
.cta-section {
|
||||
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
|
||||
padding: 120rpx 32rpx;
|
||||
}
|
||||
|
||||
.cta-content {
|
||||
text-align: center;
|
||||
max-width: 1000rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
font-size: 64rpx;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.cta-desc {
|
||||
font-size: 32rpx;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
line-height: 1.6;
|
||||
margin-bottom: 64rpx;
|
||||
}
|
||||
|
||||
.cta-main-button {
|
||||
background: white;
|
||||
color: #6366f1;
|
||||
border: none;
|
||||
border-radius: 12rpx;
|
||||
padding: 24rpx 64rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 32rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.cta-secondary-button {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
color: white;
|
||||
border: 2rpx solid rgba(255, 255, 255, 0.3);
|
||||
border-radius: 12rpx;
|
||||
padding: 20rpx 48rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 64rpx;
|
||||
backdrop-filter: blur(10rpx);
|
||||
}
|
||||
|
||||
.cta-secondary-button .button-text {
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.cta-secondary-button .arrow {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 32rpx;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.stat-number {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.footer {
|
||||
padding: 64rpx 32rpx;
|
||||
background-color: #f9fafb;
|
||||
}
|
||||
|
||||
.footer-text {
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
/* Dialog Overlay */
|
||||
.dialog-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9998;
|
||||
padding: 32rpx;
|
||||
}
|
||||
|
||||
/* Dialog Styles */
|
||||
.dialog-content {
|
||||
background: white;
|
||||
border-radius: 16rpx;
|
||||
padding: 48rpx 32rpx;
|
||||
max-width: 600rpx;
|
||||
width: 100%;
|
||||
box-shadow: 0 16rpx 64rpx rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.dialog-header {
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.dialog-form {
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 28rpx;
|
||||
color: #374151;
|
||||
margin-bottom: 12rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
border: 2rpx solid #e5e7eb;
|
||||
border-radius: 8rpx;
|
||||
padding: 0 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #1f2937;
|
||||
background-color: #ffffff;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
border-color: #6366f1;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.dialog-title {
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
color: #1f2937;
|
||||
margin-bottom: 16rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dialog-desc {
|
||||
font-size: 28rpx;
|
||||
color: #6b7280;
|
||||
line-height: 1.6;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dialog-buttons {
|
||||
display: flex;
|
||||
gap: 24rpx;
|
||||
}
|
||||
|
||||
.dialog-button {
|
||||
flex: 1;
|
||||
padding: 24rpx;
|
||||
border-radius: 12rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.cancel-button {
|
||||
background: transparent;
|
||||
color: #6b7280;
|
||||
border: 2rpx solid #e5e7eb;
|
||||
}
|
||||
|
||||
.confirm-button {
|
||||
background: #6366f1;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Success Toast */
|
||||
.success-toast {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: rgba(34, 197, 94, 0.9);
|
||||
color: white;
|
||||
padding: 32rpx 48rpx;
|
||||
border-radius: 16rpx;
|
||||
z-index: 9999;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.success-text {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* 响应式适配 */
|
||||
@media (min-width: 768rpx) {
|
||||
.values-grid,
|
||||
.scenarios-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 48rpx;
|
||||
}
|
||||
|
||||
.modules-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 32rpx;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024rpx) {
|
||||
.values-grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
.modules-grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
167
pages/index/site.vue
Normal file
@@ -0,0 +1,167 @@
|
||||
<template>
|
||||
<view class="webview-container">
|
||||
<!-- 头部导航栏 -->
|
||||
<view class="header-nav" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||||
<view class="nav-content">
|
||||
<text class="nav-title">老游条电竞学院</text>
|
||||
<view class="nav-right"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- WebView 内容区域 -->
|
||||
<view class="webview-content" :style="{ marginTop: (statusBarHeight + 44) + 'px' }">
|
||||
<web-view :src="webUrl" @message="onMessage" @error="onError" @load="onLoad"></web-view>
|
||||
</view>
|
||||
|
||||
<!-- 加载提示 -->
|
||||
<view v-if="loading" class="loading-overlay">
|
||||
<view class="loading-content">
|
||||
<uni-icons type="spinner-cycle" size="30" color="#007AFF"></uni-icons>
|
||||
<text class="loading-text">加载中...</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
webUrl: 'https://www.lytiao.com/',
|
||||
loading: true,
|
||||
statusBarHeight: 0
|
||||
}
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
// 获取状态栏高度
|
||||
const systemInfo = uni.getSystemInfoSync()
|
||||
this.statusBarHeight = systemInfo.statusBarHeight || 0
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
})
|
||||
},
|
||||
|
||||
// WebView 加载完成
|
||||
onLoad(event) {
|
||||
console.log('WebView 加载完成:', event)
|
||||
this.loading = false
|
||||
},
|
||||
|
||||
// WebView 加载错误
|
||||
onError(event) {
|
||||
console.error('WebView 加载错误:', event)
|
||||
this.loading = false
|
||||
uni.showToast({
|
||||
title: '页面加载失败',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
},
|
||||
|
||||
// 接收 WebView 消息
|
||||
onMessage(event) {
|
||||
console.log('收到 WebView 消息:', event.detail.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.webview-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.header-nav {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
background-color: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(10px);
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.nav-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 44px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.nav-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.back-text {
|
||||
margin-left: 4px;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.nav-right {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.webview-content {
|
||||
width: 100%;
|
||||
height: calc(100vh - 44px);
|
||||
}
|
||||
|
||||
.loading-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.loading-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
margin-top: 12px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* 适配不同平台 */
|
||||
/* #ifdef MP-WEIXIN */
|
||||
.webview-content {
|
||||
height: calc(100vh - 88px);
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
/* #ifdef H5 */
|
||||
.header-nav {
|
||||
background-color: #fff;
|
||||
}
|
||||
/* #endif */
|
||||
</style>
|
||||
126
pages/login/login-page.scss
Normal file
@@ -0,0 +1,126 @@
|
||||
// 隐藏 edge 浏览器的密码查看按钮
|
||||
|
||||
/* #ifdef H5 */
|
||||
.input-box ::v-deep{
|
||||
.uni-input-input[type="password"] {
|
||||
&::-ms-reveal {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
.uni-content {
|
||||
padding: 0 60rpx;
|
||||
}
|
||||
|
||||
.login-logo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
@media screen and (min-width: 690px) {
|
||||
.uni-content {
|
||||
/* #ifndef H5 */
|
||||
padding: 0;
|
||||
max-width: 300px;
|
||||
margin-left: calc(50% - 200px);
|
||||
/* #endif */
|
||||
/* #ifdef H5 */
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
top: 100px;
|
||||
padding: 30px 40px 80px 40px;
|
||||
max-width: 450px;
|
||||
max-height: 450px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 0 20px #efefef;
|
||||
background-color: #FFF;
|
||||
/* #endif */
|
||||
}
|
||||
/* #ifdef H5 */
|
||||
.login-logo {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.login-logo image {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.register-back{
|
||||
display: none;
|
||||
}
|
||||
|
||||
uni-button{
|
||||
padding-bottom: 1px;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-content view {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
|
||||
|
||||
.title {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
padding: 18px 0;
|
||||
font-weight: 800;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.tip {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
color: #BDBDC0;
|
||||
font-size: 11px;
|
||||
margin: 6px 0;
|
||||
}
|
||||
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
// 解决小程序端开启虚拟节点virtualHost引起的 class = input-box丢失的问题 [详情参考](https://uniapp.dcloud.net.cn/matter.html#%E5%90%84%E5%AE%B6%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%AE%9E%E7%8E%B0%E6%9C%BA%E5%88%B6%E4%B8%8D%E5%90%8C-%E5%8F%AF%E8%83%BD%E5%AD%98%E5%9C%A8%E7%9A%84%E5%B9%B3%E5%8F%B0%E5%85%BC%E5%AE%B9%E9%97%AE%E9%A2%98)
|
||||
.uni-content ::v-deep .uni-easyinput__content,
|
||||
/* #endif */
|
||||
|
||||
.input-box {
|
||||
height: 44px;
|
||||
background-color: #F8F8F8 !important;
|
||||
border-radius: 0;
|
||||
font-size: 14px;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #04498c;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.uni-content ::v-deep .uni-forms-item__inner {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.uni-btn {
|
||||
text-align: center;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
margin: 15px 0 10px 0;
|
||||
color: #FFF !important;
|
||||
border-radius: 5px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.uni-body.uni_modules-uni-id-pages-pages-login-login-withoutpwd{
|
||||
height: auto !important;
|
||||
}
|
||||
197
pages/login/login.vue
Normal file
@@ -0,0 +1,197 @@
|
||||
<!-- 账号密码登录页 -->
|
||||
<template>
|
||||
<view class="uni-content">
|
||||
<view class="login-logo">
|
||||
<image :src="logo"></image>
|
||||
</view>
|
||||
<!-- 顶部文字 -->
|
||||
<text class="title title-box">账号密码登录</text>
|
||||
<uni-forms>
|
||||
<uni-forms-item name="username">
|
||||
<uni-easyinput :focus="focusUsername" @blur="focusUsername = false" class="input-box"
|
||||
:inputBorder="false" v-model="username" placeholder="请输入手机号/用户名/邮箱" />
|
||||
</uni-forms-item>
|
||||
<uni-forms-item name="password">
|
||||
<uni-easyinput :focus="focusPassword" @blur="focusPassword = false" class="input-box" clearable
|
||||
type="password" :inputBorder="false" v-model="password" placeholder="请输入密码" />
|
||||
</uni-forms-item>
|
||||
</uni-forms>
|
||||
<view class="private">
|
||||
<radio-group @click="radioChange">
|
||||
<radio :value="val" :checked="val===1">
|
||||
<view class="privateRadio">
|
||||
<view>阅读并同意存客宝</view>
|
||||
<view><navigator class="link" open-type="navigate" url="/pages/login/privatememo">隐私政策</navigator></view>
|
||||
<view>和</view>
|
||||
<view><navigator class="link" url="/pages/login/usermemo">用户服务协议</navigator></view>
|
||||
</view>
|
||||
</radio>
|
||||
</radio-group>
|
||||
</view>
|
||||
<button class="uni-btn" type="primary" @click="pwdLogin">登录</button>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
"redirectTo": "",
|
||||
"password": "",
|
||||
"username": "",
|
||||
"captcha": "",
|
||||
"needCaptcha": false,
|
||||
"focusUsername": false,
|
||||
"focusPassword": false,
|
||||
"logo": "/static/logo.png",
|
||||
"val": 0
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
// #ifdef H5
|
||||
document.onkeydown = event => {
|
||||
var e = event || window.event;
|
||||
if (e && e.keyCode == 13) { //回车键的键值为13
|
||||
this.pwdLogin()
|
||||
}
|
||||
};
|
||||
// #endif
|
||||
},
|
||||
onLoad(options) {
|
||||
|
||||
|
||||
// 获取传递过来的redirect参数
|
||||
this.redirectTo = options.redirect ? decodeURIComponent(options.redirect) : null;
|
||||
|
||||
if (!this.redirectTo.startsWith("/")) {
|
||||
this.redirectTo = "/" + this.redirectTo
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
radioChange(e){
|
||||
if(this.val==0){
|
||||
this.val=1;
|
||||
}else{
|
||||
this.val=0;
|
||||
}
|
||||
uni.setStorageSync('agreePrivate', this.val);
|
||||
},
|
||||
/**
|
||||
* 密码登录
|
||||
*/
|
||||
pwdLogin() {
|
||||
let agreePrivate=uni.getStorageSync('agreePrivate');
|
||||
if(agreePrivate==0){
|
||||
uni.showToast({
|
||||
title: '还未阅读并同意存客宝协议',
|
||||
icon: 'none',
|
||||
duration: 1000
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!this.password.length) {
|
||||
this.focusPassword = true
|
||||
return uni.showToast({
|
||||
title: '请输入密码',
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.username.length) {
|
||||
this.focusUsername = true
|
||||
return uni.showToast({
|
||||
title: '请输入手机号/用户名/邮箱',
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
});
|
||||
}
|
||||
|
||||
let data = {
|
||||
"password": this.password,
|
||||
"username": this.username
|
||||
}
|
||||
|
||||
let that = this
|
||||
uni.request({
|
||||
method: 'POST',
|
||||
header: {
|
||||
'content-type': 'application/x-www-form-urlencoded', //自定义请求头信息
|
||||
},
|
||||
url: this.$config.apiUrl + '/v1/frontend/business/user/login',
|
||||
data: data,
|
||||
success: (res) => {
|
||||
if (res.data.code == 10000) {
|
||||
try {
|
||||
uni.setStorageSync('token', res.data.data.token);
|
||||
console.log(that.redirectTo)
|
||||
if (!that.redirectTo || that.redirectTo.includes('pages/ucenter/ucenter')) {
|
||||
uni.redirectTo({
|
||||
url: "/pages/ucenter/ucenter"
|
||||
})
|
||||
} else {
|
||||
uni.redirectTo({
|
||||
url: that.redirectTo
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none',
|
||||
duration: 3000
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/pages/login/login-page.scss";
|
||||
|
||||
@media screen and (min-width: 690px) {
|
||||
.uni-content {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.forget {
|
||||
font-size: 12px;
|
||||
color: #8a8f8b;
|
||||
}
|
||||
|
||||
.private{
|
||||
font-size: 12px;
|
||||
.link{
|
||||
color: blue;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.privateRadio{
|
||||
display: flex;
|
||||
justify-content: space-between; /* 水平分布 */
|
||||
align-items: center; /* 垂直居中 */
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
|
||||
.link-box {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.link {
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
134
pages/poster/index.vue
Normal file
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<button style="padding: 0;margin-left: 0; text-align: left;" class="nullBtn" v-if='taskid == 487'>
|
||||
<image class="posterImg" src="https://ckbapi.quwanzhi.com/upload/img/ckb.png" mode="widthFix"></image>
|
||||
</button>
|
||||
<button style="padding: 0;margin-left: 0; text-align: left;" class="nullBtn" open-type="getPhoneNumber" v-else
|
||||
@getphonenumber="getPhoneNumber">
|
||||
<image class="posterImg" :src="poster.sUrl" mode="widthFix"></image>
|
||||
</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
request
|
||||
} from '@/utils/request';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
taskid: '',
|
||||
token: "test",
|
||||
task: null,
|
||||
poster: null
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
let scene = options.scene;
|
||||
let taskId = options.id;
|
||||
|
||||
if (scene != undefined) {
|
||||
this.taskid = scene;
|
||||
} else if (taskId != undefined) {
|
||||
this.taskid = taskId;
|
||||
} else {
|
||||
this.taskid = 487;
|
||||
}
|
||||
|
||||
this.getPosterData()
|
||||
},
|
||||
methods: {
|
||||
getPosterData() {
|
||||
let that = this;
|
||||
uni.request({
|
||||
method: 'POST',
|
||||
header: {
|
||||
'content-type': 'application/x-www-form-urlencoded', //自定义请求头信息
|
||||
'token': that.token
|
||||
},
|
||||
url: that.$config.apiUrl2 + '/v1/frontend/business/poster/getone',
|
||||
data: {
|
||||
oldId: that.taskid,
|
||||
},
|
||||
success: (res) => {
|
||||
if (res.data.code == 200) {
|
||||
that.poster = res.data.data.poster
|
||||
that.task = res.data.data.task
|
||||
that.taskid = res.data.data.task.id
|
||||
//修改标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: ""
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
onShareAppMessage() {
|
||||
return {
|
||||
title: '',
|
||||
path: '/pages/poster/index2?id=' + this.taskid,
|
||||
imageUrl: poster.sUrl // 可以省略不写,这样会默认截图当前页面作为分享图片
|
||||
};
|
||||
},
|
||||
// 获取用户手机号
|
||||
getPhoneNumber(res) {
|
||||
let that = this;
|
||||
if (res.detail.errMsg == "getPhoneNumber:ok") {
|
||||
uni.showLoading({
|
||||
title: '请求中...',
|
||||
mask: true
|
||||
})
|
||||
uni.request({
|
||||
method: 'POST',
|
||||
header: {
|
||||
'content-type': 'application/x-www-form-urlencoded', //自定义请求头信息
|
||||
'token': that.token
|
||||
},
|
||||
url: that.$config.apiUrl2 + '/v1/frontend/business/poster/decryptphone',
|
||||
data: {
|
||||
id: that.taskid,
|
||||
code: res.detail.code
|
||||
},
|
||||
success: (res) => {
|
||||
uni.hideLoading();
|
||||
if (res.data.code == 200) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: that.task.sTip,
|
||||
success: function(res) {
|
||||
console.log(res)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.page {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.posterImg {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
193
pages/poster/index2.vue
Normal file
@@ -0,0 +1,193 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<button style="padding: 0;margin-left: 0; text-align: left;" class="nullBtn" v-if='taskid == 487'>
|
||||
<image class="posterImg" src="https://ckbapi.quwanzhi.com/upload/img/ckb.png" mode="widthFix"></image>
|
||||
</button>
|
||||
<button style="padding: 0;margin-left: 0; text-align: left;" class="nullBtn" open-type="getPhoneNumber" v-else
|
||||
@getphonenumber="getPhoneNumber">
|
||||
<image class="posterImg" :src="poster.sUrl" mode="widthFix"></image>
|
||||
</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
request
|
||||
} from '@/utils/request';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
taskid: '',
|
||||
token: "test",
|
||||
task: null,
|
||||
poster: null,
|
||||
cid: '',
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
let scene = options.scene;
|
||||
let taskId = options.id;
|
||||
let cid = options.cid;
|
||||
|
||||
console.log('页面参数:', { scene, taskId, cid });
|
||||
|
||||
// 小程序端解析 scene 参数
|
||||
// #ifdef MP-WEIXIN
|
||||
if (scene != undefined) {
|
||||
// 先对 scene 进行 URL 解码(处理 %2C 等编码字符)
|
||||
try {
|
||||
scene = decodeURIComponent(scene);
|
||||
} catch (e) {
|
||||
console.warn('scene 解码失败,使用原始值:', e);
|
||||
}
|
||||
|
||||
// 如果 scene 包含逗号,分割成 [taskId, channelId]
|
||||
if (scene.includes(',')) {
|
||||
const parts = scene.split(',');
|
||||
this.taskid = parts[0] || '';
|
||||
this.cid = parts[1] || '0';
|
||||
} else {
|
||||
// 如果不包含逗号,只有 taskId,channelId 为 0
|
||||
this.taskid = scene;
|
||||
this.cid = '0';
|
||||
}
|
||||
} else if (taskId != undefined) {
|
||||
// 兼容旧参数:使用 options.id
|
||||
this.taskid = taskId;
|
||||
this.cid = cid || '0';
|
||||
} else {
|
||||
// 默认值
|
||||
this.taskid = 487;
|
||||
this.cid = '0';
|
||||
}
|
||||
// #endif
|
||||
|
||||
// H5 端兼容旧参数
|
||||
// #ifdef H5
|
||||
if (taskId != undefined) {
|
||||
this.taskid = taskId;
|
||||
this.cid = cid || '0';
|
||||
} else if (scene != undefined) {
|
||||
// H5 也可能有 scene 参数(从分享链接等)
|
||||
// 先对 scene 进行 URL 解码
|
||||
try {
|
||||
scene = decodeURIComponent(scene);
|
||||
} catch (e) {
|
||||
console.warn('scene 解码失败,使用原始值:', e);
|
||||
}
|
||||
|
||||
if (scene.includes(',')) {
|
||||
const parts = scene.split(',');
|
||||
this.taskid = parts[0] || '';
|
||||
this.cid = parts[1] || '0';
|
||||
} else {
|
||||
this.taskid = scene;
|
||||
this.cid = '0';
|
||||
}
|
||||
} else {
|
||||
this.taskid = 487;
|
||||
this.cid = '0';
|
||||
}
|
||||
// #endif
|
||||
|
||||
console.log('解析结果:', { taskid: this.taskid, cid: this.cid });
|
||||
|
||||
this.getPosterData()
|
||||
},
|
||||
methods: {
|
||||
getPosterData() {
|
||||
let that = this;
|
||||
uni.request({
|
||||
method: 'POST',
|
||||
header: {
|
||||
'content-type': 'application/x-www-form-urlencoded', //自定义请求头信息
|
||||
'token': that.token
|
||||
},
|
||||
url: that.$config.apiUrl2 + '/v1/frontend/business/poster/getone',
|
||||
data: {
|
||||
id: that.taskid,
|
||||
},
|
||||
success: (res) => {
|
||||
if (res.data.code == 200) {
|
||||
|
||||
that.poster = res.data.data.poster
|
||||
that.task = res.data.data.task
|
||||
|
||||
//修改标题
|
||||
uni.setNavigationBarTitle({
|
||||
title: ""
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
onShareAppMessage() {
|
||||
return {
|
||||
title: '',
|
||||
path: '/pages/poster/index2?id=' + this.taskid,
|
||||
imageUrl: poster.sUrl // 可以省略不写,这样会默认截图当前页面作为分享图片
|
||||
};
|
||||
},
|
||||
// 获取用户手机号
|
||||
getPhoneNumber(res) {
|
||||
let that = this;
|
||||
if (res.detail.errMsg == "getPhoneNumber:ok") {
|
||||
uni.showLoading({
|
||||
title: '请求中...',
|
||||
mask: true
|
||||
})
|
||||
uni.request({
|
||||
method: 'POST',
|
||||
header: {
|
||||
'content-type': 'application/x-www-form-urlencoded', //自定义请求头信息
|
||||
'token': that.token
|
||||
},
|
||||
url: that.$config.apiUrl2 + '/v1/frontend/business/poster/decryptphone',
|
||||
data: {
|
||||
id: that.taskid,
|
||||
cid: that.cid,
|
||||
code: res.detail.code
|
||||
},
|
||||
success: (res) => {
|
||||
uni.hideLoading();
|
||||
if (res.data.code == 200) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: that.task.sTip,
|
||||
success: function(res) {
|
||||
console.log(res)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.page {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.posterImg {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
102
pages/ucenter/ucenter.vue
Normal file
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<view class="center">
|
||||
<view class="userInfo" @click.capture="toUserInfo">
|
||||
|
||||
<view class="defaultAvatarUrl">
|
||||
<uni-icons color="#ffffff" size="50" type="person-filled" />
|
||||
</view>
|
||||
|
||||
<view class="logo-title">
|
||||
<text class="uer-name">{{userInfo.sName}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<u-cell-group :customStyle="style">
|
||||
<u-cell title="我的表单" :isLink="true" url="/pages/form/list"></u-cell>
|
||||
<!-- <u-cell title="我的收益" :isLink="true"></u-cell> -->
|
||||
</u-cell-group>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
request
|
||||
} from '@/utils/request';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
userInfo: {},
|
||||
style: {
|
||||
"background-color": "#f9f9f9",
|
||||
}
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
request({
|
||||
url: '/v1/backend/system/sysuser/profile/info',
|
||||
data: {},
|
||||
// ...
|
||||
}).then((response) => {
|
||||
this.userInfo = response.data.data
|
||||
}).catch((error) => {
|
||||
// 处理错误
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
view {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
page {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.center {
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.userInfo {
|
||||
// padding: 20rpx;
|
||||
padding-top: 60px;
|
||||
background-image: url(@/static/headers.png);
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.defaultAvatarUrl {
|
||||
width: 150rpx;
|
||||
height: 150rpx;
|
||||
background-color: #007aff;
|
||||
border-radius: 100%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uer-name {
|
||||
height: 100rpx;
|
||||
line-height: 100rpx;
|
||||
font-size: 38rpx;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.center-list {
|
||||
margin-bottom: 30rpx;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.center-list-cell {
|
||||
width: 750rpx;
|
||||
background-color: #007AFF;
|
||||
height: 40rpx;
|
||||
}
|
||||
</style>
|
||||
28
project.config.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"appid": "wx3724765328cccf03",
|
||||
"compileType": "miniprogram",
|
||||
"libVersion": "3.8.10",
|
||||
"packOptions": {
|
||||
"ignore": [],
|
||||
"include": []
|
||||
},
|
||||
"setting": {
|
||||
"coverView": true,
|
||||
"es6": true,
|
||||
"postcss": true,
|
||||
"minified": true,
|
||||
"enhance": true,
|
||||
"showShadowRootInWxmlPanel": true,
|
||||
"packNpmRelationList": [],
|
||||
"babelSetting": {
|
||||
"ignore": [],
|
||||
"disablePlugins": [],
|
||||
"outputPath": ""
|
||||
}
|
||||
},
|
||||
"condition": {},
|
||||
"editorSetting": {
|
||||
"tabIndent": "insertSpaces",
|
||||
"tabSize": 2
|
||||
}
|
||||
}
|
||||
7
project.private.config.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
|
||||
"projectname": "ckb_mini",
|
||||
"setting": {
|
||||
"compileHotReLoad": true
|
||||
}
|
||||
}
|
||||
BIN
static/c1.png
Normal file
|
After Width: | Height: | Size: 401 B |
BIN
static/c2.png
Normal file
|
After Width: | Height: | Size: 470 B |
BIN
static/c3.png
Normal file
|
After Width: | Height: | Size: 511 B |
BIN
static/c4.png
Normal file
|
After Width: | Height: | Size: 476 B |
BIN
static/c5.png
Normal file
|
After Width: | Height: | Size: 472 B |
BIN
static/c6.png
Normal file
|
After Width: | Height: | Size: 545 B |
BIN
static/c7.png
Normal file
|
After Width: | Height: | Size: 365 B |
BIN
static/c8.png
Normal file
|
After Width: | Height: | Size: 587 B |
BIN
static/c9.png
Normal file
|
After Width: | Height: | Size: 565 B |
20
static/customicons.css
Normal file
@@ -0,0 +1,20 @@
|
||||
@font-face {
|
||||
font-family: "customicons"; /* Project id 2878519 */
|
||||
src:url('/static/customicons.ttf') format('truetype');
|
||||
}
|
||||
|
||||
.customicons {
|
||||
font-family: "customicons" !important;
|
||||
}
|
||||
|
||||
.youxi:before {
|
||||
content: "\e60e";
|
||||
}
|
||||
|
||||
.wenjian:before {
|
||||
content: "\e60f";
|
||||
}
|
||||
|
||||
.zhuanfa:before {
|
||||
content: "\e610";
|
||||
}
|
||||
BIN
static/customicons.ttf
Normal file
BIN
static/headers.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
static/logo.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
static/tabbar/grid.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
static/tabbar/grid_active.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
static/tabbar/list.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
static/tabbar/list_active.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
static/tabbar/me.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
static/tabbar/me_active.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
static/uni.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
4
uni.scss
Normal file
@@ -0,0 +1,4 @@
|
||||
@import '@/uni_modules/uni-scss/variables.scss';
|
||||
|
||||
/* uni.scss */
|
||||
@import 'uview-ui/theme.scss';
|
||||
50
utils/request.js
Normal file
@@ -0,0 +1,50 @@
|
||||
// utils/request.js
|
||||
import config from '@/config';
|
||||
|
||||
export function request(options) {
|
||||
// 在请求发送前做一些处理,如添加 token
|
||||
const token = uni.getStorageSync('token');
|
||||
|
||||
options.header = options.header || {};
|
||||
options.header['token'] = token;
|
||||
options.header['content-type'] = 'application/x-www-form-urlencoded';
|
||||
|
||||
options.method = options.method || "POST";
|
||||
options.url = config.apiUrl + options.url;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
...options,
|
||||
success: (response) => {
|
||||
if (response.data.code == 10030) {
|
||||
// 没有登录,跳转到登录页,并带上当前页面的URL
|
||||
redirectToLoginWithRedirect();
|
||||
} else {
|
||||
resolve(response);
|
||||
}
|
||||
},
|
||||
fail: (error) => {
|
||||
reject(error);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function redirectToLoginWithRedirect() {
|
||||
let currentRoute = '';
|
||||
// 获取当前页面路径和参数
|
||||
const pages = getCurrentPages();
|
||||
if (pages.length) {
|
||||
const currentPage = pages[pages.length - 1];
|
||||
currentRoute = currentPage.route;
|
||||
const query = Object.keys(currentPage.options)
|
||||
.map(key => `${key}=${currentPage.options[key]}`)
|
||||
.join('&');
|
||||
if (query) currentRoute += '?' + query;
|
||||
}
|
||||
|
||||
// 重定向到登录页面
|
||||
uni.redirectTo({
|
||||
url: `/pages/login/login?redirect=${encodeURIComponent(currentRoute)}`,
|
||||
});
|
||||
}
|
||||