小程序提交
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)}`,
|
||||||
|
});
|
||||||
|
}
|
||||||