wee
This commit is contained in:
parent
1fb102451e
commit
7e88dbb16c
1
@babel/runtime/helpers/Arrayincludes.js
Normal file
1
@babel/runtime/helpers/Arrayincludes.js
Normal file
@ -0,0 +1 @@
|
||||
Array.prototype.includes||Object.defineProperty(Array.prototype,"includes",{value:function(r,e){if(null==this)throw new TypeError('"this" is null or not defined');var t=Object(this),n=t.length>>>0;if(0==n)return!1;for(var i,o,a=0|e,u=Math.max(0<=a?a:n-Math.abs(a),0);u<n;){if((i=t[u])===(o=r)||"number"==typeof i&&"number"==typeof o&&isNaN(i)&&isNaN(o))return!0;u++}return!1}});
|
||||
1
@babel/runtime/helpers/Objectentries.js
Normal file
1
@babel/runtime/helpers/Objectentries.js
Normal file
@ -0,0 +1 @@
|
||||
Object.entries||(Object.entries=function(e){for(var r=Object.keys(e),t=r.length,n=new Array(t);t--;)n[t]=[r[t],e[r[t]]];return n});
|
||||
1
@babel/runtime/helpers/arrayLikeToArray.js
Normal file
1
@babel/runtime/helpers/arrayLikeToArray.js
Normal file
@ -0,0 +1 @@
|
||||
function _arrayLikeToArray(r,a){(null==a||a>r.length)&&(a=r.length);for(var e=0,n=new Array(a);e<a;e++)n[e]=r[e];return n}module.exports=_arrayLikeToArray;
|
||||
1
@babel/runtime/helpers/arrayWithHoles.js
Normal file
1
@babel/runtime/helpers/arrayWithHoles.js
Normal file
@ -0,0 +1 @@
|
||||
function _arrayWithHoles(r){if(Array.isArray(r))return r}module.exports=_arrayWithHoles;
|
||||
1
@babel/runtime/helpers/arrayWithoutHoles.js
Normal file
1
@babel/runtime/helpers/arrayWithoutHoles.js
Normal file
@ -0,0 +1 @@
|
||||
var arrayLikeToArray=require("./arrayLikeToArray");function _arrayWithoutHoles(r){if(Array.isArray(r))return arrayLikeToArray(r)}module.exports=_arrayWithoutHoles;
|
||||
1
@babel/runtime/helpers/assertThisInitialized.js
Normal file
1
@babel/runtime/helpers/assertThisInitialized.js
Normal file
@ -0,0 +1 @@
|
||||
function _assertThisInitialized(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}module.exports=_assertThisInitialized;
|
||||
1
@babel/runtime/helpers/classCallCheck.js
Normal file
1
@babel/runtime/helpers/classCallCheck.js
Normal file
@ -0,0 +1 @@
|
||||
function _classCallCheck(a,l){if(!(a instanceof l))throw new TypeError("Cannot call a class as a function")}module.exports=_classCallCheck;
|
||||
1
@babel/runtime/helpers/createClass.js
Normal file
1
@babel/runtime/helpers/createClass.js
Normal file
@ -0,0 +1 @@
|
||||
var toPropertyKey=require("./toPropertyKey");function _defineProperties(e,r){for(var t=0;t<r.length;t++){var o=r[t];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,toPropertyKey(o.key),o)}}function _createClass(e,r,t){return r&&_defineProperties(e.prototype,r),t&&_defineProperties(e,t),Object.defineProperty(e,"prototype",{writable:!1}),e}module.exports=_createClass;
|
||||
1
@babel/runtime/helpers/createForOfIteratorHelper.js
Normal file
1
@babel/runtime/helpers/createForOfIteratorHelper.js
Normal file
@ -0,0 +1 @@
|
||||
var unsupportedIterableToArray=require("./unsupportedIterableToArray");function _createForOfIteratorHelper(r,e){var t="undefined"!=typeof Symbol&&r[Symbol.iterator]||r["@@iterator"];if(!t){if(Array.isArray(r)||(t=unsupportedIterableToArray(r))||e&&r&&"number"==typeof r.length){t&&(r=t);var n=0,o=function(){};return{s:o,n:function(){return n>=r.length?{done:!0}:{done:!1,value:r[n++]}},e:function(r){throw r},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,u=!0,i=!1;return{s:function(){t=t.call(r)},n:function(){var r=t.next();return u=r.done,r},e:function(r){i=!0,a=r},f:function(){try{u||null==t.return||t.return()}finally{if(i)throw a}}}}module.exports=_createForOfIteratorHelper;
|
||||
1
@babel/runtime/helpers/createSuper.js
Normal file
1
@babel/runtime/helpers/createSuper.js
Normal file
@ -0,0 +1 @@
|
||||
var getPrototypeOf=require("./getPrototypeOf"),isNativeReflectConstruct=require("./isNativeReflectConstruct"),possibleConstructorReturn=require("./possibleConstructorReturn");function _createSuper(t){var e=isNativeReflectConstruct();return function(){var r,o=getPrototypeOf(t);if(e){var s=getPrototypeOf(this).constructor;r=Reflect.construct(o,arguments,s)}else r=o.apply(this,arguments);return possibleConstructorReturn(this,r)}}module.exports=_createSuper;
|
||||
1
@babel/runtime/helpers/defineProperty.js
Normal file
1
@babel/runtime/helpers/defineProperty.js
Normal file
@ -0,0 +1 @@
|
||||
var toPropertyKey=require("./toPropertyKey");function _defineProperty(e,r,t){return(r=toPropertyKey(r))in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}module.exports=_defineProperty;
|
||||
1
@babel/runtime/helpers/getPrototypeOf.js
Normal file
1
@babel/runtime/helpers/getPrototypeOf.js
Normal file
@ -0,0 +1 @@
|
||||
function _getPrototypeOf(t){return module.exports=_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)},_getPrototypeOf(t)}module.exports=_getPrototypeOf;
|
||||
1
@babel/runtime/helpers/inherits.js
Normal file
1
@babel/runtime/helpers/inherits.js
Normal file
@ -0,0 +1 @@
|
||||
var setPrototypeOf=require("./setPrototypeOf");function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&setPrototypeOf(e,t)}module.exports=_inherits;
|
||||
1
@babel/runtime/helpers/isNativeReflectConstruct.js
Normal file
1
@babel/runtime/helpers/isNativeReflectConstruct.js
Normal file
@ -0,0 +1 @@
|
||||
function _isNativeReflectConstruct(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(t){return!1}}module.exports=_isNativeReflectConstruct;
|
||||
1
@babel/runtime/helpers/iterableToArray.js
Normal file
1
@babel/runtime/helpers/iterableToArray.js
Normal file
@ -0,0 +1 @@
|
||||
function _iterableToArray(r){if("undefined"!=typeof Symbol&&null!=r[Symbol.iterator]||null!=r["@@iterator"])return Array.from(r)}module.exports=_iterableToArray;
|
||||
1
@babel/runtime/helpers/iterableToArrayLimit.js
Normal file
1
@babel/runtime/helpers/iterableToArrayLimit.js
Normal file
@ -0,0 +1 @@
|
||||
function _iterableToArrayLimit(r,e){var l=null==r?null:"undefined"!=typeof Symbol&&r[Symbol.iterator]||r["@@iterator"];if(null!=l){var t,n,i,a,u=[],o=!0,f=!1;try{if(i=(l=l.call(r)).next,0===e){if(Object(l)!==l)return;o=!1}else for(;!(o=(t=i.call(l)).done)&&(u.push(t.value),u.length!==e);o=!0);}catch(r){f=!0,n=r}finally{try{if(!o&&null!=l.return&&(a=l.return(),Object(a)!==a))return}finally{if(f)throw n}}return u}}module.exports=_iterableToArrayLimit;
|
||||
1
@babel/runtime/helpers/nonIterableRest.js
Normal file
1
@babel/runtime/helpers/nonIterableRest.js
Normal file
@ -0,0 +1 @@
|
||||
function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}module.exports=_nonIterableRest;
|
||||
1
@babel/runtime/helpers/nonIterableSpread.js
Normal file
1
@babel/runtime/helpers/nonIterableSpread.js
Normal file
@ -0,0 +1 @@
|
||||
function _nonIterableSpread(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}module.exports=_nonIterableSpread;
|
||||
1
@babel/runtime/helpers/possibleConstructorReturn.js
Normal file
1
@babel/runtime/helpers/possibleConstructorReturn.js
Normal file
@ -0,0 +1 @@
|
||||
var _typeof=require("./typeof"),assertThisInitialized=require("./assertThisInitialized");function _possibleConstructorReturn(e,r){if(r&&("object"===_typeof(r)||"function"==typeof r))return r;if(void 0!==r)throw new TypeError("Derived constructors may only return object or undefined");return assertThisInitialized(e)}module.exports=_possibleConstructorReturn;
|
||||
1
@babel/runtime/helpers/setPrototypeOf.js
Normal file
1
@babel/runtime/helpers/setPrototypeOf.js
Normal file
@ -0,0 +1 @@
|
||||
function _setPrototypeOf(t,e){return module.exports=_setPrototypeOf=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t},_setPrototypeOf(t,e)}module.exports=_setPrototypeOf;
|
||||
1
@babel/runtime/helpers/slicedToArray.js
Normal file
1
@babel/runtime/helpers/slicedToArray.js
Normal file
@ -0,0 +1 @@
|
||||
var arrayWithHoles=require("./arrayWithHoles"),iterableToArrayLimit=require("./iterableToArrayLimit"),unsupportedIterableToArray=require("./unsupportedIterableToArray"),nonIterableRest=require("./nonIterableRest");function _slicedToArray(r,e){return arrayWithHoles(r)||iterableToArrayLimit(r,e)||unsupportedIterableToArray(r,e)||nonIterableRest()}module.exports=_slicedToArray;
|
||||
1
@babel/runtime/helpers/toConsumableArray.js
Normal file
1
@babel/runtime/helpers/toConsumableArray.js
Normal file
@ -0,0 +1 @@
|
||||
var arrayWithoutHoles=require("./arrayWithoutHoles"),iterableToArray=require("./iterableToArray"),unsupportedIterableToArray=require("./unsupportedIterableToArray"),nonIterableSpread=require("./nonIterableSpread");function _toConsumableArray(r){return arrayWithoutHoles(r)||iterableToArray(r)||unsupportedIterableToArray(r)||nonIterableSpread()}module.exports=_toConsumableArray;
|
||||
1
@babel/runtime/helpers/toPrimitive.js
Normal file
1
@babel/runtime/helpers/toPrimitive.js
Normal file
@ -0,0 +1 @@
|
||||
var _typeof=require("./typeof");function _toPrimitive(r,t){if("object"!==_typeof(r)||null===r)return r;var e=r[Symbol.toPrimitive];if(void 0!==e){var i=e.call(r,t||"default");if("object"!==_typeof(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(r)}module.exports=_toPrimitive;
|
||||
1
@babel/runtime/helpers/toPropertyKey.js
Normal file
1
@babel/runtime/helpers/toPropertyKey.js
Normal file
@ -0,0 +1 @@
|
||||
var _typeof=require("./typeof"),toPrimitive=require("./toPrimitive");function _toPropertyKey(r){var t=toPrimitive(r,"string");return"symbol"===_typeof(t)?t:String(t)}module.exports=_toPropertyKey;
|
||||
1
@babel/runtime/helpers/typeof.js
Normal file
1
@babel/runtime/helpers/typeof.js
Normal file
@ -0,0 +1 @@
|
||||
function _typeof(o){return module.exports=_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(o){return typeof o}:function(o){return o&&"function"==typeof Symbol&&o.constructor===Symbol&&o!==Symbol.prototype?"symbol":typeof o},_typeof(o)}module.exports=_typeof;
|
||||
1
@babel/runtime/helpers/unsupportedIterableToArray.js
Normal file
1
@babel/runtime/helpers/unsupportedIterableToArray.js
Normal file
@ -0,0 +1 @@
|
||||
var arrayLikeToArray=require("./arrayLikeToArray");function _unsupportedIterableToArray(r,e){if(r){if("string"==typeof r)return arrayLikeToArray(r,e);var t=Object.prototype.toString.call(r).slice(8,-1);return"Object"===t&&r.constructor&&(t=r.constructor.name),"Map"===t||"Set"===t?Array.from(r):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?arrayLikeToArray(r,e):void 0}}module.exports=_unsupportedIterableToArray;
|
||||
44
api/request.js
Normal file
44
api/request.js
Normal file
@ -0,0 +1,44 @@
|
||||
const baseUrl = 'https://mini-chat.1024tool.vip/';
|
||||
|
||||
function request(url, method = 'GET', data = {}) {
|
||||
|
||||
const header = {
|
||||
'content-type': 'application/json',
|
||||
// 有其他content-type需求加点逻辑判断处理即可
|
||||
};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.request({
|
||||
url: baseUrl + url,
|
||||
method,
|
||||
data,
|
||||
dataType: 'json', // 微信官方文档中介绍会对数据进行一次JSON.parse
|
||||
header,
|
||||
success(res) {
|
||||
if (res.data.code) {
|
||||
if (res.data.code == 10103) {
|
||||
|
||||
reject(res.data);
|
||||
return;
|
||||
}
|
||||
wx.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none'
|
||||
});
|
||||
reject(res.data);
|
||||
} else {
|
||||
resolve(res.data);
|
||||
}
|
||||
|
||||
},
|
||||
fail(err) {
|
||||
console.log(err)
|
||||
// 断网、服务器挂了都会fail回调,直接reject即可
|
||||
reject(err);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 导出请求和服务地址(CommonJS 兼容)
|
||||
module.exports = request;
|
||||
105
api/upload.js
Normal file
105
api/upload.js
Normal file
@ -0,0 +1,105 @@
|
||||
import request from './request'
|
||||
|
||||
const uploadFile = async (file, callback) => {
|
||||
|
||||
|
||||
const policyData = await request('admin/policy_token', 'post')
|
||||
const res = JSON.parse(policyData.token)
|
||||
|
||||
const fileName = file.tempFilePath.split('/').pop(); // hello.png
|
||||
// const fileName = fileNameWithExt.split('.').slice(0, -1).join('.'); // hello
|
||||
|
||||
const formData = {
|
||||
key: 'upload_file/' + fileName, //上传文件名称
|
||||
policy: res.policy, //表单域
|
||||
'x-oss-signature-version': res.x_oss_signature_version, //指定签名的版本和算法
|
||||
'x-oss-credential': res.x_oss_credential, //指明派生密钥的参数集
|
||||
'x-oss-date': res.x_oss_date, //请求的时间
|
||||
'x-oss-signature': res.signature, //签名认证描述信息
|
||||
'x-oss-security-token': res.security_token, //安全令牌
|
||||
success_action_status: "200" //上传成功后响应状态码
|
||||
};
|
||||
// console.log(filePath)
|
||||
// return
|
||||
// 发送请求上传文件
|
||||
wx.uploadFile({
|
||||
url: 'https://image-fudan.oss-cn-beijing.aliyuncs.com/',
|
||||
method: 'put',
|
||||
filePath: file.tempFilePath,
|
||||
name: 'file', //固定值为file
|
||||
formData: formData,
|
||||
success(res) {
|
||||
console.log('上传响应:', res);
|
||||
if (res.statusCode === 200) {
|
||||
callback(null, 'https://image-fudan.oss-cn-beijing.aliyuncs.com/upload_file/' + fileName); // 上传成功
|
||||
} else {
|
||||
console.error('上传失败,状态码:', res.statusCode);
|
||||
console.error('失败响应:', res);
|
||||
callback(res); // 上传失败,返回响应
|
||||
}
|
||||
},
|
||||
fail(err) {
|
||||
console.error('上传失败:', err); // 输出错误信息
|
||||
wx.showToast({
|
||||
title: '上传失败,请重试!',
|
||||
icon: 'none'
|
||||
});
|
||||
callback(err); // 调用回调处理错误
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
const uploadFileToOSS = () => {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
wx.chooseMedia({
|
||||
count: 1, // 选择一个文件
|
||||
mediaType: ['image'],
|
||||
sourceType: ['album', 'camera'],
|
||||
// type: 'all', // 支持所有类型的文件
|
||||
success: (res) => {
|
||||
wx.showToast({
|
||||
title: '文件上传中,请稍等!',
|
||||
icon: 'none'
|
||||
});
|
||||
console.log('选择的文件:', res.tempFiles); // 输出选择的文件信息
|
||||
if (res.tempFiles.length > 0) {
|
||||
const tempFilePath = res.tempFiles[0];
|
||||
console.log('选择的文件路径:', tempFilePath); // 输出文件路径
|
||||
uploadFile(tempFilePath, (error, data) => {
|
||||
if (error) {
|
||||
wx.showToast({
|
||||
title: '上传失败!',
|
||||
icon: 'none'
|
||||
});
|
||||
console.error('上传失败:', error); // 输出具体的错误信息
|
||||
reject(error)
|
||||
} else {
|
||||
resolve(data)
|
||||
console.log('上传成功:', data); // 输出上传成功后的数据
|
||||
}
|
||||
});
|
||||
} else {
|
||||
wx.showToast({
|
||||
title: '未选择文件!',
|
||||
icon: 'none'
|
||||
});
|
||||
reject('未选择文件!')
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
wx.showToast({
|
||||
title: '选择文件失败!',
|
||||
icon: 'none'
|
||||
});
|
||||
console.error('选择文件失败:', err); // 输出选择文件的错误信息
|
||||
reject('选择文件失败!')
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export default uploadFileToOSS;
|
||||
22
app.js
Normal file
22
app.js
Normal file
@ -0,0 +1,22 @@
|
||||
Object.defineProperty(exports, Symbol.toStringTag, {
|
||||
value: "Module"
|
||||
});var common_vendor = require("./common/vendor.js");if (!Math) {
|
||||
"./pages/index/index.js";
|
||||
"./pages/index/detail.js";
|
||||
"./pages/ming/index.js";
|
||||
}var _sfc_main = {
|
||||
onLaunch: function onLaunch() {
|
||||
common_vendor.index.__f__("log", "at App.vue:4", "App Launch");
|
||||
},
|
||||
onShow: function onShow() {
|
||||
common_vendor.index.__f__("log", "at App.vue:7", "App Show");
|
||||
},
|
||||
onHide: function onHide() {
|
||||
common_vendor.index.__f__("log", "at App.vue:10", "App Hide");
|
||||
}
|
||||
};function createApp() {
|
||||
var app = common_vendor.createSSRApp(_sfc_main);
|
||||
return {
|
||||
app: app
|
||||
};
|
||||
}createApp().app.mount("#app");exports.createApp = createApp;
|
||||
15
app.json
Normal file
15
app.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"componentFramework": "exparser",
|
||||
"window": {
|
||||
"navigationBarTextStyle": "black",
|
||||
"navigationBarTitleText": "舞蹈",
|
||||
"navigationBarBackgroundColor": "#F8F8F8",
|
||||
"backgroundColor": "#F8F8F8"
|
||||
},
|
||||
"pages": [
|
||||
"pages/index/index",
|
||||
"pages/index/detail",
|
||||
"pages/ming/index",
|
||||
"pages/contact/index"
|
||||
]
|
||||
}
|
||||
1
app.wxss
Normal file
1
app.wxss
Normal file
@ -0,0 +1 @@
|
||||
page{--status-bar-height:25px;--top-window-height:0px;--window-top:0px;--window-bottom:0px;--window-left:0px;--window-right:0px;--window-magin:0px}[data-c-h="true"]{display:none!important}
|
||||
1
common/assets.js
Normal file
1
common/assets.js
Normal file
@ -0,0 +1 @@
|
||||
var _imports_0 = "/static/kefu.png";exports._imports_0 = _imports_0;
|
||||
7210
common/vendor.js
Normal file
7210
common/vendor.js
Normal file
File diff suppressed because it is too large
Load Diff
300
pages/contact/index.js
Normal file
300
pages/contact/index.js
Normal file
@ -0,0 +1,300 @@
|
||||
// pages/contact/index.js
|
||||
const request = require('../../api/request.js');
|
||||
|
||||
|
||||
Page({
|
||||
/**
|
||||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
messages: [],
|
||||
inputText: '',
|
||||
scrollToId: '',
|
||||
// 使用本地头像
|
||||
userAvatar: '/static/user.png',
|
||||
serviceAvatar: '/static/contact.png',
|
||||
showGetUser: false,
|
||||
userInfo: {},
|
||||
appid: '',
|
||||
page: 1,
|
||||
page_size: 100,
|
||||
openid: '',
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面加载
|
||||
*/
|
||||
onLoad(options) {
|
||||
const accountInfo = wx.getAccountInfoSync();
|
||||
console.log(accountInfo.miniProgram);
|
||||
this.setData({
|
||||
appid: accountInfo.miniProgram.appId,
|
||||
});
|
||||
console.log('contact page onLoad, options:', options);
|
||||
|
||||
// this.getMessages()
|
||||
if (wx.getStorageSync('user_info')) {
|
||||
this.setData({
|
||||
showGetUser: false,
|
||||
userInfo: wx.getStorageSync('user_info'),
|
||||
});
|
||||
this.getMessages()
|
||||
} else {
|
||||
this.setData({
|
||||
showGetUser: true,
|
||||
});
|
||||
}
|
||||
|
||||
// this.setData({
|
||||
// appid: accountInfo.miniProgram.appId,
|
||||
// });
|
||||
|
||||
// console.log('appId',accountInfo.miniProgram);
|
||||
},
|
||||
// onShow() {
|
||||
// this.getMessages()
|
||||
// },
|
||||
|
||||
getMessages() {
|
||||
const userInfo = wx.getStorageSync('user_info');
|
||||
request('app/messages', 'get', {
|
||||
app_id: this.data.appid,
|
||||
user_id: userInfo.openid,
|
||||
page: this.data.page,
|
||||
page_size: this.data.page_size,
|
||||
}).then(res => {
|
||||
console.log('res', res);
|
||||
const list = res.list.map(item => {
|
||||
item.content = JSON.parse(item.content);
|
||||
return item;
|
||||
});
|
||||
this.setData({
|
||||
messages: list,
|
||||
});
|
||||
})
|
||||
},
|
||||
requestUserProfile(e) {
|
||||
console.log('user', e.detail);
|
||||
const user = e.detail;
|
||||
const that = this;
|
||||
// wx.setStorageSync('user_info', e.detail.userInfo);
|
||||
const accountInfo = wx.getAccountInfoSync();
|
||||
wx.login({
|
||||
success: function (res) {
|
||||
request('api/wechat/miniprogram/login', 'post', {
|
||||
"app_id": accountInfo.miniProgram.appId,
|
||||
"js_code": res.code,
|
||||
"encrypted_data": user.encryptedData,
|
||||
"iv": user.iv,
|
||||
"raw_data": user.rawData,
|
||||
"signature": user.signature
|
||||
}).then(resp => {
|
||||
wx.setStorageSync('user_info', resp);
|
||||
// wx.setStorageSync('open_id', resp.openid);
|
||||
this.setData({
|
||||
showGetUser: false,
|
||||
userInfo: resp
|
||||
});
|
||||
request('app/user/create', 'post', {
|
||||
"app_id": accountInfo.miniProgram.appId,
|
||||
"user_avatar": resp.user_avatar,
|
||||
"user_id": resp.openid,
|
||||
"user_name": resp.user_name
|
||||
}).then(resp => {
|
||||
that.getMessages()
|
||||
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
dismissGetUser() {
|
||||
this.setData({
|
||||
showGetUser: false
|
||||
});
|
||||
},
|
||||
|
||||
onReady() {
|
||||
// 初始化欢迎消息,带时间分割线
|
||||
const now = new Date();
|
||||
const timeStr = this.formatTime(now);
|
||||
this.setData({
|
||||
messages: [{
|
||||
id: 'm1',
|
||||
from: 'service',
|
||||
type: 'text',
|
||||
content: '您好!请问有什么可以帮您?',
|
||||
showTime: true,
|
||||
timeStr
|
||||
}],
|
||||
scrollToId: 'm1'
|
||||
});
|
||||
},
|
||||
|
||||
onInput(e) {
|
||||
this.setData({
|
||||
inputText: e.detail.value
|
||||
});
|
||||
},
|
||||
|
||||
sendText() {
|
||||
const text = this.data.inputText && this.data.inputText.trim();
|
||||
if (!text) return;
|
||||
const now = new Date();
|
||||
const id = 'u' + Date.now();
|
||||
const timeStr = this.formatTime(now);
|
||||
// 判断是否需要显示时间分割线
|
||||
let showTime = false;
|
||||
const lastMsg = this.data.messages.length ? this.data.messages[this.data.messages.length - 1] : null;
|
||||
if (!lastMsg || now - (lastMsg._ts || now) > 5 * 60 * 1000) showTime = true;
|
||||
const msg = {
|
||||
id,
|
||||
from: 'user',
|
||||
type: 'text',
|
||||
content: {
|
||||
messages: text
|
||||
},
|
||||
showTime,
|
||||
timeStr,
|
||||
_ts: now,
|
||||
"msg_type": 1,
|
||||
receiver_id: '',
|
||||
send_time: "刚刚",
|
||||
sender_id: this.data.userInfo.openid,
|
||||
sender_name: this.data.userInfo.user_name
|
||||
};
|
||||
const newMessages = this.data.messages.concat(msg);
|
||||
this.setData({
|
||||
messages: newMessages,
|
||||
inputText: ''
|
||||
});
|
||||
const accountInfo = wx.getAccountInfoSync();
|
||||
const userInfo = wx.getStorageSync('user_info')
|
||||
request('app/send_message', 'POST', {
|
||||
"app_id": accountInfo.miniProgram.appId,
|
||||
"content": JSON.stringify({
|
||||
messages: text
|
||||
}),
|
||||
"from_user_id": userInfo.openid,
|
||||
"from_user_name": userInfo.user_name,
|
||||
"msg_type": 1
|
||||
})
|
||||
// 等待渲染,确保 scroll-into-view 生效
|
||||
setTimeout(() => {
|
||||
this.setData({
|
||||
scrollToId: id
|
||||
});
|
||||
}, 50);
|
||||
|
||||
// 模拟客服回复(延迟)
|
||||
setTimeout(() => {
|
||||
const replyNow = new Date();
|
||||
const replyTimeStr = this.formatTime(replyNow);
|
||||
const reply = {
|
||||
id: 's' + Date.now(),
|
||||
from: 'service',
|
||||
type: 'text',
|
||||
content: '收到,客服正在处理中...',
|
||||
showTime: false,
|
||||
timeStr: replyTimeStr,
|
||||
_ts: replyNow
|
||||
};
|
||||
this.setData({
|
||||
messages: this.data.messages.concat(reply),
|
||||
scrollToId: reply.id
|
||||
});
|
||||
}, 800);
|
||||
},
|
||||
|
||||
chooseImage() {
|
||||
const that = this;
|
||||
wx.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ['compressed', 'original'],
|
||||
sourceType: ['album', 'camera'],
|
||||
success(res) {
|
||||
const tempFilePaths = res.tempFilePaths;
|
||||
console.log('选择的图片路径:', res);
|
||||
if (tempFilePaths && tempFilePaths.length) {
|
||||
const now = new Date();
|
||||
const id = 'u' + Date.now();
|
||||
const timeStr = that.formatTime(now);
|
||||
let showTime = false;
|
||||
const lastMsg = that.data.messages.length ? that.data.messages[that.data.messages.length - 1] : null;
|
||||
if (!lastMsg || now - (lastMsg._ts || now) > 5 * 60 * 1000) showTime = true;
|
||||
const msg = {
|
||||
id,
|
||||
from: 'user',
|
||||
msg_type: '2',
|
||||
content: {
|
||||
messages:tempFilePaths[0]
|
||||
},
|
||||
showTime,
|
||||
timeStr,
|
||||
_ts: now,
|
||||
sender_id: that.data.userInfo.openid,
|
||||
sender_name: that.data.userInfo.user_name
|
||||
};
|
||||
that.setData({
|
||||
messages: that.data.messages.concat(msg)
|
||||
});
|
||||
setTimeout(() => {
|
||||
that.setData({
|
||||
scrollToId: id
|
||||
});
|
||||
}, 50);
|
||||
|
||||
// 模拟客服返回图片确认
|
||||
// setTimeout(() => {
|
||||
// const replyNow = new Date();
|
||||
// const replyTimeStr = that.formatTime(replyNow);
|
||||
// const reply = {
|
||||
// id: 's' + Date.now(),
|
||||
// from: 'service',
|
||||
// type: 'text',
|
||||
// content: '已收到图片,感谢!',
|
||||
// showTime: false,
|
||||
// timeStr: replyTimeStr,
|
||||
// _ts: replyNow
|
||||
// };
|
||||
// that.setData({
|
||||
// messages: that.data.messages.concat(reply)
|
||||
// });
|
||||
// setTimeout(() => {
|
||||
// that.setData({
|
||||
// scrollToId: reply.id
|
||||
// });
|
||||
// }, 50);
|
||||
// }, 1200);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// 时间格式化
|
||||
formatTime(date) {
|
||||
const y = date.getFullYear();
|
||||
const m = (date.getMonth() + 1).toString().padStart(2, '0');
|
||||
const d = date.getDate().toString().padStart(2, '0');
|
||||
const h = date.getHours().toString().padStart(2, '0');
|
||||
const min = date.getMinutes().toString().padStart(2, '0');
|
||||
return `${y}年${m}月${d}日 ${h}:${min}`;
|
||||
},
|
||||
|
||||
previewImage(e) {
|
||||
const src = e.currentTarget.dataset.src;
|
||||
if (!src) return;
|
||||
wx.previewImage({
|
||||
urls: [src],
|
||||
current: src
|
||||
});
|
||||
},
|
||||
|
||||
onShow() {},
|
||||
onHide() {},
|
||||
onUnload() {},
|
||||
onPullDownRefresh() {},
|
||||
onReachBottom() {},
|
||||
onShareAppMessage() {}
|
||||
});
|
||||
5
pages/contact/index.json
Normal file
5
pages/contact/index.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"usingComponents": {},
|
||||
"navigationBarTitleText": "联系客服"
|
||||
|
||||
}
|
||||
54
pages/contact/index.wxml
Normal file
54
pages/contact/index.wxml
Normal file
@ -0,0 +1,54 @@
|
||||
<!-- pages/contact/index.wxml -->
|
||||
<view class="chat-page">
|
||||
<!-- 顶部蓝色栏 -->
|
||||
<!-- <view class="header-bar">
|
||||
<image class="header-avatar" src="{{serviceAvatar}}" />
|
||||
<text class="header-title">租号客服</text>
|
||||
</view> -->
|
||||
|
||||
<scroll-view class="messages" scroll-y="true" scroll-into-view="{{scrollToId}}">
|
||||
<block wx:for="{{messages}}" wx:key="id">
|
||||
<!-- 时间分割线 -->
|
||||
<block wx:if="{{item.showTime}}">
|
||||
<view class="msg-time">{{item.timeStr}}</view>
|
||||
</block>
|
||||
<view id="{{item.id}}" class="message {{item.sender_id == userInfo.openid ? 'user' : 'service'}}">
|
||||
<view class="avatar-wrap">
|
||||
<image class="avatar" src="{{item.sender_id == userInfo.openid ? userAvatar : serviceAvatar}}" />
|
||||
|
||||
</view>
|
||||
<view class="bubble">
|
||||
<block wx:if="{{item.msg_type == 1}}">
|
||||
<text class="msg-text">{{item.content.messages}}</text>
|
||||
</block>
|
||||
<block wx:elif="{{item.msg_type == 2}}">
|
||||
<image src="{{item.content.messages}}" bindtap="previewImage" data-src="{{item.content.messages}}" class="msg-image" mode="aspectFill" />
|
||||
</block>
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
</block>
|
||||
</scroll-view>
|
||||
|
||||
<view class="input-area">
|
||||
<image class="btn-image-img" src="/static/upload.png" bindtap="chooseImage" mode="aspectFit" />
|
||||
<input class="input" placeholder="请输入内容" value="{{inputText}}" bindinput="onInput" confirm-type="send" bindconfirm="sendText" />
|
||||
<button class="btn-send" bindtap="sendText">发送</button>
|
||||
</view>
|
||||
|
||||
<!-- 获取用户信息弹窗 -->
|
||||
<block wx:if="{{showGetUser}}">
|
||||
<view class="overlay">
|
||||
<view class="popup">
|
||||
<text class="popup-title">授权获取您的用户信息</text>
|
||||
<text class="popup-desc">授权后可用于显示头像、昵称等,提升聊天体验。</text>
|
||||
<view class="popup-actions">
|
||||
<button class="btn-primary" open-type="getUserInfo" bindgetuserinfo="requestUserProfile">获取用户信息</button>
|
||||
|
||||
<!-- <button class="btn-secondary" bindtap="dismissGetUser">稍后再说</button> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
266
pages/contact/index.wxss
Normal file
266
pages/contact/index.wxss
Normal file
@ -0,0 +1,266 @@
|
||||
/* chat styles */
|
||||
/* 顶部栏 */
|
||||
.chat-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
background: #fafbfc;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.header-bar {
|
||||
height: 120rpx;
|
||||
background: linear-gradient(90deg, #2196f3, #3f51b5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 32rpx;
|
||||
}
|
||||
|
||||
.header-avatar {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 36rpx;
|
||||
background: #fff;
|
||||
margin-right: 18rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08)
|
||||
}
|
||||
|
||||
.header-title {
|
||||
color: #fff;
|
||||
font-size: 34rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 消息区 */
|
||||
.messages {
|
||||
flex: 1;
|
||||
padding: 0 10rpx 10px 10px;
|
||||
overflow: auto;
|
||||
background: #fafbfc;
|
||||
box-sizing: border-box;
|
||||
|
||||
}
|
||||
|
||||
.msg-time {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
color: #b0b4bc;
|
||||
font-size: 26rpx;
|
||||
margin: 32rpx 0 16rpx 0;
|
||||
}
|
||||
|
||||
.message {
|
||||
/* margin-bottom: 18rpx; */
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
||||
.message.user {
|
||||
justify-content: flex-end;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.message.service {
|
||||
justify-content: flex-start;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.message.user .bubble {
|
||||
order: 1;
|
||||
background: #e6f0fe;
|
||||
color: #222;
|
||||
border-top-right-radius: 8rpx;
|
||||
border-bottom-right-radius: 18rpx;
|
||||
border-top-left-radius: 18rpx;
|
||||
border-bottom-left-radius: 18rpx;
|
||||
margin-right: 8rpx;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.message.user .avatar-wrap {
|
||||
order: 2;
|
||||
margin-left: 8rpx;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.message.service .bubble {
|
||||
order: 2;
|
||||
background: #fff;
|
||||
color: #222;
|
||||
border-top-left-radius: 8rpx;
|
||||
border-bottom-left-radius: 18rpx;
|
||||
border-top-right-radius: 18rpx;
|
||||
border-bottom-right-radius: 18rpx;
|
||||
margin-left: 8rpx;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.message.service .avatar-wrap {
|
||||
order: 1;
|
||||
margin-right: 8rpx;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.avatar-wrap {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
background: #fff;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.bubble {
|
||||
/* ...existing code... */
|
||||
min-height: 48rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bubble {
|
||||
max-width: 60vw;
|
||||
min-width: 80rpx;
|
||||
word-break: break-all;
|
||||
padding: 18rpx 22rpx;
|
||||
border-radius: 18rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
|
||||
font-size: 30rpx;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.msg-text {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.msg-image {
|
||||
width: 200rpx;
|
||||
height: 140rpx;
|
||||
border-radius: 10rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 输入栏 */
|
||||
.input-area {
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16rpx 16rpx 0 8rpx;
|
||||
box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
.btn-image {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0 4rpx 0 4rpx;
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-size: 32rpx;
|
||||
color: #8a8a8a;
|
||||
}
|
||||
|
||||
.btn-image-img {
|
||||
width: 68rpx;
|
||||
height: 68rpx;
|
||||
margin-right: 8rpx;
|
||||
margin-left: 4rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
height: 68rpx;
|
||||
border-radius: 12rpx;
|
||||
border: 0;
|
||||
padding: 0 24rpx;
|
||||
font-size: 30rpx;
|
||||
background: #eff1f2;
|
||||
margin: 0 10rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.btn-send {
|
||||
background: #2196f3;
|
||||
color: #fff;
|
||||
padding: 0 32rpx;
|
||||
height: 68rpx;
|
||||
line-height: 68rpx;
|
||||
border-radius: 12rpx;
|
||||
font-size: 30rpx;
|
||||
border: none;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
/* 获取用户信息弹窗 */
|
||||
.overlay {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.45);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 999
|
||||
}
|
||||
|
||||
.popup {
|
||||
width: 80%;
|
||||
background: #fff;
|
||||
border-radius: 12rpx;
|
||||
padding: 40rpx 24rpx;
|
||||
text-align: center
|
||||
}
|
||||
|
||||
.popup-title {
|
||||
font-size: 32rpx;
|
||||
margin-bottom: 12rpx;
|
||||
color: #333;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.popup-desc {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
margin-bottom: 18rpx
|
||||
}
|
||||
|
||||
.popup-actions {
|
||||
display: flex;
|
||||
justify-content: space-around
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
margin-top: 40rpx;
|
||||
background: #2196f3;
|
||||
color: #fff;
|
||||
padding: 8rpx 20rpx;
|
||||
border-radius: 8rpx;
|
||||
border: none;
|
||||
width: 90%;
|
||||
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: #fff;
|
||||
color: #666;
|
||||
padding: 12rpx 20rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 1px solid #eee
|
||||
}
|
||||
118
pages/index/detail copy.js
Normal file
118
pages/index/detail copy.js
Normal file
@ -0,0 +1,118 @@
|
||||
var common_vendor = require("../../common/vendor.js");var common_assets = require("../../common/assets.js");var _sfc_main = {
|
||||
__name: "detail",
|
||||
setup: function setup(__props) {
|
||||
var danceList = common_vendor.ref([{
|
||||
id: 0,
|
||||
name: "街舞",
|
||||
category: "STORE",
|
||||
description: "街舞是一种充满活力和创意的舞蹈形式,起源于美国街头文化。它以自由的风格、强烈的节奏感和个性化的表达而闻名,是年轻人展现自我、释放激情的绝佳方式。",
|
||||
history: "街舞起源于20世纪70年代的美国纽约,最初是非洲裔和拉丁裔青年在街头聚会时的即兴舞蹈。随着嘻哈文化的发展,街舞逐渐形成了Breaking、Popping、Locking、Hip-hop等多种风格,并传播到世界各地。",
|
||||
features: "街舞具有动作多样化、变化快的特点,强调个人风格和即兴创作。舞蹈动作力度强、节奏感明显,融合了体操、武术等元素。舞者可以自由发挥创意,展现独特的个性和态度。",
|
||||
tips: "学习街舞需要循序渐进,先掌握基本的律动和步伐,再学习复杂的技巧动作。要多听音乐培养节奏感,勤加练习提高身体协调性。最重要的是要有自信,敢于表达自己的风格。"
|
||||
}, {
|
||||
id: 1,
|
||||
name: "芭蕾舞",
|
||||
category: "ACTIVITY",
|
||||
description: "芭蕾舞是一种优雅高贵的古典舞蹈,注重技巧性和艺术表现力。它以严格的动作规范、优美的身体线条和深刻的艺术内涵而著称,是舞蹈艺术的瑰宝。",
|
||||
history: "芭蕾舞起源于15世纪的意大利宫廷,后在法国路易十四时期得到大力发展。18世纪传入俄国后达到艺术高峰,产生了《天鹅湖》、《胡桃夹子》等经典作品。现代芭蕾在保持古典精髓的同时,融入了更多创新元素。",
|
||||
features: "芭蕾舞动作规范严格,要求舞者具备良好的身体条件和扎实的基本功。舞蹈注重身体线条的延伸和姿态的优美,强调轻盈飘逸的质感。每个动作都有严格的标准,需要长期训练才能达到专业水准。",
|
||||
tips: "学习芭蕾需要从基本功开始,包括把杆练习、中间练习等。要注重身体姿态的正确性,培养良好的舞蹈感觉。坚持每天练习,逐步提高柔韧性、力量和协调性。同时要培养音乐感和艺术表现力。"
|
||||
}, {
|
||||
id: 2,
|
||||
name: "机械舞",
|
||||
category: "STORE",
|
||||
description: "机械舞是街舞的一种风格,通过肌肉的快速收缩与放松产生震动效果,模拟机器人的动作。它以独特的视觉效果和精确的身体控制而著称,是技巧性很强的舞蹈形式。",
|
||||
history: "机械舞起源于20世纪70年代的美国加州,由舞者Boogaloo Sam创立。最初受到机器人和动画片的启发,后来发展成为街舞文化的重要组成部分。80年代通过电视节目传播到世界各地,成为流行的舞蹈风格。",
|
||||
features: '机械舞的核心是通过肌肉的控制产生"Pop"的效果,使身体看起来像机器人一样僵硬而有节奏。舞蹈要求精确的时间掌控和身体各部位的独立控制,动作具有很强的视觉冲击力和娱乐性。',
|
||||
tips: "学习机械舞要从基础的肌肉控制开始,练习如何让身体各部位产生震动效果。要培养对音乐节拍的敏感度,掌握准确的时间点。多观察机器人的动作特点,模仿其僵硬而精确的运动方式。"
|
||||
}, {
|
||||
id: 3,
|
||||
name: "古典舞",
|
||||
category: "ACTIVITY",
|
||||
description: "中国古典舞承载着深厚的文化底蕴,展现东方舞蹈的独特魅力。它融合了武术、戏曲等传统艺术元素,以身韵结合、意境深远而著称,是中华文化的重要载体。",
|
||||
history: "中国古典舞有着悠久的历史,可以追溯到古代宫廷舞蹈和民间舞蹈。经过历代艺术家的传承和发展,形成了独特的艺术风格。现代古典舞在保持传统精髓的基础上,融入了现代舞蹈技巧,展现出新的艺术魅力。",
|
||||
features: '古典舞注重"形神兼备,身心并用",强调内在气质的培养。动作流畅优美,富有诗意,讲究"圆、游、变、幻"的运动规律。舞蹈融合了"身法、身韵、技巧"三大要素,体现了中华文化的深厚底蕴。',
|
||||
tips: '学习古典舞要注重基本功训练,包括身体的柔韧性、协调性和表现力。要理解舞蹈的文化内涵,培养对传统文化的感悟。练习时要注意动作的韵律感,追求"形神兼备"的艺术境界。'
|
||||
}, {
|
||||
id: 4,
|
||||
name: "拉丁舞",
|
||||
category: "STORE",
|
||||
description: "拉丁舞热情奔放,充满异域风情,是社交舞蹈的重要组成部分。它以动感的音乐、激情的动作和强烈的表现力而著称,能够充分展现舞者的魅力和活力。",
|
||||
history: "拉丁舞起源于拉丁美洲,融合了欧洲、非洲和美洲原住民的舞蹈元素。20世纪初传入欧美后,逐渐发展成为国际标准舞的重要组成部分。现在包括恰恰、桑巴、伦巴、牛仔、斗牛五个舞种。",
|
||||
features: "拉丁舞动作热情奔放,充满活力,音乐节奏明快富有感染力。舞蹈注重身体线条和肌肉控制,强调胯部和腰部的灵活运用。具有很强的社交属性,适合双人配合表演。",
|
||||
tips: "学习拉丁舞要从基本步伐开始,掌握各个舞种的特点和风格。要培养对音乐的感受力,学会用身体表达音乐的情感。注重身体协调性的训练,特别是胯部和腰部的灵活性。要敢于表达,展现自信和热情。"
|
||||
}, {
|
||||
id: 5,
|
||||
name: "摩登舞",
|
||||
category: "ACTIVITY",
|
||||
description: "摩登舞优雅端庄,是标准舞的重要组成部分,展现绅士淑女风范。它以规范的动作、优美的姿态和高雅的气质而著称,是社交场合的经典舞蹈形式。",
|
||||
history: "摩登舞起源于欧洲宫廷舞蹈,经过几个世纪的发展演变,形成了现在的标准形式。包括华尔兹、探戈、狐步、快步、维也纳华尔兹五个舞种。20世纪初开始在世界范围内推广,成为国际标准舞的重要组成部分。",
|
||||
features: "摩登舞动作优雅端庄,姿态标准规范,强调双人配合的默契程度。舞蹈音乐优美,富有艺术感染力,注重礼仪和绅士淑女风范。要求舞者具备良好的身体姿态和高雅的气质。",
|
||||
tips: "学习摩登舞要注重基本姿态的训练,保持挺拔优雅的身体线条。要培养与舞伴的默契配合,学会引带和跟随。注重音乐感的培养,理解不同舞种的风格特点。要注意礼仪修养,展现绅士淑女的风范。"
|
||||
}]);
|
||||
var currentDance = common_vendor.ref(null);
|
||||
var danceIndex = common_vendor.ref(0);
|
||||
var wallpaperUrl = common_vendor.ref();
|
||||
var appId = common_vendor.ref('');
|
||||
common_vendor.onLoad(function (options) {
|
||||
common_vendor.index.__f__("log", "at pages/index/detail.vue:125", "接收到的参数:", options);
|
||||
// 尝试从 options 或当前页面信息中提取 app_id,保存在 appId 中供模板使用
|
||||
try {
|
||||
if (options && options.app_id) {
|
||||
appId.value = options.app_id;
|
||||
} else {
|
||||
var pages = typeof getCurrentPages === 'function' ? getCurrentPages() : common_vendor.index.getCurrentPages && common_vendor.index.getCurrentPages();
|
||||
if (pages && pages.length) {
|
||||
var cur = pages[pages.length - 1];
|
||||
if (cur && cur.options && cur.options.app_id) {
|
||||
appId.value = cur.options.app_id;
|
||||
} else if (cur && cur.__route__) {
|
||||
var route = cur.__route__;
|
||||
var idx = route.indexOf('?');
|
||||
if (idx !== -1) {
|
||||
var qs = route.substring(idx + 1);
|
||||
var parts = qs.split('&');
|
||||
for (var k = 0; k < parts.length; k++) {
|
||||
var p = parts[k].split('=');
|
||||
if (p[0] === 'app_id') {
|
||||
appId.value = decodeURIComponent(p[1] || '');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
if (options.url == 1) {
|
||||
wallpaperUrl.value = options.url;
|
||||
return;
|
||||
}
|
||||
if (options.index !== void 0) {
|
||||
danceIndex.value = parseInt(options.index);
|
||||
currentDance.value = danceList.value[danceIndex.value];
|
||||
} else {
|
||||
currentDance.value = danceList.value[0];
|
||||
}
|
||||
});
|
||||
return function (_ctx, _cache) {
|
||||
return common_vendor.e({
|
||||
a: wallpaperUrl.value == 1,
|
||||
j: appId.value
|
||||
}, wallpaperUrl.value == 1 ? {
|
||||
b: common_assets._imports_0
|
||||
} : common_vendor.e({
|
||||
c: currentDance.value
|
||||
}, currentDance.value ? {
|
||||
d: common_vendor.t(currentDance.value.name),
|
||||
e: common_vendor.t(currentDance.value.category),
|
||||
f: common_vendor.t(currentDance.value.description || "内容待补充..."),
|
||||
g: common_vendor.t(currentDance.value.history || "内容待补充..."),
|
||||
h: common_vendor.t(currentDance.value.features || "内容待补充..."),
|
||||
i: common_vendor.t(currentDance.value.tips || "内容待补充...")
|
||||
} : {}));
|
||||
};
|
||||
}
|
||||
};wx.createPage(_sfc_main);
|
||||
148
pages/index/detail.js
Normal file
148
pages/index/detail.js
Normal file
@ -0,0 +1,148 @@
|
||||
// 引入公共资源(原生小程序中需确保路径正确,若为工具类可直接 require,若为静态资源需用绝对路径)
|
||||
const common_vendor = require("../../common/vendor.js");
|
||||
const common_assets = require("../../common/assets.js");
|
||||
|
||||
// 定义舞蹈列表数据(原生小程序用普通数组存储,无需 ref 响应式包装)
|
||||
const danceList = [
|
||||
{
|
||||
id: 0,
|
||||
name: "街舞",
|
||||
category: "STORE",
|
||||
description: "街舞是一种充满活力和创意的舞蹈形式,起源于美国街头文化。它以自由的风格、强烈的节奏感和个性化的表达而闻名,是年轻人展现自我、释放激情的绝佳方式。",
|
||||
history: "街舞起源于20世纪70年代的美国纽约,最初是非洲裔和拉丁裔青年在街头聚会时的即兴舞蹈。随着嘻哈文化的发展,街舞逐渐形成了Breaking、Popping、Locking、Hip-hop等多种风格,并传播到世界各地。",
|
||||
features: "街舞具有动作多样化、变化快的特点,强调个人风格和即兴创作。舞蹈动作力度强、节奏感明显,融合了体操、武术等元素。舞者可以自由发挥创意,展现独特的个性和态度。",
|
||||
tips: "学习街舞需要循序渐进,先掌握基本的律动和步伐,再学习复杂的技巧动作。要多听音乐培养节奏感,勤加练习提高身体协调性。最重要的是要有自信,敢于表达自己的风格。"
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: "芭蕾舞",
|
||||
category: "ACTIVITY",
|
||||
description: "芭蕾舞是一种优雅高贵的古典舞蹈,注重技巧性和艺术表现力。它以严格的动作规范、优美的身体线条和深刻的艺术内涵而著称,是舞蹈艺术的瑰宝。",
|
||||
history: "芭蕾舞起源于15世纪的意大利宫廷,后在法国路易十四时期得到大力发展。18世纪传入俄国后达到艺术高峰,产生了《天鹅湖》、《胡桃夹子》等经典作品。现代芭蕾在保持古典精髓的同时,融入了更多创新元素。",
|
||||
features: "芭蕾舞动作规范严格,要求舞者具备良好的身体条件和扎实的基本功。舞蹈注重身体线条的延伸和姿态的优美,强调轻盈飘逸的质感。每个动作都有严格的标准,需要长期训练才能达到专业水准。",
|
||||
tips: "学习芭蕾需要从基本功开始,包括把杆练习、中间练习等。要注重身体姿态的正确性,培养良好的舞蹈感觉。坚持每天练习,逐步提高柔韧性、力量和协调性。同时要培养音乐感和艺术表现力。"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "机械舞",
|
||||
category: "STORE",
|
||||
description: "机械舞是街舞的一种风格,通过肌肉的快速收缩与放松产生震动效果,模拟机器人的动作。它以独特的视觉效果和精确的身体控制而著称,是技巧性很强的舞蹈形式。",
|
||||
history: "机械舞起源于20世纪70年代的美国加州,由舞者Boogaloo Sam创立。最初受到机器人和动画片的启发,后来发展成为街舞文化的重要组成部分。80年代通过电视节目传播到世界各地,成为流行的舞蹈风格。",
|
||||
features: '机械舞的核心是通过肌肉的控制产生"Pop"的效果,使身体看起来像机器人一样僵硬而有节奏。舞蹈要求精确的时间掌控和身体各部位的独立控制,动作具有很强的视觉冲击力和娱乐性。',
|
||||
tips: "学习机械舞要从基础的肌肉控制开始,练习如何让身体各部位产生震动效果。要培养对音乐节拍的敏感度,掌握准确的时间点。多观察机器人的动作特点,模仿其僵硬而精确的运动方式。"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "古典舞",
|
||||
category: "ACTIVITY",
|
||||
description: "中国古典舞承载着深厚的文化底蕴,展现东方舞蹈的独特魅力。它融合了武术、戏曲等传统艺术元素,以身韵结合、意境深远而著称,是中华文化的重要载体。",
|
||||
history: "中国古典舞有着悠久的历史,可以追溯到古代宫廷舞蹈和民间舞蹈。经过历代艺术家的传承和发展,形成了独特的艺术风格。现代古典舞在保持传统精髓的基础上,融入了现代舞蹈技巧,展现出新的艺术魅力。",
|
||||
features: '古典舞注重"形神兼备,身心并用",强调内在气质的培养。动作流畅优美,富有诗意,讲究"圆、游、变、幻"的运动规律。舞蹈融合了"身法、身韵、技巧"三大要素,体现了中华文化的深厚底蕴。',
|
||||
tips: '学习古典舞要注重基本功训练,包括身体的柔韧性、协调性和表现力。要理解舞蹈的文化内涵,培养对传统文化的感悟。练习时要注意动作的韵律感,追求"形神兼备"的艺术境界。'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "拉丁舞",
|
||||
category: "STORE",
|
||||
description: "拉丁舞热情奔放,充满异域风情,是社交舞蹈的重要组成部分。它以动感的音乐、激情的动作和强烈的表现力而著称,能够充分展现舞者的魅力和活力。",
|
||||
history: "拉丁舞起源于拉丁美洲,融合了欧洲、非洲和美洲原住民的舞蹈元素。20世纪初传入欧美后,逐渐发展成为国际标准舞的重要组成部分。现在包括恰恰、桑巴、伦巴、牛仔、斗牛五个舞种。",
|
||||
features: "拉丁舞动作热情奔放,充满活力,音乐节奏明快富有感染力。舞蹈注重身体线条和肌肉控制,强调胯部和腰部的灵活运用。具有很强的社交属性,适合双人配合表演。",
|
||||
tips: "学习拉丁舞要从基本步伐开始,掌握各个舞种的特点和风格。要培养对音乐的感受力,学会用身体表达音乐的情感。注重身体协调性的训练,特别是胯部和腰部的灵活性。要敢于表达,展现自信和热情。"
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "摩登舞",
|
||||
category: "ACTIVITY",
|
||||
description: "摩登舞优雅端庄,是标准舞的重要组成部分,展现绅士淑女风范。它以规范的动作、优美的姿态和高雅的气质而著称,是社交场合的经典舞蹈形式。",
|
||||
history: "摩登舞起源于欧洲宫廷舞蹈,经过几个世纪的发展演变,形成了现在的标准形式。包括华尔兹、探戈、狐步、快步、维也纳华尔兹五个舞种。20世纪初开始在世界范围内推广,成为国际标准舞的重要组成部分。",
|
||||
features: "摩登舞动作优雅端庄,姿态标准规范,强调双人配合的默契程度。舞蹈音乐优美,富有艺术感染力,注重礼仪和绅士淑女风范。要求舞者具备良好的身体姿态和高雅的气质。",
|
||||
tips: "学习摩登舞要注重基本姿态的训练,保持挺拔优雅的身体线条。要培养与舞伴的默契配合,学会引带和跟随。注重音乐感的培养,理解不同舞种的风格特点。要注意礼仪修养,展现绅士淑女的风范。"
|
||||
}
|
||||
];
|
||||
|
||||
// 原生小程序 Page 构造器(核心:数据、生命周期、方法)
|
||||
Page({
|
||||
// 1. 页面初始数据(对应 Vue 的 ref 数据,需用 this.data 访问,this.setData 更新)
|
||||
data: {
|
||||
currentDance: null, // 当前选中的舞蹈详情
|
||||
danceIndex: 0, // 当前舞蹈在列表中的索引
|
||||
wallpaperUrl: "", // 壁纸地址
|
||||
appId: "", // 应用 ID
|
||||
// 引入静态资源(原生小程序中需确保 assets 内的资源路径正确,此处与原代码保持一致)
|
||||
commonAssets: common_assets
|
||||
},
|
||||
|
||||
// 2. 页面加载生命周期(对应原代码的 onLoad,接收页面参数 options)
|
||||
onLoad(options) {
|
||||
// 日志打印(替换原框架的 log 方法,使用微信原生 console.log)
|
||||
console.log("at pages/index/detail.js: onLoad", "接收到的参数:", options);
|
||||
|
||||
// 提取 app_id(逻辑与原代码一致,适配原生小程序 API)
|
||||
try {
|
||||
if (options && options.app_id) {
|
||||
this.setData({ appId: options.app_id }); // 原生用 setData 更新数据
|
||||
} else {
|
||||
// 原生小程序获取当前页面栈:getCurrentPages() 直接调用(无需通过 vendor)
|
||||
const pages = getCurrentPages();
|
||||
if (pages && pages.length) {
|
||||
const curPage = pages[pages.length - 1]; // 最后一个页面即当前页
|
||||
if (curPage && curPage.options && curPage.options.app_id) {
|
||||
this.setData({ appId: curPage.options.app_id });
|
||||
} else if (curPage && curPage.__route__) {
|
||||
const route = curPage.__route__;
|
||||
const idx = route.indexOf('?');
|
||||
if (idx !== -1) {
|
||||
const qs = route.substring(idx + 1);
|
||||
const parts = qs.split('&');
|
||||
for (let k = 0; k < parts.length; k++) {
|
||||
const [key, value] = parts[k].split('=');
|
||||
if (key === 'app_id') {
|
||||
this.setData({ appId: decodeURIComponent(value || '') });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("提取 app_id 失败:", e);
|
||||
}
|
||||
|
||||
// 处理壁纸地址逻辑
|
||||
if (options.url === "1") { // 原生小程序参数默认是字符串,需注意类型匹配
|
||||
this.setData({ wallpaperUrl: options.url });
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理舞蹈详情逻辑(根据 options.index 选择当前舞蹈)
|
||||
if (options.index !== undefined) {
|
||||
const index = parseInt(options.index);
|
||||
this.setData({
|
||||
danceIndex: index,
|
||||
currentDance: danceList[index] // 从预定义列表中获取对应舞蹈
|
||||
});
|
||||
} else {
|
||||
// 无索引时默认显示第一个舞蹈
|
||||
this.setData({
|
||||
currentDance: danceList[0]
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 3. 其他可选生命周期(如需扩展,可在此添加,如 onShow、onReady 等)
|
||||
onShow() {
|
||||
// 页面显示时的逻辑(如重新获取数据等,根据需求添加)
|
||||
},
|
||||
|
||||
// 4. 自定义方法(如需添加交互逻辑,可在此定义,如切换舞蹈、跳转等)
|
||||
// 示例:切换到下一个舞蹈
|
||||
switchToNextDance() {
|
||||
const { danceIndex } = this.data;
|
||||
const nextIndex = (danceIndex + 1) % danceList.length; // 循环切换
|
||||
this.setData({
|
||||
danceIndex: nextIndex,
|
||||
currentDance: danceList[nextIndex]
|
||||
});
|
||||
}
|
||||
});
|
||||
1
pages/index/detail.json
Normal file
1
pages/index/detail.json
Normal file
@ -0,0 +1 @@
|
||||
{"navigationBarTitleText":"舞蹈","usingComponents":{}}
|
||||
66
pages/index/detail.wxml
Normal file
66
pages/index/detail.wxml
Normal file
@ -0,0 +1,66 @@
|
||||
<!-- pages/index/detail.wxml -->
|
||||
<!-- 1. 壁纸+客服导航栏区域(对应原逻辑中 wallpaperUrl=1 的场景) -->
|
||||
<view wx:if="{{ wallpaperUrl === '1' }}">
|
||||
<!-- 全屏壁纸:src 绑定 JS 中 commonAssets 里的图片资源 -->
|
||||
<image
|
||||
mode="aspectFill"
|
||||
src="{{ commonAssets._imports_0 }}"
|
||||
style="width:100vw; height:100vh;"
|
||||
></image>
|
||||
|
||||
<!-- 客服跳转导航:url 拼接 appId,与 JS 中 appId 变量对齐 -->
|
||||
<navigator
|
||||
url="/pages/contact/index{{ appId ? ('?app_id=' + appId) : '' }}"
|
||||
style="position:fixed; width:80%; margin-left:10%; bottom:100rpx; color:#fff; background:#ec6d23; border-radius:15rpx; height:75rpx; display:flex; justify-content:center; align-items:center; margin-top:50rpx; z-index:9999; text-decoration:none;"
|
||||
>
|
||||
<view style="width:100%; height:100%; display:flex; justify-content:center; align-items:center; color:#fff;">
|
||||
欢迎联系人工客服
|
||||
</view>
|
||||
</navigator>
|
||||
</view>
|
||||
|
||||
<!-- 2. 舞蹈详情区域(对应原逻辑中 wallpaperUrl≠1 的场景) -->
|
||||
<view class="dance-detail-container" wx:else>
|
||||
<view class="header"></view>
|
||||
|
||||
<!-- 2.1 舞蹈详情内容(currentDance 存在时显示,对应原逻辑的 {{c}}) -->
|
||||
<view class="detail-content" wx:if="{{ currentDance }}">
|
||||
<!-- 舞蹈名称+分类 -->
|
||||
<view class="dance-header">
|
||||
<text class="dance-name">{{ currentDance.name }}</text>
|
||||
<text class="dance-category">{{ currentDance.category }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 舞蹈详情信息(简介/历史/特点/要点,与 JS 中 currentDance 字段对齐) -->
|
||||
<view class="dance-info">
|
||||
<!-- 舞蹈简介:对应原 {{f}},使用 currentDance.description 兜底 -->
|
||||
<view class="info-section">
|
||||
<text class="section-title">舞蹈简介</text>
|
||||
<text class="section-content">{{ currentDance.description || '内容待补充...' }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 起源历史:对应原 {{g}},使用 currentDance.history 兜底 -->
|
||||
<view class="info-section">
|
||||
<text class="section-title">起源历史</text>
|
||||
<text class="section-content">{{ currentDance.history || '内容待补充...' }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 基本特点:对应原 {{h}},使用 currentDance.features 兜底 -->
|
||||
<view class="info-section">
|
||||
<text class="section-title">基本特点</text>
|
||||
<text class="section-content">{{ currentDance.features || '内容待补充...' }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 学习要点:对应原 {{i}},使用 currentDance.tips 兜底 -->
|
||||
<view class="info-section">
|
||||
<text class="section-title">学习要点</text>
|
||||
<text class="section-content">{{ currentDance.tips || '内容待补充...' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 2.2 加载中提示(currentDance 不存在时显示,对应原逻辑的 wx:else) -->
|
||||
<view class="loading" wx:else>
|
||||
<text class="loading-text">加载中...</text>
|
||||
</view>
|
||||
</view>
|
||||
1
pages/index/detail.wxss
Normal file
1
pages/index/detail.wxss
Normal file
@ -0,0 +1 @@
|
||||
.dance-detail-container,page{background:linear-gradient(180deg,#2c2c54,#40407a)}.dance-detail-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;min-height:100vh}.header{padding:60rpx 40rpx 20rpx}.header .back-button{align-items:center;display:-webkit-flex;display:flex;width:-webkit-fit-content;width:fit-content}.header .back-button .back-icon{color:#fff;font-size:36rpx;margin-right:10rpx}.header .back-button .back-text{color:#fff;font-size:32rpx;font-weight:500}.detail-content{padding:0 40rpx 40rpx}.dance-header{margin-bottom:40rpx;text-align:center}.dance-header .dance-name{color:#fff;display:block;font-size:48rpx;font-weight:700;margin-bottom:10rpx}.dance-header .dance-category{color:hsla(0,0%,100%,.7);font-size:24rpx;font-weight:500;letter-spacing:2rpx}.dance-info .info-section{backdrop-filter:blur(20rpx);background:hsla(0,0%,100%,.1);border:1px solid hsla(0,0%,100%,.2);border-radius:20rpx;margin-bottom:24rpx;padding:32rpx}.dance-info .info-section .section-title{color:#ff6b9d;display:block;font-size:32rpx;font-weight:700;margin-bottom:16rpx}.dance-info .info-section .section-content{color:hsla(0,0%,100%,.9);font-size:28rpx;line-height:1.6;text-align:justify}.loading{align-items:center;display:-webkit-flex;display:flex;height:60vh;justify-content:center}.loading .loading-text{color:hsla(0,0%,100%,.7);font-size:32rpx}
|
||||
43
pages/index/index.js
Normal file
43
pages/index/index.js
Normal file
@ -0,0 +1,43 @@
|
||||
var common_vendor = require("../../common/vendor.js");var _sfc_main = {
|
||||
__name: "index",
|
||||
setup: function setup(__props) {
|
||||
var currentSwiperIndex = common_vendor.ref(0);
|
||||
var onSwiperChange = function onSwiperChange(e) {
|
||||
currentSwiperIndex.value = e.detail.current;
|
||||
};
|
||||
var navigateToDetail = function navigateToDetail(index) {
|
||||
common_vendor.index.navigateTo({
|
||||
url: "/pages/index/detail?index=".concat(index)
|
||||
});
|
||||
};
|
||||
var goToTerms = function goToTerms() {
|
||||
common_vendor.index.navigateTo({
|
||||
url: "/pages/ming/index"
|
||||
});
|
||||
};
|
||||
return function (_ctx, _cache) {
|
||||
return {
|
||||
a: common_vendor.o(onSwiperChange),
|
||||
b: common_vendor.o(function ($event) {
|
||||
return navigateToDetail(0);
|
||||
}),
|
||||
c: common_vendor.o(function ($event) {
|
||||
return navigateToDetail(1);
|
||||
}),
|
||||
d: common_vendor.o(function ($event) {
|
||||
return navigateToDetail(2);
|
||||
}),
|
||||
e: common_vendor.o(function ($event) {
|
||||
return navigateToDetail(3);
|
||||
}),
|
||||
f: common_vendor.o(function ($event) {
|
||||
return navigateToDetail(4);
|
||||
}),
|
||||
g: common_vendor.o(function ($event) {
|
||||
return navigateToDetail(5);
|
||||
}),
|
||||
h: common_vendor.o(goToTerms)
|
||||
};
|
||||
};
|
||||
}
|
||||
};wx.createPage(_sfc_main);
|
||||
1
pages/index/index.json
Normal file
1
pages/index/index.json
Normal file
@ -0,0 +1 @@
|
||||
{"navigationBarTitleText":"舞蹈","usingComponents":{}}
|
||||
165
pages/index/index.wxml
Normal file
165
pages/index/index.wxml
Normal file
@ -0,0 +1,165 @@
|
||||
<view class="dance-container">
|
||||
<swiper autoplay="{{true}}" bindchange="{{a}}" class="banner-swiper" duration="{{500}}" indicatorActiveColor="#6c5ce7" indicatorColor="rgba(255,255,255,0.4)" indicatorDots="{{true}}" interval="{{3000}}">
|
||||
<swiper-item>
|
||||
<view class="top-banner">
|
||||
<view class="banner-content">
|
||||
<view class="left-section">
|
||||
<text class="main-title">舞</text>
|
||||
<text class="sub-title">蹈</text>
|
||||
<text class="sub-title">世</text>
|
||||
<text class="sub-title">界</text>
|
||||
</view>
|
||||
<view class="right-section">
|
||||
<view class="dance-emoji">🎭</view>
|
||||
<view class="promo-card hot-class-card">
|
||||
<view class="card-header">
|
||||
<text class="card-title">HOT</text>
|
||||
<text class="card-subtitle">CLASS</text>
|
||||
<view class="music-icon">🎵</view>
|
||||
</view>
|
||||
<view class="card-content">
|
||||
<text class="card-info">专业教学</text>
|
||||
<text class="card-info">名师指导</text>
|
||||
</view>
|
||||
<view class="card-footer">
|
||||
<view class="discount-badge">
|
||||
<text class="badge-text">限时</text>
|
||||
<text class="badge-text">优惠</text>
|
||||
</view>
|
||||
<view class="price-section">
|
||||
<text class="discount-label">立减</text>
|
||||
<text class="price-value">50%</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
<swiper-item>
|
||||
<view class="top-banner">
|
||||
<view class="banner-content">
|
||||
<view class="left-section">
|
||||
<text class="main-title">精</text>
|
||||
<text class="sub-title">彩</text>
|
||||
<text class="sub-title">表</text>
|
||||
<text class="sub-title">演</text>
|
||||
</view>
|
||||
<view class="right-section">
|
||||
<view class="dance-emoji">⭐</view>
|
||||
<view class="promo-card event-card">
|
||||
<view class="card-header">
|
||||
<text class="card-title">EVENT</text>
|
||||
<text class="card-subtitle">SHOW</text>
|
||||
<view class="trophy-icon">🏆</view>
|
||||
</view>
|
||||
<view class="card-content">
|
||||
<text class="card-info">年度大赛</text>
|
||||
<text class="card-info">等你参与</text>
|
||||
</view>
|
||||
<view class="card-footer">
|
||||
<view class="discount-badge">
|
||||
<text class="badge-text">报名</text>
|
||||
<text class="badge-text">中</text>
|
||||
</view>
|
||||
<view class="price-section">
|
||||
<text class="discount-label">奖金</text>
|
||||
<text class="price-value">1W+</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
<swiper-item>
|
||||
<view class="top-banner">
|
||||
<view class="banner-content">
|
||||
<view class="left-section">
|
||||
<text class="main-title">好</text>
|
||||
<text class="sub-title">玩</text>
|
||||
<text class="sub-title">新</text>
|
||||
<text class="sub-title">市</text>
|
||||
</view>
|
||||
<view class="right-section">
|
||||
<view class="dance-emoji">🛍️</view>
|
||||
<view class="promo-card new-arrival-card">
|
||||
<view class="card-header">
|
||||
<text class="card-title">NEW</text>
|
||||
<text class="card-subtitle">ARRIVAL</text>
|
||||
<view class="balloon-icon">🎈</view>
|
||||
</view>
|
||||
<view class="card-content">
|
||||
<text class="card-info">STORE SALE</text>
|
||||
<text class="card-info">KOREA STAR</text>
|
||||
</view>
|
||||
<view class="card-footer">
|
||||
<view class="discount-badge">
|
||||
<text class="badge-text">NEW</text>
|
||||
<text class="badge-text">ARRIVAL</text>
|
||||
</view>
|
||||
<view class="price-section">
|
||||
<text class="discount-label">解锁新</text>
|
||||
<text class="price-value">0PE</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view class="dance-grid">
|
||||
<view class="dance-row">
|
||||
<view bindtap="{{b}}" class="dance-item street-dance">
|
||||
<view class="dance-content">
|
||||
<text class="dance-title">街舞</text>
|
||||
<text class="dance-subtitle">STORE</text>
|
||||
</view>
|
||||
</view>
|
||||
<view bindtap="{{c}}" class="dance-item ballet-dance">
|
||||
<view class="dance-content">
|
||||
<text class="dance-title">芭蕾舞</text>
|
||||
<text class="dance-subtitle">ACTIVITY</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="dance-row">
|
||||
<view bindtap="{{d}}" class="dance-item machine-dance">
|
||||
<view class="dance-content">
|
||||
<text class="dance-title">机械舞</text>
|
||||
<text class="dance-subtitle">STORE</text>
|
||||
</view>
|
||||
</view>
|
||||
<view bindtap="{{e}}" class="dance-item classical-dance">
|
||||
<view class="dance-content">
|
||||
<text class="dance-title">古典舞</text>
|
||||
<text class="dance-subtitle">ACTIVITY</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="dance-row">
|
||||
<view bindtap="{{f}}" class="dance-item latin-dance">
|
||||
<view class="dance-content">
|
||||
<text class="dance-title">拉丁舞</text>
|
||||
<text class="dance-subtitle">STORE</text>
|
||||
</view>
|
||||
</view>
|
||||
<view bindtap="{{g}}" class="dance-item modern-dance">
|
||||
<view class="dance-content">
|
||||
<text class="dance-title">摩登舞</text>
|
||||
<text class="dance-subtitle">ACTIVITY</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bottom-nav">
|
||||
<view class="nav-item active">
|
||||
<text class="nav-text">首页</text>
|
||||
<view class="nav-underline"></view>
|
||||
</view>
|
||||
<view bindtap="{{h}}" class="nav-item">
|
||||
<text class="nav-text">舞蹈名词</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
1
pages/index/index.wxss
Normal file
1
pages/index/index.wxss
Normal file
@ -0,0 +1 @@
|
||||
.dance-container{background:linear-gradient(180deg,#2c2c54,#40407a);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;min-height:100vh}.status-bar{align-items:center;display:-webkit-flex;display:flex;justify-content:space-between;padding:60rpx 40rpx 20rpx}.status-bar .time{color:#fff;font-size:32rpx;font-weight:600}.status-bar .status-icons{align-items:center;display:-webkit-flex;display:flex}.status-bar .status-icons .signal-icon{color:#fff;font-size:28rpx}.banner-swiper{height:450rpx;margin-bottom:60rpx}.top-banner{height:100%;padding:40rpx;position:relative}.top-banner .banner-content{align-items:flex-start;display:-webkit-flex;display:flex;height:100%;justify-content:space-between}.top-banner .left-section{display:-webkit-flex;display:flex;flex-direction:column}.top-banner .left-section .main-title,.top-banner .left-section .sub-title{color:#fff;display:block;font-size:90rpx;font-weight:900;line-height:.9;margin-bottom:10rpx}.top-banner .right-section{align-items:flex-start;display:-webkit-flex;display:flex;position:relative}.top-banner .right-section .dance-emoji{font-size:100rpx;left:-60rpx;position:absolute;top:-20rpx;z-index:1}.top-banner .right-section .promo-card{border-radius:24rpx;box-shadow:0 12rpx 40rpx rgba(0,0,0,.15);color:#fff;padding:32rpx;position:relative;width:320rpx}.top-banner .right-section .promo-card .card-header{align-items:flex-start;display:-webkit-flex;display:flex;justify-content:space-between;margin-bottom:24rpx}.top-banner .right-section .promo-card .card-header .card-subtitle,.top-banner .right-section .promo-card .card-header .card-title{display:block;font-size:40rpx;font-weight:900;line-height:1}.top-banner .right-section .promo-card .card-header .balloon-icon,.top-banner .right-section .promo-card .card-header .music-icon,.top-banner .right-section .promo-card .card-header .trophy-icon{font-size:32rpx}.top-banner .right-section .promo-card .card-content{margin-bottom:24rpx}.top-banner .right-section .promo-card .card-content .card-info{display:block;font-size:24rpx;margin-bottom:4rpx;opacity:.9}.top-banner .right-section .promo-card .card-footer{align-items:center;display:-webkit-flex;display:flex;justify-content:space-between}.top-banner .right-section .promo-card .card-footer .discount-badge{backdrop-filter:blur(10rpx);background:hsla(0,0%,100%,.25);border-radius:12rpx;padding:12rpx 20rpx}.top-banner .right-section .promo-card .card-footer .discount-badge .badge-text{color:#fff;display:block;font-size:20rpx;font-weight:700;line-height:1.2}.top-banner .right-section .promo-card .card-footer .price-section{align-items:baseline;display:-webkit-flex;display:flex;gap:8rpx}.top-banner .right-section .promo-card .card-footer .price-section .discount-label{font-size:24rpx;font-weight:500}.top-banner .right-section .promo-card .card-footer .price-section .price-value{font-size:36rpx;font-weight:900}.top-banner .right-section .hot-class-card{background:linear-gradient(135deg,#ff6b6b,#ffa726)}.top-banner .right-section .event-card{background:linear-gradient(135deg,#4ecdc4,#44a08d)}.top-banner .right-section .new-arrival-card{background:linear-gradient(135deg,#667eea,#764ba2)}.dance-grid{margin-bottom:120rpx;padding:0 40rpx}.dance-grid .dance-row{display:-webkit-flex;display:flex;gap:30rpx;margin-bottom:30rpx}.dance-grid .dance-item{border-radius:20rpx;box-shadow:0 8rpx 32rpx rgba(0,0,0,.12),0 2rpx 8rpx rgba(0,0,0,.08);flex:1;overflow:hidden;padding:50rpx 30rpx;position:relative;text-align:center}.dance-grid .dance-item .dance-content{position:relative;z-index:2}.dance-grid .dance-item .dance-content .dance-title{color:#fff;display:block;font-size:32rpx;font-weight:700;margin-bottom:8rpx}.dance-grid .dance-item .dance-content .dance-subtitle{color:hsla(0,0%,100%,.8);font-size:22rpx;font-weight:500;letter-spacing:1rpx;opacity:.8}.dance-grid .dance-item:active{transform:scale(.96);transition:all .2s ease}.dance-grid .street-dance{background:linear-gradient(135deg,#ffeaa7,#fab1a0)}.dance-grid .ballet-dance{background:linear-gradient(135deg,#74b9ff,#0984e3)}.dance-grid .machine-dance{background:linear-gradient(135deg,#55efc4,#00b894)}.dance-grid .classical-dance{background:linear-gradient(135deg,#fdcb6e,#e17055)}.dance-grid .latin-dance{background:linear-gradient(135deg,#a29bfe,#6c5ce7)}.dance-grid .modern-dance{background:linear-gradient(135deg,#fd79a8,#e84393)}.bottom-nav{backdrop-filter:blur(20px);background:rgba(44,44,84,.95);border-top:1px solid hsla(0,0%,100%,.1);bottom:0;display:-webkit-flex;display:flex;left:0;padding:30rpx 40rpx;position:fixed;right:0}.bottom-nav .nav-item{flex:1;position:relative;text-align:center}.bottom-nav .nav-item .nav-text{color:hsla(0,0%,100%,.6);font-size:28rpx;font-weight:500}.bottom-nav .nav-item.active .nav-text{color:#ff6b9d;font-weight:700}.bottom-nav .nav-item.active .nav-underline{background:#ff6b9d;border-radius:2rpx;bottom:-15rpx;height:4rpx;left:50%;position:absolute;transform:translateX(-50%);width:50rpx}
|
||||
15
pages/ming/index.js
Normal file
15
pages/ming/index.js
Normal file
@ -0,0 +1,15 @@
|
||||
var common_vendor = require("../../common/vendor.js");var _sfc_main = {
|
||||
__name: "index",
|
||||
setup: function setup(__props) {
|
||||
var goHome = function goHome() {
|
||||
common_vendor.index.navigateTo({
|
||||
url: "/pages/index/index"
|
||||
});
|
||||
};
|
||||
return function (_ctx, _cache) {
|
||||
return {
|
||||
a: common_vendor.o(goHome)
|
||||
};
|
||||
};
|
||||
}
|
||||
};wx.createPage(_sfc_main);
|
||||
1
pages/ming/index.json
Normal file
1
pages/ming/index.json
Normal file
@ -0,0 +1 @@
|
||||
{"navigationBarTitleText":"舞蹈","usingComponents":{}}
|
||||
87
pages/ming/index.wxml
Normal file
87
pages/ming/index.wxml
Normal file
@ -0,0 +1,87 @@
|
||||
<view class="dance-terms-container">
|
||||
<scroll-view class="terms-scroll" scrollY="true" showScrollbar="false">
|
||||
<view class="terms-list">
|
||||
<view class="term-card ballet-card">
|
||||
<view class="term-header">
|
||||
<text class="term-title">芭蕾舞 - Plié(普利耶)</text>
|
||||
</view>
|
||||
<view class="term-content">
|
||||
<text class="term-description"> 意为弯曲,是芭蕾舞的基础动作之一,分为 Demi Plié(半蹲)和 Grand Plié(大蹲)。Demi Plié 是膝盖往脚尖的方向尽可能弯曲,脚跟不离地;Grand Plié 则是膝盖完全弯曲到大腿接近水平线的位置。第一、第二、第四、第五位置的 Grand Plié 脚跟会动自然上升而离地,第三位置 Grand Plié 的脚跟不提起且平踩在地面。 </text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="term-card ballet-card">
|
||||
<view class="term-header">
|
||||
<text class="term-title">芭蕾舞 - Battement Tendu(巴特芒汤迪)</text>
|
||||
</view>
|
||||
<view class="term-content">
|
||||
<text class="term-description"> 即靠合延伸,将活动脚在地板上滑行,往外到一个延伸、拉长的脚尖点地位置,可以向前、旁、后,脚尖不可离地,再用同样的方法擦地板回到本来的位置 </text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="term-card ballet-card">
|
||||
<view class="term-header">
|
||||
<text class="term-title">芭蕾舞 - Arabesque(阿拉贝斯克)</text>
|
||||
</view>
|
||||
<view class="term-content">
|
||||
<text class="term-description"> 迎风展翅舞姿,单腿直立,另一腿向后抬起,双臂伸展,形成优美的线条,是芭蕾舞中极具代表性的姿态。 </text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="term-card classical-card">
|
||||
<view class="term-header">
|
||||
<text class="term-title">中国古典舞 - 云手</text>
|
||||
</view>
|
||||
<view class="term-content">
|
||||
<text class="term-description"> 双手如向行云流水般连贯绕圆,以腰为轴,带动上肢运动,是中国古典舞中常见的手部动作,体现了中国古典舞圆融连贯的特点。 </text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="term-card classical-card">
|
||||
<view class="term-header">
|
||||
<text class="term-title">中国古典舞 - 卧鱼</text>
|
||||
</view>
|
||||
<view class="term-content">
|
||||
<text class="term-description"> 是中国古典舞中的一个优美动作,单腿跪地,身体下俯,常用于表现温婉、柔美的情感或特定的舞蹈情境。 </text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="term-card latin-card">
|
||||
<view class="term-header">
|
||||
<text class="term-title">拉丁舞 - 伦巴的"8字胯"</text>
|
||||
</view>
|
||||
<view class="term-content">
|
||||
<text class="term-description"> 通过腰腹肌肉控制,让胯部依次向前后左右四个方向摆动,形成"∞"字形轨迹,缓慢且富有韧性,是伦巴舞的核心胯部动作。 </text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="term-card latin-card">
|
||||
<view class="term-header">
|
||||
<text class="term-title">拉丁舞 - 桑巴的弹跳步</text>
|
||||
</view>
|
||||
<view class="term-content">
|
||||
<text class="term-description"> 膝盖快速屈伸时,胯部随身体起伏快自然向两侧摆动,如同波浪般连贯,是桑巴舞的标志性动作,展现出桑巴的热烈与活力。 </text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="term-card modern-card">
|
||||
<view class="term-header">
|
||||
<text class="term-title">摩登舞 - 探戈的颤步</text>
|
||||
</view>
|
||||
<view class="term-content">
|
||||
<text class="term-description"> 探戈舞中,颤步是其重要动作之一,动作极具有力,脚尖他间的停顿来体现来的庄重与张力,通常与其他动作如交叉步等配合使用。 </text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="term-card modern-card">
|
||||
<view class="term-header">
|
||||
<text class="term-title">摩登舞 - 华尔兹的旋转与升降</text>
|
||||
</view>
|
||||
<view class="term-content">
|
||||
<text class="term-description"> 每一步伴随身体轻微起伏,升时提踵、降时落踵,旋转流畅且富有韵律,舞步多为弧形轨迹,是华尔兹舞优雅风格的重要体现。 </text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="bottom-nav">
|
||||
<view bindtap="{{a}}" class="nav-item">
|
||||
<text class="nav-text">首页</text>
|
||||
</view>
|
||||
<view class="nav-item active">
|
||||
<text class="nav-text">舞蹈名词</text>
|
||||
<view class="nav-underline"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
1
pages/ming/index.wxss
Normal file
1
pages/ming/index.wxss
Normal file
@ -0,0 +1 @@
|
||||
page{background:#2c2c54}.dance-terms-container{background:linear-gradient(180deg,#2c2c54,#40407a);font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;min-height:100vh}.terms-scroll{height:calc(100vh - 120rpx);padding:40rpx 30rpx 0}.terms-list{padding-bottom:120rpx}.term-card{backdrop-filter:blur(20rpx);background:hsla(0,0%,100%,.1);border:1px solid hsla(0,0%,100%,.2);border-radius:20rpx;box-sizing:border-box;margin-bottom:24rpx;padding:24rpx 28rpx;width:calc(100% - 60rpx)}.term-card .term-header{margin-bottom:16rpx}.term-card .term-header .term-title{word-wrap:break-word;color:#fff;font-size:30rpx;font-weight:700;line-height:1.4;word-break:break-all}.term-card .term-content .term-description{word-wrap:break-word;color:hsla(0,0%,100%,.9);font-size:26rpx;line-height:1.6;text-align:justify;word-break:break-all}.ballet-card{border-left:6rpx solid #ff6b9d}.ballet-card .term-title{color:#ff6b9d}.classical-card{border-left:6rpx solid #ffa726}.classical-card .term-title{color:#ffa726}.latin-card{border-left:6rpx solid #ab47bc}.latin-card .term-title{color:#ab47bc}.modern-card{border-left:6rpx solid #42a5f5}.modern-card .term-title{color:#42a5f5}.bottom-nav{backdrop-filter:blur(20px);background:rgba(44,44,84,.95);border-top:1px solid hsla(0,0%,100%,.1);bottom:0;display:-webkit-flex;display:flex;left:0;padding:30rpx 40rpx;position:fixed;right:0}.bottom-nav .nav-item{flex:1;position:relative;text-align:center}.bottom-nav .nav-item .nav-text{color:hsla(0,0%,100%,.6);font-size:28rpx;font-weight:500}.bottom-nav .nav-item.active .nav-text{color:#ff6b9d;font-weight:700}.bottom-nav .nav-item.active .nav-underline{background:#ff6b9d;border-radius:2rpx;bottom:-15rpx;height:4rpx;left:50%;position:absolute;transform:translateX(-50%);width:50rpx}
|
||||
39
project.config.json
Normal file
39
project.config.json
Normal file
@ -0,0 +1,39 @@
|
||||
{
|
||||
"miniprogramRoot": "",
|
||||
"__compileDebugInfo__": {
|
||||
"useSummer": true
|
||||
},
|
||||
"appid": "wx26ad074017e1e63f",
|
||||
"libVersion": "3.9.2",
|
||||
"setting": {
|
||||
"es6": false,
|
||||
"postcss": false,
|
||||
"compileWorklet": false,
|
||||
"minified": false,
|
||||
"uglifyFileName": false,
|
||||
"uploadWithSourceMap": true,
|
||||
"enhance": false,
|
||||
"packNpmManually": false,
|
||||
"packNpmRelationList": [],
|
||||
"minifyWXSS": true,
|
||||
"minifyWXML": true,
|
||||
"localPlugins": false,
|
||||
"disableUseStrict": false,
|
||||
"useCompilerPlugins": false,
|
||||
"condition": false,
|
||||
"swc": false,
|
||||
"disableSWC": true,
|
||||
"babelSetting": {
|
||||
"ignore": [],
|
||||
"disablePlugins": [],
|
||||
"outputPath": ""
|
||||
}
|
||||
},
|
||||
"compileType": "miniprogram",
|
||||
"simulatorPluginLibVersion": {},
|
||||
"packOptions": {
|
||||
"ignore": [],
|
||||
"include": []
|
||||
},
|
||||
"editorSetting": {}
|
||||
}
|
||||
43
project.private.config.json
Normal file
43
project.private.config.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
|
||||
"projectname": "%E8%88%9E%E8%B9%88",
|
||||
"setting": {
|
||||
"compileHotReLoad": true,
|
||||
"urlCheck": false,
|
||||
"coverView": false,
|
||||
"lazyloadPlaceholderEnable": false,
|
||||
"skylineRenderEnable": false,
|
||||
"preloadBackgroundData": false,
|
||||
"autoAudits": false,
|
||||
"useApiHook": true,
|
||||
"useApiHostProcess": true,
|
||||
"showShadowRootInWxmlPanel": false,
|
||||
"useStaticServer": false,
|
||||
"useLanDebug": false,
|
||||
"showES6CompileOption": false,
|
||||
"checkInvalidKey": true,
|
||||
"ignoreDevUnusedFiles": true,
|
||||
"bigPackageSizeSupport": true
|
||||
},
|
||||
"condition": {
|
||||
"miniprogram": {
|
||||
"list": [
|
||||
{
|
||||
"name": "pages/contact/index",
|
||||
"pathName": "pages/contact/index",
|
||||
"query": "url=1",
|
||||
"scene": null,
|
||||
"launchMode": "default"
|
||||
},
|
||||
{
|
||||
"name": "pages/index/detail",
|
||||
"pathName": "pages/index/detail",
|
||||
"query": "url=1&app_id=wx26ad074017e1e63f",
|
||||
"launchMode": "default",
|
||||
"scene": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"libVersion": "3.9.2"
|
||||
}
|
||||
BIN
static/contact.png
Normal file
BIN
static/contact.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
BIN
static/kefu.png
Normal file
BIN
static/kefu.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
BIN
static/logo.png
Normal file
BIN
static/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
0
static/service-avatar.jpg
Normal file
0
static/service-avatar.jpg
Normal file
BIN
static/upload.png
Normal file
BIN
static/upload.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
0
static/user-avatar.jpg
Normal file
0
static/user-avatar.jpg
Normal file
BIN
static/user.png
Normal file
BIN
static/user.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
Loading…
x
Reference in New Issue
Block a user