diff --git a/components/ActivateAgentPopup.vue b/components/ActivateAgentPopup.vue
index da2445a..052cc85 100644
--- a/components/ActivateAgentPopup.vue
+++ b/components/ActivateAgentPopup.vue
@@ -73,13 +73,11 @@ export default {
// 处理AGENT点击
handleAgentClick(agent) {
- console.log("点击了AGENT:", agent);
-
if (agent.status ==1) {
// 激活逻辑
- uni.navigateTo({
- url: "/pages/agent/index?id="+agent.agentId
- });
+ uni.navigateTo({
+ url: "/subPackages/other/evita?id="+agent.agentId
+ });
} else {
uni.navigateTo({
url:"/subPackages/equityGoods/detail?id="+agent.vos[0].benefitPackageId
diff --git a/components/DynamicIsland.vue b/components/DynamicIsland.vue
index 78c3848..0fa0af6 100644
--- a/components/DynamicIsland.vue
+++ b/components/DynamicIsland.vue
@@ -25,7 +25,7 @@
EVITA
- DES介绍 >>
+ DES介绍 >>
DES广播 >>
@@ -363,7 +363,7 @@
// "https://des.js-dyyj.com/dist/#/",
// });
uni.navigateTo({
- url:'/subPackages/other/evita'
+ url:'/subPackages/other/evita?id=1'
})
},
diff --git a/components/GPT/.DS_Store b/components/GPT/.DS_Store
new file mode 100644
index 0000000..ec30373
Binary files /dev/null and b/components/GPT/.DS_Store differ
diff --git a/components/GPT/components/client-chat.vue b/components/GPT/components/client-chat.vue
new file mode 100644
index 0000000..e689d03
--- /dev/null
+++ b/components/GPT/components/client-chat.vue
@@ -0,0 +1,414 @@
+
+
+
+
+
+ {{ pop.id }}.{{ pop.name }}
+
+
+
+
+
+
+
+ {{ moment(new Date(String(item.timestamp).length === 10 ? item.timestamp * 1000 :
+ Number(item.timestamp))).format('MM-DD HH:mm') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 正在思考中
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/GPT/components/pending.vue b/components/GPT/components/pending.vue
new file mode 100644
index 0000000..d899534
--- /dev/null
+++ b/components/GPT/components/pending.vue
@@ -0,0 +1,232 @@
+
+
+ {{title}}
+
+
+
+
+
+
diff --git a/components/GPT/index.vue b/components/GPT/index.vue
new file mode 100644
index 0000000..102d15f
--- /dev/null
+++ b/components/GPT/index.vue
@@ -0,0 +1,799 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{robotObj.name}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{n.content}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 按住 说话
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/GPT/utils/ClientData.js b/components/GPT/utils/ClientData.js
new file mode 100644
index 0000000..30e6428
--- /dev/null
+++ b/components/GPT/utils/ClientData.js
@@ -0,0 +1,347 @@
+import Vue from "vue";
+import { MESSAGE_TYPE } from "./chat_constant";
+import { getQueryVariable, generateRequestId, arrayUnique } from "./util";
+import { v4 as uuidv4 } from "uuid";
+import GLOBAL from "./global";
+import Observer from "./observer";
+const $e = Observer;
+// const $s = this.$s;
+
+let cache = null; // 缓存
+let timeoutTasks = {}; // 超时任务管理
+const msgSendTimeout = 2 * 60 * 1000; // 发送消息超时ms,此处超时默认为2min
+
+class ClientData {
+ constructor(option) {
+ cache = {
+ session_id: "", // 会话ID
+ configInfo: null, // 配置信息
+ chatsContent: [], // 会话聊天内容
+ systemEvents: [], // 系统事件栈
+ transferInfo: {
+ transferStatus: false,
+ transferAvatar: "",
+ }, // 当前转人工状态
+ };
+
+ this.$s = null
+
+ }
+ init() {
+ // 获取基础配置
+ this.queryConfigInfo();
+ }
+ setAttr(options) {
+ this.$s =options.socketObj
+ }
+ // 获取基础配置
+ async queryConfigInfo() {
+ try {
+ const seatBizId = ''// getQueryVariable("seat_biz_id");
+ console.log("seatBizId", seatBizId);
+ const sessionInfo = await this.createSession();
+ console.log("createsession, res", sessionInfo);
+ if (sessionInfo.code === 0) {
+ cache.seat_biz_id = seatBizId;
+ cache.session_id = sessionInfo.data.session_id;
+ } else {
+ uni.showModal({
+ title: "获取会话ID失败,请重试",
+ icon: "none",
+ });
+ }
+ // 接着获取机器人基础信息
+ const botInfo = {
+ code: 0,
+ data: {
+ name: "测试机器人",
+ avatar:
+ "https://qbot-1251316161.cos.ap-nanjing.myqcloud.com/avatar.png",
+ is_available: true,
+ bot_biz_id: "1664519736704069632",
+ },
+ };
+ if (botInfo.data) {
+ cache.configInfo = botInfo.data;
+ cache.configInfo.session_id = sessionInfo.data.session_id;
+ $e.$emit("client_configChange", cache.configInfo);
+ } else {
+ uni.showModal({
+ title: "获取机器人信息失败",
+ icon: "none",
+ });
+ }
+ } catch (e) {
+ console.log("获取机器人信息失败", e);
+ uni.showModal({
+ title: "获取会话信息失败,请刷新页面重试",
+ icon: "none",
+ });
+ }
+ }
+ async createSession() {
+ const session_id = uuidv4();
+ return { code: 0, data: { session_id: session_id } };
+ }
+ // 消息上行事件(用户端)
+ triggerSendMsg =async (msg, type='text', status= true) => {
+ console.log("[triggerSendMsg]", msg, wx);
+ if (!cache.configInfo || !cache.configInfo.session_id) {
+ await this.queryConfigInfo();
+ }
+ const requestId = generateRequestId();
+ const params = {
+ request_id: requestId,
+ session_id: cache.configInfo ? cache.configInfo.session_id : 0,
+ is_msg_status: status
+ };
+ if (type == "text") {
+ params.content = msg;
+ } else if (type == "img") {
+ params.content = ``;
+ params.realContent = msg;
+ }
+
+ this.$s.emit("send", params, type);
+ }
+
+ // 监听token用量和详情事件
+ listenTokenStat() {
+ this.$s.on("token_stat", (data) => {
+ $e.$emit("token_state_change", data);
+ if (data.session_id !== cache.session_id) return; // 若新消息不属于当前机器人时,则不做处理
+ let loadingMsg = cache.chatsContent.find((el) => el.loading_message);
+ let loadingText = "思考中";
+ if (loadingMsg) {
+ if (data.procedures && data.procedures.length > 0) {
+ loadingText =
+ data.procedures[data.procedures.length - 1].title || "思考中";
+ }
+ let currentList = cache.chatsContent;
+ currentList.forEach((el) => {
+ if (el.loading_message) {
+ el.text = loadingText;
+ el.record_id = data.record_id;
+ el.tokens_msg = data;
+ // 只有标准模式加这个
+ if (GLOBAL.webimToken[0].pattern === "standard") {
+ el.is_final = false;
+ }
+ }
+ });
+ $e.$emit("client_msgContentChange", {
+ chatsContent: cache.chatsContent,
+ type: MESSAGE_TYPE.ANSWER,
+ });
+ } else {
+ let findedMsg = cache.chatsContent.find(
+ (el) => el.record_id === data.record_id
+ );
+ if (!findedMsg) return;
+ findedMsg.tokens_msg = data;
+
+ $e.$emit("client_msgContentChange", {
+ chatsContent: cache.chatsContent,
+ type: MESSAGE_TYPE.ANSWER,
+ });
+ }
+ });
+ }
+
+ // 组装消息队列数据
+ // 问题确认消息:根据request_id关联覆盖(服务端收到问题后的确认消息)
+ // 答案消息:倒序遍历插入(服务端答案消息)
+ assembleMsgContent(msgList, type) {
+ console.log("assembleMsgContent", msgList, type);
+ let newMsg = msgList;
+
+ if (type === MESSAGE_TYPE.QUESTION) {
+ // 发送的问题消息由前端临时插入消息队列
+ cache.chatsContent.push(newMsg);
+ } else if (type === MESSAGE_TYPE.ANSWER) {
+ if (cache.chatsContent.length < 1) {
+ cache.chatsContent.push(newMsg);
+ } else {
+ let currentList = cache.chatsContent;
+
+ timeoutTasks[newMsg.request_id] &&
+ clearTimeout(timeoutTasks[newMsg.request_id]);
+
+ if (currentList.length === 2 && newMsg.can_rating) {
+ currentList[0].transferRobot = true;
+ }
+ if (newMsg.transfer && newMsg.loading_message) {
+ currentList.pop();
+ currentList[currentList.length - 1].loading_message = false;
+ currentList[currentList.length - 1] = {
+ ...newMsg,
+ ...currentList[currentList.length - 1],
+ transfer: true,
+ transferRobot: false,
+ };
+ } else {
+ for (let i = currentList.length - 1; i >= 0; i--) {
+ const { transfer, quit, transferRobot } = currentList[i];
+ let tmp = {
+ ...newMsg,
+ transfer,
+ quit,
+ transferRobot,
+ };
+ // 保留tokens_msg,防止覆盖
+ if (currentList[i].tokens_msg) {
+ tmp = { ...tmp, tokens_msg: currentList[i].tokens_msg };
+ }
+ // 保留thought 放置被覆盖
+ if (currentList[i].agent_thought) {
+ tmp = { ...tmp, agent_thought: currentList[i].agent_thought };
+ }
+ // 保留reference
+ if (currentList[i].references) {
+ tmp = { ...tmp, references: currentList[i].references };
+ }
+ // 答案消息流式输出覆盖(record_id)
+ if (newMsg.record_id === currentList[i].record_id) {
+ currentList[i] = tmp;
+ break;
+ }
+ // 服务端问题消息确认数据,覆盖前端插入的临时问题消息数据(request_id匹配 & 自己发出的问题消息)
+ if (
+ newMsg.request_id &&
+ newMsg.request_id === currentList[i].request_id &&
+ newMsg.is_from_self
+ ) {
+ newMsg.is_loading = false; // 服务端确认收到问题消息,则去除”发送中“状态
+ currentList[i] = tmp;
+ // 非人工状态时, 并且用户发送的不是敏感消息。插入临时[正在思考中...]消息
+ if (!newMsg.is_evil && !cache.transferInfo.transferStatus) {
+ currentList.push({
+ loading_message: true,
+ is_from_self: false,
+ content: "",
+ from_avatar: cache.configInfo.avatar,
+ timestamp: Number(currentList[i].timestamp), // 精确到秒
+ });
+ }
+ break;
+ }
+ // 插入最新答案消息
+ if (Number(newMsg.timestamp) >= Number(currentList[i].timestamp)) {
+ if (currentList[i].loading_message) {
+ // 删除原来的[正在思考中...]消息
+ currentList[currentList.length - 1] = newMsg;
+ } else {
+ currentList.splice(i + 1, 0, newMsg);
+ }
+ break;
+ }
+ if (
+ i === 0 &&
+ Number(newMsg.timestamp) < Number(currentList[i].timestamp)
+ ) {
+ currentList.splice(0, 0, newMsg);
+ }
+ }
+ }
+ }
+ } else if (type === MESSAGE_TYPE.HISTORY) {
+ let currentList = cache.chatsContent;
+ // 历史数据打上标签,无需展示”重新生成“和”停止生成“操作
+ msgList = msgList.map((r) => {
+ return {
+ ...r,
+ is_history: true,
+ is_final: true,
+ };
+ });
+
+ if (currentList.length === 0) {
+ // 若消息队列为空(用户端,初始拉取历史记录,用做判断欢迎页展示场景)
+ cache.chatsContent = [].concat(msgList);
+ } else {
+ // 若消息队列不为空
+ let oldMsgCurrent = currentList[0];
+ let newMsgHistory = msgList[msgList.length - 1];
+
+ // 将历史数据拼装到消息队列中(按照时间戳重排数据)
+ if (Number(newMsgHistory.timestamp) < Number(oldMsgCurrent.timestamp)) {
+ cache.chatsContent = [].concat(msgList).concat(cache.chatsContent);
+ } else {
+ msgList.reverse().forEach((msg) => {
+ for (let i = 0; i < cache.chatsContent.length; i++) {
+ if (msg.record_id === cache.chatsContent[i].record_id) {
+ // 重复覆盖
+ cache.chatsContent[i] = msg;
+ break;
+ } else if (
+ Number(msg.timestamp) <= Number(cache.chatsContent[i].timestamp)
+ ) {
+ cache.chatsContent.splice(i, 0, msg);
+ break;
+ } else if (
+ i === cache.chatsContent.length - 1 &&
+ Number(msg.timestamp) > Number(cache.chatsContent[i].timestamp)
+ ) {
+ cache.chatsContent.splice(i + 1, 0, msg);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ // 消息去重。同一record_id取最新,同时保留消息最早的时间戳
+ cache.chatsContent = arrayUnique(
+ cache.chatsContent,
+ "record_id",
+ "timestamp"
+ );
+
+ // 消息队列变更通知事件
+ $e.$emit("client_msgContentChange", {
+ chatsContent: cache.chatsContent,
+ type,
+ });
+ }
+ // 修改指定msgId的消息内容
+ modifyMsgContent(msgId) {
+ const findedMsg = this.getMsgById(msgId);
+
+ if (findedMsg) {
+ findedMsg.is_final = true;
+ findedMsg.content = findedMsg.content.concat(
+ `| 已停止生成`
+ );
+
+ $e.$emit("client_msgContentChange", {
+ chatsContent: cache.chatsContent,
+ type: MESSAGE_TYPE.STOP, // ”停止生成“事件
+ });
+ }
+ }
+ // 根据msgId获取消息
+ getMsgById(msgId) {
+ const findedMsg = cache.chatsContent.find((r) => r.record_id === msgId);
+ return findedMsg;
+ }
+ // 根据msgId获取其关联问题消息
+ getQmsgById(msgId) {
+ let findedQmsg = null;
+ const findedMsg = this.getMsgById(msgId);
+
+ if (findedMsg) {
+ findedQmsg = cache.chatsContent.find(
+ (r) => r.record_id === findedMsg.related_record_id
+ );
+ }
+
+ return findedQmsg;
+ }
+ releaseCache() {}
+ destroy() {
+ // be careful to clear the cache to avoid errors
+ this.releaseCache();
+ }
+}
+
+export default ClientData;
diff --git a/components/GPT/utils/EventHub.js b/components/GPT/utils/EventHub.js
new file mode 100644
index 0000000..c289e6a
--- /dev/null
+++ b/components/GPT/utils/EventHub.js
@@ -0,0 +1,50 @@
+import Vue from 'vue';
+
+class EventHub {
+ constructor (vm) {
+ this.vm = vm;
+ this.curVm = null;
+ this.events = {};
+ this.eventMapUid = {};
+ }
+ $register (vm) {
+ this.curVm = vm;
+ }
+ setEventMapUid (uid, type) {
+ if (!this.eventMapUid[uid]) {
+ this.eventMapUid[uid] = [];
+ }
+ this.eventMapUid[uid].push(type);
+ }
+ $on (type, fn) {
+ if (!this.events[type]) {
+ this.events[type] = [];
+ }
+ this.events[type].push(fn);
+ if (this.curVm instanceof this.vm) {
+ this.setEventMapUid(this.curVm._uid, type);
+ }
+ }
+ $emit (type, ...args) {
+ if (this.events[type]) {
+ this.events[type].forEach(fn => fn(...args));
+ }
+ }
+ $off (type, fn) {
+ if (fn && this.events[type]) {
+ const index = this.events[type].findIndex(f => f === fn);
+ if (index !== -1) {
+ this.events[type].splice(index, 1);
+ }
+ return;
+ }
+ delete this.events[type];
+ }
+ $offAll (uid) {
+ const curAllTypes = this.eventMapUid[uid] || [];
+ curAllTypes.forEach(type => this.$off(type));
+ delete this.eventMapUid[uid];
+ }
+}
+
+export default new EventHub(Vue);;
diff --git a/components/GPT/utils/chat_constant.js b/components/GPT/utils/chat_constant.js
new file mode 100644
index 0000000..13b3b80
--- /dev/null
+++ b/components/GPT/utils/chat_constant.js
@@ -0,0 +1,12 @@
+// type: Q-问题,A-答案,H-历史消息,S-停止生成,C-结束会话,T-转接会话,R-参考来源,F-点赞/点踩回执
+export const MESSAGE_TYPE = {
+ QUESTION: 'Q',
+ ANSWER: 'A',
+ HISTORY: 'H',
+ STOP: 'S',
+ CLOSE: 'C',
+ TRANSFER: 'T',
+ REFERENCE: 'R',
+ FEEDBACK: 'F',
+ WORKBENCH_HISTORY: 'WH'
+};
diff --git a/components/GPT/utils/global.js b/components/GPT/utils/global.js
new file mode 100644
index 0000000..b68e590
--- /dev/null
+++ b/components/GPT/utils/global.js
@@ -0,0 +1,8 @@
+wx.GLOBE = {
+ webimToken: [],
+ SOCKET: null,
+}
+
+
+
+export default wx.GLOBE
\ No newline at end of file
diff --git a/components/GPT/utils/message.js b/components/GPT/utils/message.js
new file mode 100644
index 0000000..4eb49ae
--- /dev/null
+++ b/components/GPT/utils/message.js
@@ -0,0 +1,56 @@
+/**
+ * !插入数据
+ * @param roomId
+ * @param sourceId
+ * @param orderId
+ * @param type
+ * @param fileId
+ * @param txt
+ * @param time
+ * @param userId
+ * @param nickName
+ * @param sendOrReceive
+ * @param address
+ */
+export const setMsgData = data => {
+ console.log('setMsgData', data)
+ const resData = data
+ const session_id = resData.chatId // 群id
+
+ let msgData = wx.getStorageSync('imMsgData') || {}
+ // * 插入群数据
+ if (msgData[session_id]) {
+ if (resData.timestamp > msgData[session_id].timestamp) {
+ msgData[session_id].timestamp = resData.timestamp
+ }
+ msgData[session_id].listMsg.push(resData)
+ } else {
+ msgData[session_id] = {
+ listMsg: [resData],
+ timestamp: resData.timestamp,
+ session_id: resData.session_id,
+ }
+ }
+ wx.setStorageSync('imMsgData', msgData)
+ return resData
+}
+
+
+// ! 获取群消息
+export const getHistroyMsg = id => {
+ let msgData = wx.getStorageSync('imMsgData') || {}
+ let msgList = []
+ if (msgData[id]) {
+ const data = msgData[id]
+ // *处理历史消息并按时间排序
+ const compare = property => {
+ return function(a, b) {
+ var value1 = a[property]
+ var value2 = b[property]
+ return value1 - value2
+ }
+ }
+ msgList = data.listMsg.sort(compare('time'))
+ }
+ return { msgList }
+}
diff --git a/components/GPT/utils/observer.js b/components/GPT/utils/observer.js
new file mode 100644
index 0000000..20390e7
--- /dev/null
+++ b/components/GPT/utils/observer.js
@@ -0,0 +1,45 @@
+import GLOBAL from './global';
+class Observer {
+ constructor() {
+ this._event = {}
+ }
+ $on(eventName, handler) {
+ if (this._event[eventName]) {
+ this._event[eventName].push(handler)
+ } else {
+ this._event[eventName] = [handler]
+ }
+ }
+
+ $emit(eventName) {
+ let events = this._event[eventName]
+ let otherArgs = Array.prototype.slice.call(arguments, 1)
+ let that = this
+ if (events) {
+ events.forEach(event => {
+ event.apply(that, otherArgs)
+ })
+ }
+ }
+ $off(eventName, handler) {
+ let events = this._event[eventName]
+ if (events) {
+ this._event[eventName] = events.filter(event => {
+ return event !== handler
+ })
+ }
+ }
+ $once(eventName, handler) {
+ let that = this
+ function func() {
+ let args = Array.prototype.slice.call(arguments, 0)
+ handler.apply(that, args)
+ this.off(eventName, func)
+ }
+ this.on(eventName, func)
+ }
+}
+if (!GLOBAL.observer) {
+ GLOBAL.observer = new Observer()
+}
+export default GLOBAL.observer
diff --git a/components/GPT/utils/socket.js b/components/GPT/utils/socket.js
new file mode 100644
index 0000000..05b7d79
--- /dev/null
+++ b/components/GPT/utils/socket.js
@@ -0,0 +1,283 @@
+import Vue from "vue";
+import GLOBAL_OBJ from "./global";
+import "./EventHub";
+import { setMsgData } from "./message";
+// 心跳间隔
+const HEART_BEAT_TIME = 20000;
+// 心跳最大失败次数(超过此次数重连)
+const HEART_BEAT_FAIL_NUM = 1;
+// 重连间隔
+const RECONNECT_TIME = 1000;
+
+export default class Socket {
+ constructor(option) {
+ this.socket = null;
+ this._options = option;
+ this.timeoutObj = null;
+ this.robotObj = {};
+ this.selfCloseStatus = false
+ this.reconnectLock = false
+ console.log("Socket init", GLOBAL_OBJ);
+ }
+ getToken() {
+ return new Promise((resolve, reject) => {
+ uni.request({
+ method: "GET",
+ dataType: "json",
+ // url: `http://192.168.124.118:8083/xcx/framework/agent/${this._options.agentId}`,
+ url: `https://des.js-dyyj.com/getDemoToken?id=${this._options.agentId}`,
+ success: (res) => {
+ console.log("请求token成功", res);
+ resolve(res);
+ },
+ fail: (err) => {
+ wx.showToast({
+ title: "创建失败",
+ icon: "none",
+ });
+ console.log("请求token失败", err);
+ reject()
+ },
+ });
+ });
+ }
+ async init() {
+ return this.createSocket();
+ }
+ async createSocket(options) {
+ return new Promise(async (resolve, reject) => {
+ const origin = "wss://wss.lke.cloud.tencent.com";
+ let path = "/v1/qbot/chat/conn/";
+ let initSocket = 1;
+ let mainToken
+ const res = await this.getToken();
+ if (
+ res &&
+ res.data &&
+ res.data.apiResponse &&
+ res.data.apiResponse.Token
+ ) {
+ mainToken = res.data.apiResponse.Token;
+ }
+ // 机器人信息
+ this.robotObj = res.data.requestInfo;
+ console.log("获取token:", mainToken);
+
+ // 建立连接
+ const socket = wx.connectSocket({
+ url: `${origin}${path}?EIO=4&transport=websocket`,
+ success: (e) => {
+ console.log("创建链接成功", e, socket);
+ },
+ complete: (e) => {
+ console.log("socket - complete", e);
+
+ },
+ });
+ this.socket = socket;
+ GLOBAL_OBJ.SOCKET = this;
+
+ let systemEventEmit = (eventName, data) => {
+ Vue.prototype.$eventHub.$emit(eventName, data);
+ };
+
+ socket.onOpen((e) => {
+ // 监听发送
+ if (initSocket === 1) {
+ const token = mainToken || "";
+ if (token) {
+ // cb({ token: token });
+ this.send({
+ data:
+ "40" +
+ JSON.stringify({
+ token: token,
+ }),
+ });
+ } else {
+ // cb({ token: '' });
+ this.send({
+ data: JSON.stringify({
+ token: "",
+ }),
+ });
+ }
+ initSocket++;
+ } else {
+ const token = mainToken || "";
+ // cb({ token: token });
+ this.send({
+ data: JSON.stringify({
+ token: token,
+ }),
+ });
+ initSocket++;
+ }
+
+ options && options.complete && options.complete()
+ });
+
+ socket.onMessage((e) => {
+ // console.log("socket.onMessage", e);
+ const { data } = e;
+ if (data == 2) {
+ // 触发浪涌
+ this.send({
+ data: 3,
+ });
+ }
+
+ const params = this.getMsgData(data);
+ const { type } = params ?? {};
+ this.on(type, params);
+ if (params && params.type === "reply" && !params.is_from_self) {
+ // 回复消息
+ this._options.onMessage && this._options.onMessage(params);
+ }
+ const num = "" + data.substring(0, 2);
+ if (num == "40") {
+ resolve();
+ }
+
+ this.createInter();
+ });
+ // 失败
+ socket.onError((e) => {
+ console.log("websocket error 长链接报错", e);
+ // 失败重建
+ this.doConnectTimeout();
+ //
+ });
+ // 关闭
+ socket.onClose((e) => {
+ console.log("websocket close 长链接关闭", e);
+ this.connectSocketTimeOut && clearTimeout(this.connectSocketTimeOut);
+ //非自动关闭重连
+ if (e.code == 1006) {
+ this.doConnectTimeout();
+ }
+ });
+ });
+ }
+
+ doConnectTimeout() {
+ // 重连一次
+ if (!this.reconnectLock) {
+ this.reconnectLock = true;
+ this.connectSocketTimeOut = setTimeout(() => {
+ this.createSocket({
+ complete: function (res) {
+ this.reconnectLock = false;
+ },
+ });
+ }, RECONNECT_TIME);
+ }
+ }
+
+ onConnect(e) {
+ console.log("websocket connect", e);
+ }
+
+ send(e, t) {
+ this.socket && this.socket.send(e);
+ this.createInter();
+ }
+
+ getMsgData(e) {
+ if (e && typeof e == "string") {
+ const status = e.indexOf("42");
+ const index = e.indexOf("[");
+ if (status > -1 && index > -1) {
+ const txt = e.substring(index);
+ const item = JSON.parse(txt);
+ const [type, obj] = item;
+ const payload = obj.payload ? obj.payload : {};
+ const params = {
+ chatId: this._options.agentId,
+ type,
+ contentType: "text", //默认文字
+ timestamp: new Date().getTime(),
+ ...payload,
+ };
+ // 缓存聊天记录
+ return params;
+ }
+ }
+ return null;
+ }
+
+ emit(type, params, contentType) {
+ console.log("emit", type, params);
+ const data = {
+ payload: params,
+ };
+ switch (type) {
+ case "send":
+ // 发送消息
+ const socketParams = { data: "42" + JSON.stringify(["send", data]) };
+ this.send(socketParams, contentType);
+
+ console.log(params.request_id + '发送内容', data)
+ if (!params.is_msg_status) {
+ // 不写入缓存中
+ return;
+ }
+ const msgParams = {
+ chatId: this._options.agentId,
+ contentType,
+ type,
+ timestamp: new Date().getTime(),
+ ...params,
+ content: params.realContent ? params.realContent : params.content,
+ };
+ msgParams && setMsgData(msgParams);
+
+ break;
+ }
+ }
+ // 监听
+ on(type, params) {
+ switch (type) {
+ case "reply":
+ // 回复结束
+ const tmpParams = {
+ ...params,
+ name: this.robotObj.name,
+ headImage: this.robotObj.headImage,
+ };
+ if (
+ params &&
+ params.type === "reply" &&
+ !params.is_from_self &&
+ params.can_rating
+ ) {
+ // 回复消息
+ this._options.onMessage && this._options.onMessage(tmpParams);
+ }
+
+ if (!params.is_from_self && params.is_final) {
+ // 回复结束 写入缓存
+ setMsgData(tmpParams);
+ }
+ // 回复
+ break;
+ }
+ }
+
+ // 关闭socket
+ destroy() {
+ if (this.socket && this.socket.readyState == 1) {
+ this.socket && this.socket.close();
+ this.socket = null;
+ }
+ }
+
+ createInter() {
+ if (this.timeoutObj) {
+ clearTimeout(this.timeoutObj);
+ }
+ this.timeoutObj = setTimeout(() => {
+ this.socket && this.socket.send && this.socket.send({ data: 3 });
+ }, HEART_BEAT_TIME);
+ }
+}
diff --git a/components/GPT/utils/util.js b/components/GPT/utils/util.js
new file mode 100644
index 0000000..942e0c8
--- /dev/null
+++ b/components/GPT/utils/util.js
@@ -0,0 +1,119 @@
+/**
+ * 获取 location hash 参数
+ * @param {string} variable 参数名
+ * @returns {string} 参数值
+ */
+export const getQueryVariable = (variable) => {
+ const query = window.location.hash.split('?');
+
+ if (query.length < 2) {
+ return '';
+ }
+
+ const vars = query[1].split('&');
+
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
+ for (let i = 0; i < vars.length; i++) {
+ const pair = vars[i].split('=');
+ if (pair[0] === variable) {
+ return decodeURI(pair[1]);
+ }
+ }
+ return '';
+};
+
+/**
+ * 滚动至指定dom底部
+ */
+export const scrollToBottom = (sDom, sTop) => {
+ if (!sDom) return;
+ sDom.scrollTo({
+ top: sTop
+ // behavior: 'smooth'
+ });
+};
+
+/**
+ * 数组去重
+ */
+export const arrayUnique = (arr, replaceKey, holdKey) => {
+ let temp = {};
+
+ return arr.reduce((prev, cur) => {
+ if (!temp[cur[replaceKey]]) {
+ temp[cur[replaceKey]] = {index: prev.length};
+ prev.push(cur);
+ } else {
+ const oldItem = temp[cur[replaceKey]];
+ cur[holdKey] = oldItem[holdKey];
+ prev.splice(oldItem['index'], 1, cur);
+ }
+
+ return prev;
+ }, []);
+};
+
+export const generateRequestId = (length = 10) => {
+ const data =
+ ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
+ 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
+ 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
+ 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
+ let nums = '';
+ for (let i = 0; i < length; i++) {
+ const r = parseInt(Math.random() * 61, 10);
+ nums += data[r];
+ }
+ return nums + '-' + parseInt(Math.random() * 10000000000, 10);
+};
+
+function escapeHtml (str) {
+ return str.replace(/[&<>"'/]/g, function (match) {
+ return {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ "'": ''',
+ '/': '/'
+ }[match];
+ });
+}
+
+
+export const splitTextForTTS = (text, maxLength = 30) => {
+ // 定义优先分割的标点符号
+ const punctuation = ['。', ',', ';', '?', '!', ',', ';', '?', '!', '、'];
+ let segments = [];
+ let segment = '';
+ let tempSegment = '';
+
+ for (let i = 0; i < text.length; i++) {
+ tempSegment += text[i]; // 如果超过最大长度,则尝试在上一个标点符号处分割
+
+ if (tempSegment.length > maxLength) {
+ let lastPunctuationIndex = -1;
+ for (let j = tempSegment.length - 1; j >= 0; j--) {
+ if (punctuation.includes(tempSegment[j])) {
+ lastPunctuationIndex = j;
+ break;
+ }
+ } // 如果找到标点符号,则在标点符号后分割
+
+ if (lastPunctuationIndex !== -1) {
+ segments.push(tempSegment.slice(0, lastPunctuationIndex + 1).trim());
+ tempSegment = tempSegment.slice(lastPunctuationIndex + 1).trim();
+ } else {
+ // 如果没有找到标点符号,则在最大长度处分割
+ segments.push(tempSegment.slice(0, maxLength).trim());
+ tempSegment = tempSegment.slice(maxLength).trim();
+ }
+ }
+ } // 添加最后一个段落
+
+ if (tempSegment.length > 0) {
+ segments.push(tempSegment.trim());
+ }
+
+ return segments;
+ }
diff --git a/components/ProductSection.vue b/components/ProductSection.vue
index f2309ed..f4e7ac5 100644
--- a/components/ProductSection.vue
+++ b/components/ProductSection.vue
@@ -4,83 +4,92 @@
{{ title }}
- 更多
+ 更多
-
-
-
-
-
-
-
-
-
-
- 智能体
-
- {{ item.agent.name }}
-
-
-
-
-
- {{ item.title }}
- ¥{{ item.price }}
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 智能体
+
+ {{ item.agent.name }}
+
+
+
+
+
+ {{ item.title }}
+ ¥{{ item.price }}
+
+
+
+
+
+
+
+
+
@@ -124,10 +133,11 @@ export default {
type: String,
default: "#02fcfc",
},
- isFeel: {
- type: Boolean,
- default: false,
+ type: {
+ type: Number,
+ default: 1,
},
+
color: {
type: String,
default: "#D3FCFF",
@@ -180,9 +190,17 @@ export default {
},
toAgent(e){
- uni.navigateTo({
- url: "/pages/agent/index?id="+e.agent.agentId
- });
+ if(e.agentStatus){
+ uni.navigateTo({
+ url: "/subPackages/other/evita?id="+e.agent.agentId
+ });
+ }else{
+ uni.showToast({
+ title:'请先购买当前商品',
+ icon:'none'
+ })
+ }
+
},
// 显示图片
diff --git a/components/WaterfallLayout.vue b/components/WaterfallLayout.vue
index d3d3419..808376d 100644
--- a/components/WaterfallLayout.vue
+++ b/components/WaterfallLayout.vue
@@ -1,320 +1,299 @@
-
-
-
-
-
-
-
- {{ item.title }}
-
-
-
-
-
-
-
-
-
-
- {{ item.title }}
-
-
-
-
-
-
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+ .like-count {
+ font-size: 22rpx;
+ color: #666;
+ }
+
\ No newline at end of file
diff --git a/manifest.json b/manifest.json
index 3e3f8c0..e9579b6 100644
--- a/manifest.json
+++ b/manifest.json
@@ -64,7 +64,8 @@
}
},
"lazyCodeLoading" : "requiredComponents",
- "requiredPrivateInfos" : [ "getLocation", "chooseLocation" ]
+ "requiredPrivateInfos" : [ "getLocation", "chooseLocation" ],
+ "requiredBackgroundModes" : [ "audio" ]
},
"mp-alipay" : {
"usingComponents" : true
diff --git a/pages/agent/index.vue b/pages/agent/index.vue
index 02409e3..72e290b 100644
--- a/pages/agent/index.vue
+++ b/pages/agent/index.vue
@@ -1,8 +1,45 @@
+
+
+
-
+
+
+
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/pages/index/iSoul.vue b/pages/index/iSoul.vue
index df6986b..13755f8 100644
--- a/pages/index/iSoul.vue
+++ b/pages/index/iSoul.vue
@@ -1,1511 +1,1735 @@
-
-
+
-
-
-
-
+
+
+
+
+
+ 📖
+ 暂无纪念册
+ 您还没有数字资产纪念册
+ 快去购买数字资产创建您的专属纪念册吧
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
+::v-deep .uni-popup {
+ z-index: 999 !important;
+}
+view {
+ box-sizing: border-box;
+}
+
+.profile-container {
+ background: white;
+ color: white;
+}
+
+/* 状态栏占位 */
+.status-bar-placeholder {
+ height: var(--status-bar-height);
+ width: 100%;
+}
+
+/* 顶部导航 */
+.header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ height: 48px;
+}
+
+.back-btn,
+.more-btn {
+ width: 60rpx;
+ height: 60rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 40rpx;
+ color: white;
+}
+
+.dots {
+ font-size: 32rpx;
+ font-weight: bold;
+}
+
+/* 用户信息区域 */
+.user-section {
+ display: flex;
+ align-items: center;
+ padding: 0 40rpx 30rpx;
+}
+
+.user-avatar {
+ width: 120rpx;
+ height: 120rpx;
+ border-radius: 50%;
+ overflow: hidden;
+ margin-right: 30rpx;
+}
+
+.avatar-img {
+ width: 100%;
+ height: 100%;
+}
+
+.user-info {
+ flex: 1;
+}
+
+.username {
+ font-size: 36rpx;
+ font-weight: bold;
+ color: white;
+ margin-bottom: 10rpx;
+}
+
+.user-id {
+ font-size: 24rpx;
+ color: rgba(255, 255, 255, 0.8);
+ margin-bottom: 10rpx;
+}
+
+.location {
+ display: flex;
+ align-items: center;
+ font-size: 24rpx;
+ color: rgba(255, 255, 255, 0.8);
+}
+
+.location-icon,
+.info-icon {
+ margin-right: 8rpx;
+}
+
+/* 城市艺术漫游 */
+.city-art {
+ padding: 0 40rpx 20rpx;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.city-title {
+ display: flex;
+ align-items: center;
+ font-size: 28rpx;
+ color: rgba(255, 255, 255, 0.9);
+}
+
+.pin-icon {
+ margin-right: 8rpx;
+}
+
+.city-name {
+ font-size: 28rpx;
+ color: white;
+ font-weight: bold;
+}
+
+.gender-icon {
+ width: 40rpx;
+ height: 40rpx;
+ background: rgba(255, 255, 255, 0.2);
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 24rpx;
+}
+
+/* 统计数据 */
+.stats-section {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-top: 80rpx;
+ padding-bottom: 50rpx;
+ padding: 0 40rpx;
+}
+
+.stats-left {
+ display: flex;
+ gap: 60rpx;
+}
+
+.stat-item {
+ text-align: center;
+ min-width: 80rpx;
+}
+
+.stat-number {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: white;
+ margin-bottom: 8rpx;
+}
+
+.stat-label {
+ font-size: 24rpx;
+ color: rgba(255, 255, 255, 0.8);
+}
+
+/* 权益兑换入口 */
+.exchange-entry {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 16rpx;
+ background: rgba(255, 255, 255, 0.1);
+ border-radius: 20rpx;
+ min-width: 120rpx;
+ transition: all 0.3s ease;
+
+ &:active {
+ transform: scale(0.95);
+ background: rgba(255, 255, 255, 0.2);
+ }
+}
+
+.exchange-icon {
+ font-size: 32rpx;
+ margin-bottom: 8rpx;
+}
+
+.exchange-text {
+ font-size: 22rpx;
+ color: rgba(255, 255, 255, 0.9);
+ font-weight: 500;
+}
+
+/* 操作按钮 */
+.action-buttons {
+ display: flex;
+ padding: 0 40rpx 40rpx;
+ gap: 20rpx;
+}
+
+.follow-btn {
+ flex: 1;
+ background: #ff4757;
+ border-radius: 50rpx;
+ padding: 20rpx;
+ text-align: center;
+ color: white;
+ font-size: 28rpx;
+ font-weight: bold;
+}
+
+.message-btn {
+ flex: 1;
+ background: rgba(255, 255, 255, 0.2);
+ border-radius: 50rpx;
+ padding: 20rpx;
+ text-align: center;
+ color: white;
+ font-size: 28rpx;
+ font-weight: bold;
+}
+
+/* 待激活的Agent */
+.agent-section {
+ margin: 0 47rpx;
+ border-radius: 20rpx;
+ margin-bottom: 0rpx;
+ overflow: hidden;
+ display: flex;
+ align-items: center;
+ padding: 30rpx 0;
+}
+
+.agent-header {
+ margin-right: 30rpx;
+ flex-shrink: 0;
+}
+
+.agent-title {
+ font-size: 28rpx;
+ color: #000000;
+}
+
+.agent-content {
+ flex: 1;
+}
+
+.agent-scroll {
+ width: 430rpx;
+ white-space: nowrap;
+ /* 微信小程序隐藏横向滚动条 */
+ overflow: hidden;
+
+ /* Webkit浏览器 */
+ &::-webkit-scrollbar {
+ display: none !important;
+ width: 0 !important;
+ height: 0 !important;
+ }
+
+ /* Firefox */
+ scrollbar-width: none;
+ /* IE和Edge */
+ -ms-overflow-style: none;
+}
+
+.agent-avatars {
+ display: inline-flex;
+ gap: 20rpx;
+}
+
+.agent-avatar {
+ width: 104rpx;
+ height: 104rpx;
+ border-radius: 50%;
+ overflow: hidden;
+ flex-shrink: 0;
+}
+
+.agent-img {
+ width: 100%;
+ height: 100%;
+}
+
+/* 数字资产权益 */
+.digital-assets {
+ margin: 0 30rpx 30rpx;
+}
+
+.asset-header {
+ margin-bottom: 20rpx;
+}
+
+.asset-title {
+ font-size: 28rpx;
+ color: #000000;
+ font-weight: 500;
+}
+
+.asset-content {
+ width: 100%;
+}
+
+/* 单个数据铺满显示样式 */
+.asset-card-single {
+ width: 100%;
+ border-radius: 20rpx;
+ overflow: hidden;
+ box-shadow: 0 15rpx 12rpx rgba(0, 0, 0, 0.15);
+ transition: all 0.3s ease;
+ position: relative;
+}
+
+.asset-card-single:active {
+ transform: scale(0.98);
+ box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.2);
+}
+
+.single-card-wrapper {
+ position: relative;
+ width: 100%;
+ height: 400rpx;
+ overflow: hidden;
+}
+
+.asset-img-single {
+ width: 100%;
+ height: 100%;
+ transition: transform 0.3s ease;
+}
+
+.asset-card-single:active .asset-img-single {
+ transform: scale(1.05);
+}
+
+.asset-overlay-single {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: linear-gradient(transparent, rgba(0, 0, 0, 1));
+ padding: 60rpx 30rpx 30rpx;
+ color: white;
+}
+
+.asset-badge-single {
+ background: linear-gradient(135deg, #fffdb7 0%, #97fffa 100%);
+ color: black;
+ font-size: 22rpx;
+ padding: 8rpx 16rpx;
+ border-radius: 20rpx;
+ display: inline-block;
+ margin-bottom: 16rpx;
+ font-weight: 500;
+}
+
+.asset-name-single {
+ font-size: 32rpx;
+ font-weight: bold;
+ margin-bottom: 8rpx;
+ line-height: 1.3;
+}
+
+.asset-desc-single {
+ font-size: 28rpx;
+ color: rgba(255, 255, 255, 0.9);
+ margin-bottom: 20rpx;
+ line-height: 1.4;
+}
+
+.asset-action-single {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background: linear-gradient(135deg, #fffdb7e6 0%, #97fffab5 100%);
+ border-radius: 25rpx;
+ padding: 12rpx 20rpx;
+ backdrop-filter: blur(10rpx);
+}
+
+.action-text-single {
+ font-size: 28rpx;
+ font-weight: bold;
+ color: black;
+}
+
+.action-arrow-single {
+ font-size: 28rpx;
+ font-weight: bold;
+ color: black;
+ transition: transform 0.3s ease;
+}
+
+.asset-card-single:active .action-arrow-single {
+ transform: translateX(6rpx);
+}
+
+.asset-scroll-container {
+}
+
+.asset-scroll {
+ width: 100%;
+ white-space: nowrap;
+ overflow: hidden;
+
+ /* 微信小程序隐藏横向滚动条 */
+ &::-webkit-scrollbar {
+ display: none !important;
+ width: 0 !important;
+ height: 0 !important;
+ }
+
+ /* Firefox */
+ scrollbar-width: none;
+ /* IE和Edge */
+ -ms-overflow-style: none;
+}
+
+.asset-cards {
+ display: inline-flex;
+ gap: 20rpx;
+ padding: 30rpx 10rpx;
+}
+
+.asset-card {
+ width: 500rpx;
+ border-radius: 20rpx;
+ overflow: hidden;
+ box-shadow: 0 15rpx 12rpx rgba(0, 0, 0, 0.15);
+ transition: all 0.3s ease;
+ position: relative;
+ flex-shrink: 0;
+}
+
+.asset-card:active {
+ transform: scale(0.98);
+ box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.2);
+}
+
+.asset-card-wrapper {
+ position: relative;
+ width: 100%;
+ height: 300rpx;
+ overflow: hidden;
+}
+
+.asset-img {
+ width: 100%;
+ height: 100%;
+ transition: transform 0.3s ease;
+}
+
+.asset-card:active .asset-img {
+ transform: scale(1.05);
+}
+
+.asset-overlay {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: linear-gradient(transparent, rgba(0, 0, 0, 1));
+ padding: 40rpx 30rpx 30rpx;
+ color: white;
+ // backdrop-filter: blur(10rpx);
+ width: 100%;
+ height: 100%;
+}
+
+.asset-badge {
+ background: linear-gradient(135deg, #fffdb7 0%, #97fffa 100%);
+ color: black;
+ font-size: 20rpx;
+ padding: 6rpx 12rpx;
+ border-radius: 16rpx;
+ display: inline-block;
+ margin-bottom: 12rpx;
+ font-weight: 500;
+}
+
+.asset-name {
+ font-size: 26rpx;
+ font-weight: 500;
+ margin-bottom: 6rpx;
+ line-height: 1.3;
+}
+
+.asset-desc {
+ font-size: 34rpx;
+ color: white;
+ margin-bottom: 16rpx;
+ font-weight: bold;
+ line-height: 1.4;
+}
+
+.asset-action {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background: linear-gradient(135deg, #fffdb7e6 0%, #97fffab5 100%);
+ border-radius: 20rpx;
+ padding: 10rpx 16rpx;
+ backdrop-filter: blur(10rpx);
+ white-space: nowrap;
+ min-width: 0;
+}
+
+.action-text-order {
+ font-size: 26rpx;
+ font-weight: bold;
+ color: black;
+ flex-shrink: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.action-arrow {
+ font-size: 26rpx;
+ font-weight: bold;
+ color: white;
+ transition: transform 0.3s ease;
+ flex-shrink: 0;
+ margin-left: 8rpx;
+}
+
+.action-arrow-order {
+ font-size: 26rpx;
+ font-weight: bold;
+ color: black;
+ transition: transform 0.3s ease;
+ flex-shrink: 0;
+ margin-left: 8rpx;
+}
+
+.asset-card:active .action-arrow {
+ transform: translateX(6rpx);
+}
+
+/* 原来的图片风格 */
+.asset-card-old {
+ border-radius: 20rpx;
+ overflow: hidden;
+}
+
+/* 底部操作按钮 */
+.asset-actions {
+ display: flex;
+ padding: 20rpx 0;
+ background: white;
+ border-radius: 20rpx;
+ font-size: 25rpx;
+}
+
+.action-icon {
+ width: 36rpx;
+ height: 36rpx;
+ border-radius: 50%;
+ margin-bottom: 12rpx;
+}
+
+.action-icon.red {
+ background: #ff4757;
+}
+
+.action-icon.gray {
+ background: #ccc;
+}
+
+/* 有感商品 */
+.feeling-goods {
+ margin: 20rpx 30rpx 30rpx;
+}
+
+.goods-card {
+ border-radius: 20rpx;
+ overflow: hidden;
+}
+
+.goods-bg {
+ padding: 40rpx 30rpx 20rpx;
+ position: relative;
+}
+
+.goods-title {
+ font-size: 32rpx;
+ color: white;
+ font-weight: bold;
+ margin-bottom: 10rpx;
+}
+
+.goods-brand {
+ font-size: 36rpx;
+ color: white;
+ font-weight: bold;
+ margin-bottom: 5rpx;
+}
+
+.goods-subtitle {
+ font-size: 24rpx;
+ color: rgba(255, 255, 255, 0.8);
+}
+
+.goods-actions {
+ display: flex;
+ background: white;
+}
+
+.goods-action {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 20rpx 10rpx;
+ font-size: 26rpx;
+ color: #000000;
+}
+
+.goods-action.active {
+ color: #ff4757;
+}
+
+/* 数字资产纪念册 */
+.memorial-section {
+ margin: 0 47rpx;
+ margin-bottom: 30rpx;
+}
+
+.memorial-divider {
+ display: flex;
+ align-items: center;
+ padding: 30rpx 0;
+ margin-bottom: 30rpx;
+}
+
+.divider-line {
+ flex: 1;
+ height: 2rpx;
+ background: #e0e0e0;
+}
+
+.divider-text {
+ padding: 0 30rpx;
+ font-size: 30rpx;
+ color: #000000;
+ font-weight: bold;
+ white-space: nowrap;
+}
+
+.memorial-cards {
+ display: flex;
+ gap: 20rpx;
+}
+
+/* 单条数据特殊展示样式 */
+.memorial-card-single {
+ width: 100%;
+ max-width: 100%;
+ margin: 0 auto;
+ border-radius: 20rpx;
+ overflow: hidden;
+ box-shadow: 0 12rpx 40rpx rgba(0, 0, 0, 0.15);
+ transition: all 0.3s ease;
+ position: relative;
+}
+
+.memorial-card-single:active {
+ transform: scale(0.98);
+ box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.2);
+}
+
+.single-card-wrapper {
+ position: relative;
+ width: 100%;
+ height: 400rpx;
+ overflow: hidden;
+}
+
+.memorial-img-single {
+ width: 100%;
+ height: 100%;
+ transition: transform 0.3s ease;
+}
+
+.memorial-card-single:active .memorial-img-single {
+ transform: scale(1.05);
+}
+
+.single-overlay {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
+ padding: 60rpx 30rpx 30rpx;
+ color: white;
+}
+
+.single-badge {
+ background: linear-gradient(135deg, #77f3f9 0%, #764ba2 100%);
+ color: white;
+ font-size: 22rpx;
+ padding: 8rpx 16rpx;
+ border-radius: 20rpx;
+ display: inline-block;
+ margin-bottom: 16rpx;
+ font-weight: 500;
+ box-shadow: 0 4rpx 12rpx rgba(102, 126, 234, 0.3);
+}
+
+.single-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ margin-bottom: 8rpx;
+ line-height: 1.3;
+}
+
+.single-desc {
+ font-size: 24rpx;
+ color: rgba(255, 255, 255, 0.8);
+ margin-bottom: 20rpx;
+ line-height: 1.4;
+}
+
+.single-action {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background: rgba(255, 255, 255, 0.1);
+ border-radius: 25rpx;
+ padding: 12rpx 20rpx;
+ backdrop-filter: blur(10rpx);
+ border: 1rpx solid rgba(255, 255, 255, 0.2);
+}
+
+.action-text {
+ font-size: 26rpx;
+ font-weight: 500;
+ color: white;
+}
+
+.action-arrow {
+ font-size: 28rpx;
+ font-weight: bold;
+ color: white;
+ transition: transform 0.3s ease;
+}
+
+.memorial-card-single:active .action-arrow {
+ transform: translateX(6rpx);
+}
+
+.memorial-card {
+ flex: 1;
+ border-radius: 10rpx;
+ overflow: hidden;
+ background: white;
+}
+
+.memorial-img {
+ width: 100%;
+ height: 425rpx;
+}
+
+.memorial-info {
+ padding: 20rpx 10rpx;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.memorial-title {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ font-size: 22rpx;
+ color: #000000;
+ flex: 1;
+}
+
+.memorial-more {
+ font-size: 14rpx;
+ color: #999;
+}
+
+/* 无数据时的空状态样式 */
+.memorial-empty {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ min-height: 280rpx;
+}
+
+.empty-content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ text-align: center;
+ color: #333333;
+}
+
+.empty-icon {
+ font-size: 80rpx;
+ margin-bottom: 20rpx;
+ opacity: 0.6;
+}
+
+.empty-title {
+ font-size: 32rpx;
+ color: white;
+ font-weight: 500;
+ margin-bottom: 10rpx;
+}
+
+.empty-desc {
+ font-size: 26rpx;
+ margin-bottom: 8rpx;
+}
+
+.empty-tip {
+ font-size: 24rpx;
+ line-height: 1.4;
+}
+
+/* 底部菜单 */
+.bottom-menu {
+ padding: 40rpx 30rpx;
+ background: white;
+ margin: 0 30rpx;
+ border-radius: 20rpx;
+ margin-bottom: 30rpx;
+}
+
+.menu-item {
+ padding: 30rpx 0;
+ border-bottom: 1rpx solid #f5f5f5;
+ font-size: 28rpx;
+ color: #333;
+}
+
+.menu-item:last-child {
+ border-bottom: none;
+}
+
+// 用户顶部背景区域
+.user-top {
+ background-size: cover;
+ background-position: center;
+ background-repeat: no-repeat;
+ padding-bottom: 20rpx;
+}
+
+.digital-img {
+ height: 265rpx;
+ width: 100%;
+ border-radius: 20rpx;
+}
+
+/* 权益兑换弹窗 */
+.exchange-popup {
+ width: 600rpx;
+ background-color: #ffffff;
+ border-radius: 16rpx;
+ overflow: hidden;
+}
+
+.popup-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 30rpx;
+ border-bottom: 1px solid #f0f0f0;
+}
+
+.popup-title {
+ font-size: 32rpx;
+ font-weight: 600;
+ color: #333;
+}
+
+.popup-close {
+ font-size: 40rpx;
+ color: #999;
+ padding: 0 10rpx;
+}
+
+.popup-content {
+ padding: 40rpx 30rpx 30rpx;
+}
+
+.input-section {
+ margin-bottom: 40rpx;
+}
+
+.input-label {
+ display: block;
+ font-size: 28rpx;
+ color: #333;
+ margin-bottom: 20rpx;
+ font-weight: 500;
+}
+
+.exchange-input {
+ width: 100%;
+ height: 88rpx;
+ border: 2rpx solid #e0e0e0;
+ border-radius: 12rpx;
+ padding: 0 20rpx;
+ font-size: 28rpx;
+ color: #333;
+ box-sizing: border-box;
+
+ &:focus {
+ border-color: #77f3f9;
+ }
+}
+
+.popup-actions {
+ display: flex;
+ gap: 20rpx;
+}
+
+.cancel-btn,
+.confirm-btn {
+ flex: 1;
+ height: 80rpx;
+ border-radius: 12rpx;
+ font-size: 28rpx;
+ font-weight: 600;
+ border: none;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.3s ease;
+
+ &:active {
+ transform: scale(0.98);
+ }
+}
+
+.cancel-btn {
+ background: #f5f5f5;
+ color: #77f3f9;
+}
+
+.confirm-btn {
+ background: #77f3f9;
+ color: #000000;
+}
+
+.column-divider {
+ width: 2rpx;
+ height: 60rpx;
+ background: rgba(0, 0, 0, 0.1);
+ margin: 35rpx 16rpx;
+ flex-shrink: 0;
+}
+
+.action-box {
+ display: flex;
+ align-items: center;
+ justify-content: space-around;
+ padding: 20rpx 40rpx 0;
+}
+
+.popup-actions-bottom {
+ color: #989898;
+ font-weight: bold;
+ font-size: 28rpx;
+ margin-top: 30rpx;
+ margin-bottom: 30rpx;
+}
+
diff --git a/pages/index/index.vue b/pages/index/index.vue
index 7a16720..afdcc3f 100644
--- a/pages/index/index.vue
+++ b/pages/index/index.vue
@@ -27,6 +27,7 @@
detailUrlPrefix="/subPackages/equityGoods/detail"
@like-toggle="handleLikeToggle"
color="#D2FFDE"
+ :type="1"
/>
+
diff --git a/pages/index/readingBody.vue b/pages/index/readingBody.vue
index b31743a..6f49f0a 100644
--- a/pages/index/readingBody.vue
+++ b/pages/index/readingBody.vue
@@ -1,17 +1,87 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+ 关于阅读题
+
+
+
+
+
+
+
+
+
+
+
+
+ 在这里,你的每一次人文漫游、每一次灵感闪现,都值得被郑重记录。我们鼓励你分享高质量的图文笔记,将旅途中的美与感动,化为这座精神星球上的璀璨星辰。
+
+
+ Epic
+ soul交响」阅读体以数字文化资产IP为核心,以消费产品创新为导向,把“每个生命都有史诗般的灵魂”作为创作宗旨,通过文字、图像、音视频、交互式展览等多种技术工具创作完成的轻量化数字文化内容产品,邀您一起收藏这颗星球所有未被传唱的英雄史诗。
+
+
+ Epic
+ soul交响」阅读体将长期关注乡村振兴、城市更新、文化焕新等领域,践行探索未来文化信息的解构、分发和互动方式。
+
+
+
+
+ 阅读合集
+
+
-
+
+ 《今夜,我们都有一艘秘密飞船》
+
+
+ 本期由DAYUN远见文化工厂与吴文化博物馆联合推出,将其馆藏文物“元代朱碧山造银槎杯”活化为数字IP。这不仅是一次文物活化的深度实践,更是一份献给现代人的精神远航指南,邀你随时登船,自在漂浮。
+
+
+
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
- 阅读合集
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ {{ item.title }}
+
+
+ {{ descList[index] }}
+
+
+
+
+
+
+
\ No newline at end of file
+.bg {
+ padding-bottom: 200rpx;
+}
+
+.swiper-box,
+.top-box {
+ margin: 10rpx 25rpx 0;
+ height: 830rpx;
+ box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
+ border-radius: 20rpx;
+ overflow: hidden;
+ // padding-top: 10rpx;
+ // background-color: #fff;
+
+ image {
+ width: 100%;
+ height: 100%;
+ }
+}
+
+.carousel-swiper {
+ width: 582.13rpx;
+ height: 706.24rpx;
+ margin: -40rpx auto 0;
+
+ image {
+ width: 100%;
+ height: 100%;
+ }
+}
+
+.exhibit-issue {
+ font-family: serif;
+ font-size: 28rpx;
+ color: #999;
+ font-style: italic;
+ padding: 40rpx 30rpx 0 0;
+ text-align: right;
+}
+
+.custom-indicators {
+ display: flex;
+ justify-content: center;
+ gap: 8rpx;
+ margin-top: 40rpx;
+
+ .indicator-dot {
+ width: 8rpx;
+ height: 8rpx;
+ border-radius: 4rpx;
+ background-color: rgba(150, 150, 150, 0.5);
+ transition: all 0.3s;
+ }
+
+ .indicator-dot.active {
+ width: 20rpx;
+ background-color: rgb(133, 133, 133);
+ }
+}
+
+.category-scroll {
+ // padding: 40rpx 0 0 40rpx;
+ // display: flex;
+ height: 393rpx;
+ margin: 50rpx 25rpx 0;
+
+ image {
+ width: 100%;
+ height: 393rpx;
+ flex-shrink: 0;
+ // margin-right: 20rpx;
+ border-radius: 20rpx;
+ }
+
+ video {
+ width: 100%;
+ height: 393rpx;
+ border-radius: 20rpx;
+ }
+}
+
+.title-box {
+ font-size: 36rpx;
+ font-weight: 500;
+ margin-top: 40rpx;
+ padding-left: 25rpx;
+
+ image {
+ width: 185.85rpx;
+ height: 20.98rpx;
+ margin-left: 21rpx;
+ }
+}
+
+.title-box-about {
+ font-size: 36rpx;
+ font-weight: 500;
+ margin-top: 50rpx;
+ padding-left: 25rpx;
+
+ image {
+ width: 106.5rpx;
+ height: 20.98rpx;
+ margin-left: 21rpx;
+ }
+}
+
+.reading-title {
+ margin: 60rpx auto 0;
+ width: 585rpx;
+ height: 30rpx;
+ border-radius: 15rpx;
+ background-color: rgba(46, 220, 78, 0.8);
+ font-weight: bold;
+ font-size: 28rpx;
+ color: #000000;
+ padding: 0 40rpx;
+ position: relative;
+
+ view {
+ position: absolute;
+ z-index: 20;
+ bottom: 15rpx;
+ }
+
+ & > view:nth-child(2) {
+ left: 268rpx;
+ }
+
+ & > view:nth-child(3) {
+ right: 55rpx;
+ }
+
+ span {
+ width: 111rpx;
+ height: 100%;
+ background-color: rgb(9, 154, 60);
+ border-radius: 15rpx;
+ position: absolute;
+ left: 32rpx;
+ }
+}
+
+.reading-box {
+ margin: 20rpx 25rpx 0;
+
+ padding: 35rpx 10rpx 5rpx;
+ display: flex;
+ justify-content: space-around;
+ flex-wrap: wrap;
+ position: relative;
+ // top: -15rpx;
+ gap: 16rpx;
+
+ image {
+ width: 100%;
+ height: 346rpx;
+ }
+
+ .reading-box-item {
+ flex: 0 0 calc(50% - 8rpx);
+ border-radius: 20rpx;
+ box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
+ background-color: #fff;
+ padding: 20rpx;
+ font-size: 30rpx;
+ }
+
+ .reading-box-item-title {
+ margin: 15rpx 0;
+ font-weight: bold;
+ }
+
+ .reading-box-item-desc {
+ font-size: 20rpx;
+ color: #808080;
+ }
+}
+
+.start-swiper {
+ width: 100vw;
+ height: calc(100vh - 123rpx);
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 100;
+
+ image {
+ width: 100%;
+ height: 100%;
+ }
+}
+
+.desc-box {
+ padding: 0 25rpx;
+ color: #616161;
+ margin: 30rpx 0;
+ font-size: 22rpx;
+
+ view {
+ margin-bottom: 20rpx;
+ }
+}
+
+.new-book-body {
+ margin: 20rpx 25rpx 0;
+ border-radius: 20rpx;
+ box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
+ padding: 50rpx 0rpx 30rpx;
+ background-color: #fff;
+ text-align: left;
+
+ image {
+ margin: 0 auto;
+ display: block;
+ }
+
+ .new-book-body-title {
+ width: 583rpx;
+ font-size: 37rpx;
+ font-weight: bold;
+ margin: 20rpx auto;
+ }
+
+ .new-book-body-desc {
+ width: 583rpx;
+ color: #808080;
+ font-size: 24rpx;
+ margin: 20rpx auto;
+ }
+}
+.newBookCard {
+ width: 583rpx;
+ height: 706rpx;
+ margin: 0 auto;
+ background-size: 100% auto;
+ background-repeat: no-repeat;
+ background-position: top;
+ background-color: #fff;
+ background-image: url(https://des.js-dyyj.com/data/2025/08/29/a1a0009c-9248-48e3-b5a7-5d2970a1eb19.png);
+}
+
diff --git a/pages/index/sensoryStore.vue b/pages/index/sensoryStore.vue
index 8f33d7f..21997cc 100644
--- a/pages/index/sensoryStore.vue
+++ b/pages/index/sensoryStore.vue
@@ -1,5 +1,6 @@
+
@@ -51,8 +52,9 @@
import headerVue from "@/components/header.vue"
import CustomTabBar from '@/components/CustomTabBar.vue';
import MusicControl from '@/components/MusicControl.vue';
+ import BackButton from "@/components/BackButton.vue";
export default {
- components: {CustomTabBar,headerVue,MusicControl},
+ components: {CustomTabBar,headerVue,MusicControl,BackButton},
data() {
return {
topBanner: [],
diff --git a/pages/index/timeShopBank.vue b/pages/index/timeShopBank.vue
index c578894..42b70ff 100644
--- a/pages/index/timeShopBank.vue
+++ b/pages/index/timeShopBank.vue
@@ -9,6 +9,22 @@
:page-id="'timeShopBank_page'"
:style-type="'timeShop'"
/>
+
+
+ 欢迎来到「旅行时间行」,你的精神财富储蓄所。
+
+
+ 在这里,你的每一次人文漫游、每一次灵感闪现,都值得被郑重记录。我们鼓励你分享高质量的图文笔记,将旅途中的美与感动,化为这座精神星球上的璀璨星辰。
+
+
+ 为他人的美好驻足、点赞、留言,每一次真诚的互动,都是在为你的时间银行存入-笔宝贵的「精神货币」。这些资产不仅可以兑换独家福利与实体好物,更能为你解锁专属的荣誉身份,让你成为这座星球上最闪耀的共创者。
+
+
+ 即刻发布你的第一篇笔记,开启你的财富积累之旅吧!
+
+
+
+
@@ -187,7 +203,7 @@ export default {
{};
},
onShow() {
- if (this.userInfo && this.userInfo.token) {
+ if (this.userInfo && this.userInfo.id) {
this.getUserInfo();
}
},
@@ -374,7 +390,7 @@ page {
.tab-container {
background: #ffffff;
padding: 0 32rpx;
- margin-top: 40rpx;
+ margin-top: 20rpx;
margin-bottom: 20rpx;
}
@@ -492,6 +508,20 @@ page {
color: #999;
}
}
+.desc-box{
+ padding: 0 20rpx;
+ color: #616161;
+ margin: 30rpx 0;
+ font-size: 22rpx;
+ view{
+ margin-bottom: 20rpx;
+ &:nth-child(1){
+ font-size: 24rpx;
+ font-weight: bold;
+ margin-bottom: 20rpx;
+ }
+ }
+}
/* 自定义样式已移至WaterfallLayout组件内部 */
diff --git a/pages/notes/detail.vue b/pages/notes/detail.vue
index 304baa7..111b236 100644
--- a/pages/notes/detail.vue
+++ b/pages/notes/detail.vue
@@ -433,7 +433,7 @@ padding: 12rpx 30rpx;
font-size: 30rpx;
line-height: 1.6;
color: #333;
- font-weight: bold;
+ font-weight: 500;
}
}
diff --git a/pages/stratIndex.vue b/pages/stratIndex.vue
index e87c239..4202156 100644
--- a/pages/stratIndex.vue
+++ b/pages/stratIndex.vue
@@ -18,7 +18,8 @@
},
data() {
return {
- screenPng: ""
+ screenPng: "",
+ count:1
}
},
@@ -26,6 +27,7 @@
},
onReady () {
+
// 小轮播
this.Post({
type_id: 3,
@@ -44,6 +46,7 @@
const app = getApp();
app.initBackgroundMusic(); // 初始化背景音乐
uni.$bgMusic.play(); // 播放音乐
+
},
methods: {
goIndex () {
diff --git a/static/imgs/icon-bf-active.png b/static/imgs/icon-bf-active.png
new file mode 100644
index 0000000..034edfa
Binary files /dev/null and b/static/imgs/icon-bf-active.png differ
diff --git a/static/imgs/icon-bf.png b/static/imgs/icon-bf.png
new file mode 100644
index 0000000..1e159f0
Binary files /dev/null and b/static/imgs/icon-bf.png differ
diff --git a/static/imgs/icon-copy.png b/static/imgs/icon-copy.png
new file mode 100644
index 0000000..34bee97
Binary files /dev/null and b/static/imgs/icon-copy.png differ
diff --git a/static/imgs/icon-pic.png b/static/imgs/icon-pic.png
new file mode 100644
index 0000000..cf44a61
Binary files /dev/null and b/static/imgs/icon-pic.png differ
diff --git a/static/imgs/icon-txt.png b/static/imgs/icon-txt.png
new file mode 100644
index 0000000..4efde2d
Binary files /dev/null and b/static/imgs/icon-txt.png differ
diff --git a/static/imgs/icon-video.png b/static/imgs/icon-video.png
new file mode 100644
index 0000000..935aef1
Binary files /dev/null and b/static/imgs/icon-video.png differ
diff --git a/static/imgs/more.png b/static/imgs/more.png
new file mode 100644
index 0000000..9faf353
Binary files /dev/null and b/static/imgs/more.png differ
diff --git a/static/js/request.js b/static/js/request.js
index ecac40f..64a8552 100644
--- a/static/js/request.js
+++ b/static/js/request.js
@@ -8,7 +8,7 @@ const DEV_API_URL = 'https://epic.new.js-dyyj.com';
// const PROD_API_URL = 'https://epic.js-dyyj.com';
const PROD_API_URL = 'https://epic.new.js-dyyj.com';
const NEWAPIURL = process.env.NODE_ENV === 'development' ? DEV_API_URL : PROD_API_URL;
-const DEV_API_URL_DES = 'http://192.168.124.118:8083/xcx';
+const DEV_API_URL_DES = 'http://192.168.124.177:8083/xcx';
// const DEV_API_URL_DES = 'https://des.js-dyyj.com/xcx';
const PROD_API_URL_DES = 'https://des.js-dyyj.com/xcx';
const NEWAPIURL_DES = process.env.NODE_ENV === 'development' ? DEV_API_URL_DES : PROD_API_URL_DES;
diff --git a/subPackages/equityGoods/detail.vue b/subPackages/equityGoods/detail.vue
index 2202a2c..10b0573 100644
--- a/subPackages/equityGoods/detail.vue
+++ b/subPackages/equityGoods/detail.vue
@@ -1,301 +1,250 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
- {{ goodsInfo.title||'-' }}
-
- 限量
- {{ goodsInfo.publishQuantity||0 }}份
- 剩余 {{ goodsInfo.remainQuantity||0 }}份
-
-
-
-
-
-
- ¥
- {{ goodsInfo.price||0 }}
-
-
-
-
- {{ goodsInfo.collectQuantity || 0 }}人收藏
-
-
-
-
-
+
+
+
+
+
+
+
+ {{ goodsInfo.title||'-' }}
+
+ 限量
+ {{ goodsInfo.publishQuantity||0 }}份
+ 剩余 {{ goodsInfo.remainQuantity||0 }}份
-
- 数字资产权力方
- 江苏大运河见
+
+
+
+
+ IP-AGENT
+
+
+ {{goodsInfo.agent.name}}
-
- 备案平台
- 江苏文交所
+
+ 点击收听
- -->
-
-
-
-
-
-
-
-
-
-
-
- 产品{{
- ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十"][
- index
- ]
- }}:
-
- {{ item.goodsName }}{{ item.skuName || "" }}
- X{{ item.bindQuantity }}份
-
-
-
+
+
+ ¥
+ {{ goodsInfo.price||0 }}
+
+
+
+
+ {{ goodsInfo.collectQuantity || 0 }}人收藏
+
+
+
+
+
+
+
+
+
+
+ 产品{{
+ ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十"][
+ index
+ ]
+ }}
+
+ {{ item.goodsName }}{{ item.skuName || "" }}X{{ item.bindQuantity }}份
+
+ {{ item.goodsType==3?item.subtitle: item.description }}
+
+
+
+
+
-
-
-
-
-
-
-
-
- {{ tab.name }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ {{ tab.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
-
-
- 立即购买
-
-
-
+ -->
+
+
+
+
+
+
+ 立即购买
+
+
+
+ .detail-container {
+ background: #f5f5f5;
+ min-height: 100vh;
+ }
+
+ .banner-content {
+ width: 100%;
+ height: 1000rpx;
+ position: relative;
+
+ .top-banner {
+ width: 100%;
+ height: 100%;
+ }
+
+ .dot-container {
+ position: absolute;
+ bottom: 43rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ left: 0;
+
+ .dot-line {
+ width: 52rpx;
+ height: 4rpx;
+ margin: 0 8rpx;
+ background: RGBA(189, 170, 173, 0.8);
+
+ &.active {
+ background: #94fafa;
+ }
+ }
+ }
+
+ .page-indicator {
+ position: absolute;
+ bottom: 20rpx;
+ right: 20rpx;
+ // background: rgba(0, 0, 0, 0.5);
+ border-radius: 10rpx;
+ padding: 10rpx 20rpx;
+
+ .page-text {
+ font-size: 24rpx;
+ color: #fff;
+ font-weight: 500;
+ }
+ }
+ }
+
+ .product-info {
+ padding: 40rpx 10rpx;
+ margin: 20rpx;
+ padding-bottom: 1rpx;
+
+ .title-section {
+ width: 370rpx;
+ margin-bottom: 30rpx;
+
+ .product-title {
+ font-size: 34rpx;
+ font-weight: bold;
+ color: #000000;
+ line-height: 1.4;
+ margin-bottom: 20rpx;
+ }
+
+ .tags-container {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+
+ .limit-tag {
+ background: #94fafa;
+ color: #333333;
+ padding: 8rpx 16rpx;
+ font-size: 26rpx;
+ border-radius: 6rpx;
+ }
+
+ .limit-count {
+ color: #000000;
+ padding: 8rpx 16rpx;
+ font-size: 26rpx;
+ border-radius: 0rpx 6rpx 6rpx 0;
+ }
+
+ .remaining {
+ color: #808080;
+ font-size: 26rpx;
+ margin-left: auto;
+ }
+ }
+ }
+
+ .price-section {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 40rpx;
+ margin-top: 20rpx;
+
+ .price-container {
+ display: flex;
+ align-items: baseline;
+
+ .currency {
+ font-size: 28rpx;
+ color: #333;
+ font-weight: bold;
+ }
+
+ .price {
+ font-size: 40rpx;
+ color: #333;
+ font-weight: bold;
+ font-family: "Futura";
+ }
+ }
+
+ .collect-container {
+ display: flex;
+ align-items: center;
+ gap: 10rpx;
+
+ .heart-icon {
+ width: 35rpx;
+ height: 29rpx;
+ transition: all 0.3s ease;
+ flex-shrink: 0;
+
+ &.liked {
+ opacity: 1;
+ filter: hue-rotate(320deg) saturate(2);
+ }
+
+ &:active {
+ transform: scale(1.2);
+ }
+ }
+
+ .collect-count {
+ color: #231815;
+ font-size: 28rpx;
+ font-weight: 500;
+ }
+ }
+ }
+
+ .equity-section {
+ margin-bottom: 40rpx;
+ border-top: 0.5rpx solid #e5e5e5;
+ border-bottom: 0.5rpx solid #e5e5e5;
+ padding: 40rpx 0;
+
+ .equity-row {
+ display: flex;
+ justify-content: space-between;
+ gap: 20rpx;
+
+ .equity-item {
+ text-align: left;
+
+ .equity-label {
+ font-size: 23rpx;
+ color: #231815;
+ font-weight: bold;
+ margin-bottom: 10rpx;
+ line-height: 1.3;
+ }
+
+ .equity-value {
+ font-size: 20rpx;
+ color: #595757;
+ font-weight: 500;
+ line-height: 1.3;
+ }
+ }
+ }
+ }
+
+ .equity-title {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin: 40rpx 0 30rpx;
+
+ .title-line {
+ width: 30rpx;
+ height: 2rpx;
+ background: #94fafa;
+ }
+
+ .title-text {
+ padding: 0 30rpx;
+ font-size: 25rpx;
+ color: #94fafa;
+ font-weight: bold;
+ }
+ }
+
+ .equity-details {
+ border-top: 1rpx solid #e5e5e5;
+ padding-top: 60rpx;
+ .equity-detail-item {
+ margin-bottom: 30rpx;
+ line-height: 1.5;
+
+ .detail-content-wrapper {
+ display: flex;
+ align-items: center;
+ .detail-info{
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ height: 110rpx;
+ }
+
+ .detail-label {
+ width: 100%;
+ font-size: 22rpx;
+ color: #808080;
+ font-weight: bold;
+ margin-right: 10rpx;
+ }
+
+ .detail-content {
+ width: 550rpx;
+ font-size: 26rpx;
+ color: #000000;
+ font-weight: 500;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+
+ }
+ }
+
+ .toggle-icon {
+ display: flex;
+ align-items: center;
+ gap: 8rpx;
+ cursor: pointer;
+ padding: 0rpx;
+ margin-left: 20rpx;
+
+ .icon-text {
+ font-size: 22rpx;
+ color: #666;
+ }
+
+ .icon-arrow {
+ font-size: 20rpx;
+ color: #666;
+ transition: transform 0.3s ease;
+ transform: rotate(0deg);
+
+ &.expanded {
+ transform: rotate(180deg);
+ }
+ }
+
+ &:active {
+ opacity: 0.7;
+ }
+ }
+ }
+ }
+ }
+
+ // Tab导航
+ .tab-nav {
+ margin: 0 40rpx;
+ margin-top: 40rpx;
+ white-space: nowrap;
+ width: 690rpx;
+
+ .tab-container {
+ display: flex;
+ min-width: 100%;
+
+ .tab-item {
+ padding: 10rpx 20rpx;
+ text-align: center;
+ color: #3e3a39;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ background-color: #94fafa66;
+ display: flex;
+ align-items: center;
+ flex-shrink: 0;
+ margin-right: 16rpx;
+
+ &:last-child {
+ margin-right: 0;
+ }
+
+ &.active {
+ background-color: #94fafa;
+ color: #525454;
+ font-size: 30rpx;
+ border-radius: 10rpx 10rpx 0 0;
+ font-weight: bold;
+ }
+
+ .tab-text {
+ font-size: 30rpx;
+ white-space: nowrap;
+ }
+ }
+ }
+ }
+
+ // Tab切换区域
+ .tab-section {
+ margin: 0 20rpx;
+ background-color: #fff;
+ border-radius: 20rpx;
+ overflow: hidden;
+ margin-bottom: calc(20px + constant(safe-area-inset-bottom));
+ margin-bottom: calc(20px + env(safe-area-inset-bottom));
+
+ // Tab内容
+ .tab-content {
+ padding: 30rpx;
+
+ .tab-panel {
+ min-height: 400rpx;
+
+ img {
+ width: 100%;
+ }
+
+ // 证书容器
+ .certificate-container {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ .certificate-image {
+ width: 100%;
+ max-width: 600rpx;
+ height: auto;
+ border-radius: 12rpx;
+ }
+ }
+
+ // 信息内容
+ .info-content {
+ padding: 20rpx 0;
+
+ .info-item {
+ display: flex;
+ margin-bottom: 20rpx;
+ align-items: flex-start;
+
+ .info-label {
+ font-size: 28rpx;
+ color: #666;
+ min-width: 160rpx;
+ flex-shrink: 0;
+ }
+
+ .info-value {
+ font-size: 28rpx;
+ color: #333;
+ flex: 1;
+ line-height: 1.5;
+ }
+ }
+ }
+
+ // 权益信息内容
+ .equity-info-content {
+ padding: 20rpx 0;
+
+ .equity-info-item {
+ display: flex;
+ margin-bottom: 20rpx;
+ align-items: flex-start;
+
+ .equity-info-label {
+ font-size: 28rpx;
+ color: #666;
+ min-width: 160rpx;
+ flex-shrink: 0;
+ }
+
+ .equity-info-value {
+ font-size: 28rpx;
+ color: #333;
+ flex: 1;
+ line-height: 1.5;
+ }
+ }
+
+ .equity-description {
+ margin-top: 30rpx;
+ padding: 20rpx;
+ background-color: #f8f9fa;
+ border-radius: 12rpx;
+
+ .description-text {
+ font-size: 26rpx;
+ color: #666;
+ line-height: 1.6;
+ }
+ }
+ }
+
+ // 权益详情列表
+ .equity-detail-list {
+ .equity-detail-item {
+ margin-bottom: 30rpx;
+ padding: 20rpx;
+ background: #f8f9fa;
+ border-radius: 12rpx;
+
+ .equity-name {
+ font-size: 28rpx;
+ color: #333;
+ font-weight: 600;
+ margin-bottom: 12rpx;
+ }
+
+ .equity-desc {
+ font-size: 26rpx;
+ color: #666;
+ line-height: 1.5;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // 立即购买按钮
+ .purchase-section {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: white;
+ padding: 20rpx 30rpx;
+ border-top: 1rpx solid #e5e5e5;
+ z-index: 100;
+ padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
+
+ .purchase-button {
+ width: 690rpx;
+ height: 88rpx;
+ margin: 0 auto;
+ background: #94fafa;
+ border-radius: 44rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ box-shadow: 0 8rpx 20rpx #94fafa;
+ transition: all 0.3s ease;
+
+ &:active {
+ transform: scale(0.98);
+ box-shadow: 0 4rpx 10rpx rgba(255, 30, 85, 0.2);
+ }
+
+ .purchase-text {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #525454;
+ }
+ }
+ }
+
+ // 为底部按钮预留空间
+ .detail-container {
+ padding-bottom: 140rpx;
+ }
+
+ .avatar {
+ width: 119rpx;
+ height: 119rpx;
+ border-radius: 50%;
+ }
+
+ .agent-info {
+ text-align: center;
+
+ .agent {
+ font-size: 18rpx;
+ }
+
+ .agent-name {
+ font-size: 28rpx;
+ font-weight: bold;
+ }
+
+ .agent-use {
+ font-size: 22rpx;
+ color: #00FFFF;
+ margin-top: 5rpx;
+ }
+ }
+
\ No newline at end of file
diff --git a/subPackages/other/evita.vue b/subPackages/other/evita.vue
index 832bcd5..b2c8562 100644
--- a/subPackages/other/evita.vue
+++ b/subPackages/other/evita.vue
@@ -2,8 +2,7 @@
-
-
+
@@ -16,15 +15,36 @@
},
data(){
return{
- img:''
+ img:'',
+ agentId:'',
+ agentInfo:null
}
},
- onLoad() {
+ onLoad(e) {
+ this.agentId = e.id
+ this.getInfo()
},
methods:{
+ getInfo(){
+ this.Post(
+ {
+ },
+ "/framework/agent/"+this.agentId,
+ "DES"
+ ).then((res) => {
+ if (res.code == 200) {
+ this.agentInfo = res.data
+ } else {
+ uni.showToast({
+ title: res.msg,
+ icon: "none",
+ });
+ }
+ });
+ },
toWebView() {
uni.navigateTo({
- url: "/pages/agent/index"
+ url: "/pages/agent/index?id="+this.agentId
});
},
@@ -35,5 +55,6 @@
\ No newline at end of file