flat:4.7暂存
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/unpackage/
|
34
App.vue
@@ -1,9 +1,9 @@
|
||||
<script setup>
|
||||
import { reactive, inject } from 'vue';
|
||||
import { reactive, inject, onMounted } from 'vue';
|
||||
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app';
|
||||
import useUserStore from './stores/useUserStore';
|
||||
import useDictStore from './stores/useDictStore';
|
||||
const { $api, navTo } = inject('globalFunction');
|
||||
const { $api, navTo, appendScriptTagElement } = inject('globalFunction');
|
||||
|
||||
onLaunch((options) => {
|
||||
useDictStore().getDictData();
|
||||
@@ -26,6 +26,19 @@ onLaunch((options) => {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
appendScriptTagElement('./static/js/jweixin-1.4.0.js').then(() => {
|
||||
console.log('✅ 微信 JSSDK 加载完成');
|
||||
});
|
||||
} else {
|
||||
appendScriptTagElement('/static/js/jweixin-1.4.0.js').then(() => {
|
||||
console.log('✅ 微信 JSSDK 加载完成');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
console.log('App Show');
|
||||
});
|
||||
@@ -39,7 +52,18 @@ onHide(() => {
|
||||
@import '@/common/common.css';
|
||||
/* 修改pages tabbar样式 H5有效 */
|
||||
.uni-tabbar .uni-tabbar__item:nth-child(4) .uni-tabbar__bd .uni-tabbar__icon {
|
||||
height: 100% !important;
|
||||
width: 80rpx !important;
|
||||
height: 78rpx !important;
|
||||
width: 78rpx !important;
|
||||
margin-top: -1rpx;
|
||||
}
|
||||
</style>
|
||||
.uni-tabbar-border {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
/* 提升toast层级 */
|
||||
uni-toast,
|
||||
uni-modal,
|
||||
.uni-modal,
|
||||
.uni-mask {
|
||||
z-index: 999;
|
||||
}
|
||||
</style>
|
@@ -34,6 +34,26 @@ html {
|
||||
|
||||
/* 布局调整 */
|
||||
|
||||
/* 点击动效 */
|
||||
/* 缩小 */
|
||||
.button-click {
|
||||
transition: transform 0.1s ease;
|
||||
}
|
||||
|
||||
.button-click:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
/* 背景变色 */
|
||||
.btn-light {
|
||||
color: white;
|
||||
border-radius: 16rpx;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.btn-light:active {
|
||||
background-color: #2980b9;
|
||||
}
|
||||
|
||||
/* 控制hover */
|
||||
.opctiy_8 {
|
||||
|
@@ -450,6 +450,32 @@ function sendingMiniProgramMessage(data = {
|
||||
});
|
||||
}
|
||||
|
||||
function copyText(text) {
|
||||
uni.setClipboardData({
|
||||
data: text,
|
||||
showToast: false,
|
||||
success(res) {
|
||||
msg('复制成功')
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function appendScriptTagElement(src) {
|
||||
if (!src) return null;
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.src = src;
|
||||
script.onload = () => {
|
||||
resolve()
|
||||
};
|
||||
script.onerror = () => {
|
||||
reject()
|
||||
};
|
||||
document.body.appendChild(script);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export const $api = {
|
||||
msg,
|
||||
prePage,
|
||||
@@ -461,7 +487,8 @@ export const $api = {
|
||||
insertSortData,
|
||||
uploadFile,
|
||||
formatFileSize,
|
||||
sendingMiniProgramMessage
|
||||
sendingMiniProgramMessage,
|
||||
copyText
|
||||
}
|
||||
|
||||
|
||||
@@ -485,5 +512,6 @@ export default {
|
||||
formatTotal,
|
||||
getWeeksOfMonth,
|
||||
isFutureDate,
|
||||
parseQueryParams
|
||||
parseQueryParams,
|
||||
appendScriptTagElement
|
||||
}
|
1
common/queue.js
Normal file
@@ -0,0 +1 @@
|
||||
const _count=Symbol("count");const _lowestCount=Symbol("lowestCount");const _items=Symbol("items");class Queue{constructor(){this[_count]=0;this[_lowestCount]=0;this[_items]={}}enqueue(element){this[_items][this[_count]]=element;this[_count]++}dequeue(){if(this.isEmpty())return undefined;const result=this[_items][this[_lowestCount]];delete this[_items][this[_lowestCount]];this[_lowestCount]++;return result}peek(){return this.isEmpty()?undefined:this[_items][this[_lowestCount]]}isEmpty(){return this[_count]-this[_lowestCount]===0}size(){return this[_count]-this[_lowestCount]}clear(){this[_count]=0;this[_lowestCount]=0;this[_items]={}}toString(){return Object.values(this[_items]).join(",")}}Object.freeze(Queue.prototype);const _dequeItems=Symbol("dequeItems");class Deque{constructor(){this[_items]={};this[_lowestCount]=0;this[_count]=0}addFront(element){if(this.isEmpty()){this.addBack(element)}else if(this[_lowestCount]>0){this[_lowestCount]--;this[_items][this[_lowestCount]]=element}else{for(let i=this[_count];i>0;i--){this[_items][i]=this[_items][i-1]}this[_items][0]=element;this[_count]++}}addBack(element){this[_items][this[_count]]=element;this[_count]++}removeFront(){if(this.isEmpty())return undefined;const result=this[_items][this[_lowestCount]];delete this[_items][this[_lowestCount]];this[_lowestCount]++;return result}removeBack(){if(this.isEmpty())return undefined;this[_count]--;const result=this[_items][this[_count]];delete this[_items][this[_count]];return result}peekFront(){return this.isEmpty()?undefined:this[_items][this[_lowestCount]]}peekBack(){return this.isEmpty()?undefined:this[_items][this[_count]-1]}isEmpty(){return this[_count]-this[_lowestCount]===0}size(){return this[_count]-this[_lowestCount]}clear(){this[_items]={};this[_lowestCount]=0;this[_count]=0}toString(){return Object.values(this[_items]).join(",")}}Object.freeze(Deque.prototype);export{Queue,Deque};
|
@@ -59,6 +59,10 @@ const handleItemClick = (e) => {
|
||||
margin-top: -40rpx;
|
||||
}
|
||||
}
|
||||
p {
|
||||
font-weight: 500;
|
||||
line-height: 44.8rpx;
|
||||
}
|
||||
}
|
||||
.markdown-body {
|
||||
user-select: text;
|
||||
|
13
config.js
@@ -1,14 +1,19 @@
|
||||
export default {
|
||||
baseUrl: 'http://39.98.44.136:8080', // 测试
|
||||
// baseUrl: 'http://39.98.44.136:8080', // 测试
|
||||
baseUrl: 'https://qd.zhaopinzao8dian.com/api', // 测试
|
||||
// sseAI+
|
||||
StreamBaseURl: 'http://39.98.44.136:8000',
|
||||
// StreamBaseURl: 'http://39.98.44.136:8000',
|
||||
StreamBaseURl: 'https://qd.zhaopinzao8dian.com/ai',
|
||||
// 语音转文字
|
||||
vioceBaseURl: 'ws://39.98.44.136:6006/speech-recognition',
|
||||
DBversion: 3,
|
||||
// vioceBaseURl: 'ws://39.98.44.136:8080/speech-recognition',
|
||||
vioceBaseURl: 'wss://qd.zhaopinzao8dian.com/api/speech-recognition',
|
||||
DBversion: 2,
|
||||
// 应用信息
|
||||
appInfo: {
|
||||
// 应用名称
|
||||
name: "青岛市就业服务",
|
||||
// 地区名
|
||||
areaName: '青岛市',
|
||||
// AI名称
|
||||
AIName: '小红',
|
||||
// 应用版本
|
||||
|
@@ -3,72 +3,121 @@ import {
|
||||
onUnmounted
|
||||
} from 'vue';
|
||||
|
||||
export function useAudioRecorder(wsUrl) {
|
||||
function mergeText(prevText, newText) {
|
||||
if (newText.startsWith(prevText)) {
|
||||
return newText; // 直接替换,避免重复拼接
|
||||
}
|
||||
return prevText + newText; // 兼容意外情况
|
||||
}
|
||||
|
||||
export function useAudioRecorder(wsUrl) {
|
||||
// 状态变量
|
||||
const isRecording = ref(false);
|
||||
const isStopping = ref(false);
|
||||
const isSocketConnected = ref(false);
|
||||
const recordingDuration = ref(0);
|
||||
const bufferPressure = ref(0); // 缓冲区压力 (0-100)
|
||||
const currentInterval = ref(0); // 当前发送间隔
|
||||
const audioDataForDisplay = ref(new Array(16).fill(0.01));
|
||||
const volumeLevel = ref(0);
|
||||
|
||||
// 音频相关
|
||||
const audioContext = ref(null);
|
||||
const mediaStream = ref(null);
|
||||
const workletNode = ref(null);
|
||||
const analyser = ref(null);
|
||||
|
||||
// 网络相关
|
||||
const socket = ref(null);
|
||||
const audioBuffer = ref([]);
|
||||
const bufferInterval = ref(null);
|
||||
|
||||
// 配置常量
|
||||
const SAMPLE_RATE = 16000;
|
||||
const BASE_INTERVAL_MS = 300; // 基础发送间隔
|
||||
const MIN_INTERVAL_MS = 100; // 最小发送间隔
|
||||
const MAX_BUFFER_SIZE = 20; // 最大缓冲区块数
|
||||
const PRESSURE_THRESHOLD = 0.7; // 加快发送的阈值 (70%)
|
||||
const SILENCE_THRESHOLD = 0.02; // 静音阈值 (0-1)
|
||||
const SILENCE_DURATION = 400; // 静音持续时间(ms)后切片
|
||||
const MIN_SOUND_DURATION = 300; // 最小有效声音持续时间(ms)
|
||||
|
||||
// 音频处理变量
|
||||
const lastSoundTime = ref(0);
|
||||
const audioChunks = ref([]);
|
||||
const currentChunkStartTime = ref(0);
|
||||
const silenceStartTime = ref(0);
|
||||
|
||||
// 语音识别结果
|
||||
const recognizedText = ref('');
|
||||
const lastFinalText = ref(''); // 保存最终确认的文本
|
||||
|
||||
// AudioWorklet处理器代码
|
||||
const workletProcessorCode = `
|
||||
class AudioProcessor extends AudioWorkletProcessor {
|
||||
constructor(options) {
|
||||
super();
|
||||
this.sampleRate = options.processorOptions.sampleRate;
|
||||
this.samplesPerChunk = Math.floor(this.sampleRate * 0.1); // 每100ms的样本数
|
||||
this.buffer = new Int16Array(this.samplesPerChunk);
|
||||
this.index = 0;
|
||||
}
|
||||
|
||||
process(inputs) {
|
||||
const input = inputs[0];
|
||||
if (input.length > 0) {
|
||||
const inputChannel = input[0];
|
||||
|
||||
for (let i = 0; i < inputChannel.length; i++) {
|
||||
// 转换为16位PCM
|
||||
this.buffer[this.index++] = Math.max(-32768, Math.min(32767, inputChannel[i] * 32767));
|
||||
|
||||
// 当缓冲区满时发送
|
||||
if (this.index >= this.samplesPerChunk) {
|
||||
this.port.postMessage({
|
||||
audioData: this.buffer.buffer,
|
||||
timestamp: Date.now()
|
||||
}, [this.buffer.buffer]);
|
||||
|
||||
// 创建新缓冲区
|
||||
class AudioProcessor extends AudioWorkletProcessor {
|
||||
constructor(options) {
|
||||
super();
|
||||
this.silenceThreshold = options.processorOptions.silenceThreshold;
|
||||
this.sampleRate = options.processorOptions.sampleRate;
|
||||
this.samplesPerChunk = Math.floor(this.sampleRate * 0.05); // 50ms的块
|
||||
this.buffer = new Int16Array(this.samplesPerChunk);
|
||||
this.index = 0;
|
||||
}
|
||||
this.lastUpdate = 0;
|
||||
}
|
||||
|
||||
calculateVolume(inputs) {
|
||||
const input = inputs[0];
|
||||
if (!input || input.length === 0) return 0;
|
||||
|
||||
let sum = 0;
|
||||
const inputChannel = input[0];
|
||||
for (let i = 0; i < inputChannel.length; i++) {
|
||||
sum += inputChannel[i] * inputChannel[i];
|
||||
}
|
||||
return Math.sqrt(sum / inputChannel.length);
|
||||
}
|
||||
|
||||
process(inputs) {
|
||||
const now = currentTime;
|
||||
const volume = this.calculateVolume(inputs);
|
||||
|
||||
// 每50ms发送一次分析数据
|
||||
if (now - this.lastUpdate > 0.05) {
|
||||
this.lastUpdate = now;
|
||||
|
||||
// 简单的频率分析 (模拟16个频段)
|
||||
const simulatedFreqData = [];
|
||||
for (let i = 0; i < 16; i++) {
|
||||
simulatedFreqData.push(
|
||||
Math.min(1, volume * 10 + (Math.random() * 0.2 - 0.1))
|
||||
);
|
||||
}
|
||||
|
||||
this.port.postMessage({
|
||||
type: 'analysis',
|
||||
volume: volume,
|
||||
frequencyData: simulatedFreqData,
|
||||
isSilent: volume < this.silenceThreshold,
|
||||
timestamp: now
|
||||
});
|
||||
}
|
||||
|
||||
// 原始音频处理
|
||||
const input = inputs[0];
|
||||
if (input && input.length > 0) {
|
||||
const inputChannel = input[0];
|
||||
for (let i = 0; i < inputChannel.length; i++) {
|
||||
this.buffer[this.index++] = Math.max(-32768, Math.min(32767, inputChannel[i] * 32767));
|
||||
|
||||
if (this.index >= this.samplesPerChunk) {
|
||||
this.port.postMessage({
|
||||
type: 'audio',
|
||||
audioData: this.buffer.buffer,
|
||||
timestamp: now
|
||||
}, [this.buffer.buffer]);
|
||||
|
||||
this.buffer = new Int16Array(this.samplesPerChunk);
|
||||
this.index = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
registerProcessor('audio-processor', AudioProcessor);
|
||||
`;
|
||||
registerProcessor('audio-processor', AudioProcessor);
|
||||
`;
|
||||
|
||||
// 初始化WebSocket连接
|
||||
const initSocket = (wsUrl) => {
|
||||
@@ -77,77 +126,91 @@ export function useAudioRecorder(wsUrl) {
|
||||
|
||||
socket.value.onopen = () => {
|
||||
isSocketConnected.value = true;
|
||||
console.log('WebSocket连接已建立');
|
||||
resolve();
|
||||
};
|
||||
|
||||
socket.value.onerror = (error) => {
|
||||
console.error('WebSocket连接错误:', error);
|
||||
reject(error);
|
||||
};
|
||||
|
||||
socket.value.onclose = (event) => {
|
||||
console.log(`WebSocket连接关闭,代码: ${event.code}, 原因: ${event.reason}`);
|
||||
socket.value.onclose = () => {
|
||||
isSocketConnected.value = false;
|
||||
console.log('WebSocket连接已关闭');
|
||||
};
|
||||
|
||||
socket.value.onmessage = handleMessage;
|
||||
});
|
||||
};
|
||||
|
||||
// 计算动态发送间隔
|
||||
const calculateDynamicInterval = () => {
|
||||
const pressureFactor = bufferPressure.value / 100;
|
||||
// 压力越大,间隔越小(发送越快)
|
||||
return Math.max(
|
||||
MIN_INTERVAL_MS,
|
||||
BASE_INTERVAL_MS - (pressureFactor * (BASE_INTERVAL_MS - MIN_INTERVAL_MS))
|
||||
);
|
||||
const handleMessage = (values) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
if (data.text) {
|
||||
const {
|
||||
asrEnd,
|
||||
text
|
||||
} = data
|
||||
if (asrEnd === 'true') {
|
||||
recognizedText.value += data.text;
|
||||
} else {
|
||||
lastFinalText.value = '';
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('解析识别结果失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理音频切片
|
||||
const processAudioChunk = (isSilent) => {
|
||||
const now = Date.now();
|
||||
|
||||
if (!isSilent) {
|
||||
// 检测到声音
|
||||
lastSoundTime.value = now;
|
||||
|
||||
if (silenceStartTime.value > 0) {
|
||||
// 从静音恢复到有声音
|
||||
silenceStartTime.value = 0;
|
||||
}
|
||||
} else {
|
||||
// 静音状态
|
||||
if (silenceStartTime.value === 0) {
|
||||
silenceStartTime.value = now;
|
||||
}
|
||||
|
||||
// 检查是否达到静音切片条件
|
||||
if (now - silenceStartTime.value >= SILENCE_DURATION &&
|
||||
now - currentChunkStartTime.value >= MIN_SOUND_DURATION) {
|
||||
sendCurrentChunk();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 发送缓冲的音频数据
|
||||
const sendBufferedAudio = () => {
|
||||
if (audioBuffer.value.length === 0 || !socket.value || socket.value.readyState !== WebSocket.OPEN) {
|
||||
// 发送当前音频块
|
||||
const sendCurrentChunk = () => {
|
||||
if (audioChunks.value.length === 0 || !socket.value || socket.value.readyState !== WebSocket.OPEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 将缓冲区大小限制为8000字节 (小于8192)
|
||||
const MAX_CHUNK_SIZE = 8000 / 2; // 16位 = 2字节,所以4000个样本
|
||||
// 合并所有块
|
||||
const totalBytes = audioChunks.value.reduce((total, chunk) => total + chunk.byteLength, 0);
|
||||
const combined = new Int16Array(totalBytes / 2);
|
||||
let offset = 0;
|
||||
|
||||
let samplesToSend = [];
|
||||
let totalSamples = 0;
|
||||
audioChunks.value.forEach(chunk => {
|
||||
const samples = new Int16Array(chunk);
|
||||
combined.set(samples, offset);
|
||||
offset += samples.length;
|
||||
});
|
||||
|
||||
// 收集不超过限制的样本
|
||||
while (audioBuffer.value.length > 0 && totalSamples < MAX_CHUNK_SIZE) {
|
||||
const buffer = audioBuffer.value[0];
|
||||
const samples = new Int16Array(buffer);
|
||||
const remainingSpace = MAX_CHUNK_SIZE - totalSamples;
|
||||
|
||||
if (samples.length <= remainingSpace) {
|
||||
samplesToSend.push(samples);
|
||||
totalSamples += samples.length;
|
||||
audioBuffer.value.shift();
|
||||
} else {
|
||||
// 只取部分样本
|
||||
samplesToSend.push(samples.slice(0, remainingSpace));
|
||||
audioBuffer.value[0] = samples.slice(remainingSpace).buffer;
|
||||
totalSamples = MAX_CHUNK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
// 合并样本并发送
|
||||
if (totalSamples > 0) {
|
||||
const combined = new Int16Array(totalSamples);
|
||||
let offset = 0;
|
||||
|
||||
samplesToSend.forEach(chunk => {
|
||||
combined.set(chunk, offset);
|
||||
offset += chunk.length;
|
||||
});
|
||||
|
||||
socket.value.send(combined.buffer);
|
||||
}
|
||||
// 发送合并后的数据
|
||||
socket.value.send(combined.buffer);
|
||||
audioChunks.value = [];
|
||||
|
||||
// 记录新块的开始时间
|
||||
currentChunkStartTime.value = Date.now();
|
||||
silenceStartTime.value = 0;
|
||||
} catch (error) {
|
||||
console.error('发送音频数据时出错:', error);
|
||||
}
|
||||
@@ -158,31 +221,34 @@ export function useAudioRecorder(wsUrl) {
|
||||
if (isRecording.value) return;
|
||||
|
||||
try {
|
||||
// 重置状态
|
||||
recognizedText.value = '';
|
||||
lastFinalText.value = '';
|
||||
// 重置状态
|
||||
recordingDuration.value = 0;
|
||||
audioBuffer.value = [];
|
||||
bufferPressure.value = 0;
|
||||
currentInterval.value = BASE_INTERVAL_MS;
|
||||
console.log('正在初始化WebSocket连接...');
|
||||
audioChunks.value = [];
|
||||
lastSoundTime.value = 0;
|
||||
currentChunkStartTime.value = Date.now();
|
||||
silenceStartTime.value = 0;
|
||||
|
||||
// 初始化WebSocket
|
||||
await initSocket(wsUrl);
|
||||
console.log('正在获取音频设备权限...');
|
||||
|
||||
// 获取音频流
|
||||
mediaStream.value = await navigator.mediaDevices.getUserMedia({
|
||||
audio: {
|
||||
sampleRate: SAMPLE_RATE,
|
||||
channelCount: 1,
|
||||
echoCancellation: false,
|
||||
noiseSuppression: false,
|
||||
echoCancellation: true,
|
||||
noiseSuppression: true,
|
||||
autoGainControl: false
|
||||
},
|
||||
video: false
|
||||
});
|
||||
console.log('正在初始化音频上下文...');
|
||||
|
||||
// 创建音频上下文
|
||||
audioContext.value = new(window.AudioContext || window.webkitAudioContext)({
|
||||
sampleRate: SAMPLE_RATE,
|
||||
latencyHint: 'interactive'
|
||||
sampleRate: SAMPLE_RATE
|
||||
});
|
||||
|
||||
// 注册AudioWorklet
|
||||
@@ -195,23 +261,20 @@ export function useAudioRecorder(wsUrl) {
|
||||
|
||||
// 创建AudioWorkletNode
|
||||
workletNode.value = new AudioWorkletNode(audioContext.value, 'audio-processor', {
|
||||
numberOfInputs: 1,
|
||||
numberOfOutputs: 1,
|
||||
outputChannelCount: [1],
|
||||
processorOptions: {
|
||||
silenceThreshold: SILENCE_THRESHOLD,
|
||||
sampleRate: SAMPLE_RATE
|
||||
}
|
||||
});
|
||||
|
||||
// 处理音频数据
|
||||
workletNode.value.port.onmessage = (e) => {
|
||||
if (e.data.audioData instanceof ArrayBuffer) {
|
||||
audioBuffer.value.push(e.data.audioData);
|
||||
|
||||
// 当缓冲区压力超过阈值时立即尝试发送
|
||||
if (audioBuffer.value.length / MAX_BUFFER_SIZE > PRESSURE_THRESHOLD) {
|
||||
sendBufferedAudio();
|
||||
}
|
||||
if (e.data.type === 'audio') {
|
||||
audioChunks.value.push(e.data.audioData);
|
||||
} else if (e.data.type === 'analysis') {
|
||||
audioDataForDisplay.value = e.data.frequencyData;
|
||||
volumeLevel.value = e.data.volume;
|
||||
processAudioChunk(e.data.isSilent);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -220,12 +283,7 @@ export function useAudioRecorder(wsUrl) {
|
||||
source.connect(workletNode.value);
|
||||
workletNode.value.connect(audioContext.value.destination);
|
||||
|
||||
// 启动定时发送
|
||||
bufferInterval.value = setInterval(sendBufferedAudio, currentInterval.value);
|
||||
console.log('录音初始化完成,开始录制');
|
||||
// 更新状态
|
||||
isRecording.value = true;
|
||||
console.log(`开始录音,采样率: ${audioContext.value.sampleRate}Hz`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('启动录音失败:', error);
|
||||
@@ -234,39 +292,27 @@ export function useAudioRecorder(wsUrl) {
|
||||
}
|
||||
};
|
||||
|
||||
// 停止录音并保存
|
||||
// 停止录音
|
||||
const stopRecording = async () => {
|
||||
if (!isRecording.value || isStopping.value) return;
|
||||
|
||||
isStopping.value = true;
|
||||
|
||||
try {
|
||||
// 停止定时器
|
||||
if (bufferInterval.value) {
|
||||
clearInterval(bufferInterval.value);
|
||||
bufferInterval.value = null;
|
||||
}
|
||||
|
||||
// 发送剩余音频数据
|
||||
if (audioBuffer.value.length > 0) {
|
||||
console.log(`正在发送剩余 ${audioBuffer.value.length} 个音频块...`);
|
||||
sendBufferedAudio();
|
||||
}
|
||||
// 发送最后一个音频块(无论是否静音)
|
||||
sendCurrentChunk();
|
||||
|
||||
// 发送结束标记
|
||||
if (socket.value?.readyState === WebSocket.OPEN) {
|
||||
console.log('发送结束标记...');
|
||||
socket.value.send(JSON.stringify({
|
||||
action: 'end',
|
||||
duration: recordingDuration.value
|
||||
}));
|
||||
|
||||
// 等待数据发送完成
|
||||
await new Promise((resolve) => {
|
||||
await new Promise(resolve => {
|
||||
if (socket.value.bufferedAmount === 0) {
|
||||
resolve();
|
||||
} else {
|
||||
console.log(`等待 ${socket.value.bufferedAmount} 字节数据发送...`);
|
||||
const timer = setInterval(() => {
|
||||
if (socket.value.bufferedAmount === 0) {
|
||||
clearInterval(timer);
|
||||
@@ -275,14 +321,10 @@ export function useAudioRecorder(wsUrl) {
|
||||
}, 50);
|
||||
}
|
||||
});
|
||||
|
||||
// 关闭连接
|
||||
console.log('正在关闭WebSocket连接...');
|
||||
socket.value.close();
|
||||
}
|
||||
|
||||
cleanup();
|
||||
console.log('录音已停止并保存');
|
||||
|
||||
} catch (error) {
|
||||
console.error('停止录音时出错:', error);
|
||||
@@ -292,20 +334,33 @@ export function useAudioRecorder(wsUrl) {
|
||||
}
|
||||
};
|
||||
|
||||
// 取消录音
|
||||
// 清理资源
|
||||
const cleanup = () => {
|
||||
if (mediaStream.value) {
|
||||
mediaStream.value.getTracks().forEach(track => track.stop());
|
||||
mediaStream.value = null;
|
||||
}
|
||||
|
||||
if (workletNode.value) {
|
||||
workletNode.value.disconnect();
|
||||
workletNode.value = null;
|
||||
}
|
||||
|
||||
if (audioContext.value && audioContext.value.state !== 'closed') {
|
||||
audioContext.value.close();
|
||||
audioContext.value = null;
|
||||
}
|
||||
|
||||
audioChunks.value = [];
|
||||
isRecording.value = false;
|
||||
isSocketConnected.value = false;
|
||||
};
|
||||
|
||||
/// 取消录音
|
||||
const cancelRecording = async () => {
|
||||
if (!isRecording.value || isStopping.value) return;
|
||||
|
||||
isStopping.value = true;
|
||||
|
||||
try {
|
||||
// 停止定时器
|
||||
if (bufferInterval.value) {
|
||||
clearInterval(bufferInterval.value);
|
||||
bufferInterval.value = null;
|
||||
}
|
||||
|
||||
// 发送取消标记
|
||||
if (socket.value?.readyState === WebSocket.OPEN) {
|
||||
console.log('发送结束标记...');
|
||||
socket.value.send(JSON.stringify({
|
||||
@@ -313,11 +368,7 @@ export function useAudioRecorder(wsUrl) {
|
||||
}));
|
||||
socket.value.close();
|
||||
}
|
||||
console.log('清理资源...');
|
||||
cleanup();
|
||||
console.log('录音已成功停止');
|
||||
console.log('录音已取消');
|
||||
|
||||
cleanup()
|
||||
} catch (error) {
|
||||
console.error('取消录音时出错:', error);
|
||||
throw error;
|
||||
@@ -326,51 +377,9 @@ export function useAudioRecorder(wsUrl) {
|
||||
}
|
||||
};
|
||||
|
||||
// 清理资源
|
||||
const cleanup = () => {
|
||||
// 清除定时器
|
||||
if (bufferInterval.value) {
|
||||
clearInterval(bufferInterval.value);
|
||||
bufferInterval.value = null;
|
||||
}
|
||||
|
||||
// 关闭音频流
|
||||
if (mediaStream.value) {
|
||||
console.log('正在停止媒体流...');
|
||||
mediaStream.value.getTracks().forEach(track => track.stop());
|
||||
mediaStream.value = null;
|
||||
}
|
||||
|
||||
// 断开音频节点
|
||||
if (workletNode.value) {
|
||||
workletNode.value.disconnect();
|
||||
workletNode.value.port.onmessage = null;
|
||||
workletNode.value = null;
|
||||
}
|
||||
|
||||
// 关闭音频上下文
|
||||
if (audioContext.value) {
|
||||
if (audioContext.value.state !== 'closed') {
|
||||
audioContext.value.close().catch(e => {
|
||||
console.warn('关闭AudioContext时出错:', e);
|
||||
});
|
||||
}
|
||||
audioContext.value = null;
|
||||
}
|
||||
|
||||
// 清空缓冲区
|
||||
audioBuffer.value = [];
|
||||
bufferPressure.value = 0;
|
||||
|
||||
// 重置状态
|
||||
isRecording.value = false;
|
||||
isSocketConnected.value = false;
|
||||
};
|
||||
|
||||
// 组件卸载时自动清理
|
||||
onUnmounted(() => {
|
||||
if (isRecording.value) {
|
||||
cancelRecording();
|
||||
stopRecording();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -379,97 +388,12 @@ export function useAudioRecorder(wsUrl) {
|
||||
isStopping,
|
||||
isSocketConnected,
|
||||
recordingDuration,
|
||||
bufferPressure,
|
||||
currentInterval,
|
||||
audioDataForDisplay,
|
||||
volumeLevel,
|
||||
startRecording,
|
||||
stopRecording,
|
||||
recognizedText,
|
||||
lastFinalText,
|
||||
cancelRecording
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// import {
|
||||
// ref
|
||||
// } from 'vue'
|
||||
// export function useRealtimeRecorder(wsUrl) {
|
||||
// const isRecording = ref(false)
|
||||
// const mediaRecorder = ref(null)
|
||||
// const socket = ref(null)
|
||||
// const recognizedText = ref('')
|
||||
|
||||
// const startRecording = async () => {
|
||||
// if (!navigator.mediaDevices?.getUserMedia) {
|
||||
// uni.showToast({
|
||||
// title: '当前环境不支持录音',
|
||||
// icon: 'none'
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
// recognizedText.value = ''
|
||||
// const stream = await navigator.mediaDevices.getUserMedia({
|
||||
// audio: {
|
||||
// sampleRate: 16000,
|
||||
// channelCount: 1,
|
||||
// echoCancellation: false,
|
||||
// noiseSuppression: false,
|
||||
// autoGainControl: false
|
||||
// },
|
||||
// video: false
|
||||
// })
|
||||
// socket.value = new WebSocket(wsUrl)
|
||||
|
||||
// socket.value.onopen = () => {
|
||||
// console.log('[WebSocket] 连接已建立')
|
||||
// }
|
||||
|
||||
// socket.value.onmessage = (event) => {
|
||||
// recognizedText.value = JSON.parse(event.data).text
|
||||
// }
|
||||
|
||||
// const recorder = new MediaRecorder(stream, {
|
||||
// mimeType: 'audio/webm;codecs=opus',
|
||||
// audioBitsPerSecond: 16000,
|
||||
// })
|
||||
|
||||
// recorder.ondataavailable = (e) => {
|
||||
// if (e.data.size > 0 && socket.value?.readyState === WebSocket.OPEN) {
|
||||
// socket.value.send(e.data)
|
||||
// }
|
||||
// }
|
||||
|
||||
// recorder.start(300) // 每 300ms 发送一段数据
|
||||
// mediaRecorder.value = recorder
|
||||
// isRecording.value = true
|
||||
// }
|
||||
|
||||
// const stopRecording = () => {
|
||||
// mediaRecorder.value?.stop()
|
||||
// mediaRecorder.value = null
|
||||
// isRecording.value = false
|
||||
|
||||
// if (socket.value?.readyState === WebSocket.OPEN) {
|
||||
// socket.value.send('[end]')
|
||||
// socket.value.close()
|
||||
// }
|
||||
// }
|
||||
|
||||
// const cancelRecording = () => {
|
||||
// mediaRecorder.value?.stop()
|
||||
// mediaRecorder.value = null
|
||||
// isRecording.value = false
|
||||
// recognizedText.value = ''
|
||||
|
||||
// if (socket.value?.readyState === WebSocket.OPEN) {
|
||||
// socket.value.send('[cancel]')
|
||||
// socket.value.close()
|
||||
// }
|
||||
// }
|
||||
|
||||
// return {
|
||||
// isRecording,
|
||||
// recognizedText,
|
||||
// startRecording,
|
||||
// stopRecording,
|
||||
// cancelRecording
|
||||
// }
|
||||
// }
|
||||
}
|
109
hook/useSpeechReader.js
Normal file
@@ -0,0 +1,109 @@
|
||||
import {
|
||||
ref,
|
||||
onBeforeUnmount,
|
||||
onMounted
|
||||
} from 'vue'
|
||||
import {
|
||||
onHide,
|
||||
onUnload
|
||||
} from '@dcloudio/uni-app'
|
||||
|
||||
function formatTextForSpeech(rawText) {
|
||||
return rawText
|
||||
// 去除链接 markdown 格式 [xxx](url)
|
||||
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
|
||||
// 去除 Markdown 语法符号
|
||||
.replace(/[*_`>#\-]/g, '')
|
||||
// 将换行转换为句号
|
||||
.replace(/\n+/g, '。')
|
||||
// 多个标点统一转为句号(表示停顿)
|
||||
.replace(/[。,,.、!!??;;::~~…··\-\/\\]{1,}/g, '。')
|
||||
// 合并多个句号
|
||||
.replace(/([。]{2,})/g, '。')
|
||||
// 去除多余空格
|
||||
.replace(/\s+/g, ' ')
|
||||
// 去除开头结尾的句号
|
||||
.replace(/^[。]+|[。]+$/g, '')
|
||||
.trim()
|
||||
}
|
||||
|
||||
export function useSpeechReader() {
|
||||
const isSpeaking = ref(false)
|
||||
const isPaused = ref(false)
|
||||
let utterance = null
|
||||
|
||||
const cleanMarkdown = (text) => {
|
||||
return formatTextForSpeech(text)
|
||||
}
|
||||
|
||||
const speak = (text, options = {
|
||||
lang: 'zh-CN',
|
||||
rate: 0.9,
|
||||
pitch: 1.2
|
||||
}) => {
|
||||
cancel() // 重置之前的
|
||||
const voices = speechSynthesis.getVoices()
|
||||
const chineseVoices = voices.filter(v => v.lang.includes('zh'))
|
||||
// console.log(chineseVoices.map((item) => item.name))
|
||||
const cleanText = cleanMarkdown(text)
|
||||
utterance = new SpeechSynthesisUtterance(cleanText)
|
||||
// utterance.voice = chineseVoices.find(v => v.name === 'Shelley')
|
||||
utterance.lang = options.lang || 'zh-CN'
|
||||
utterance.rate = options.rate || 1
|
||||
utterance.pitch = options.pitch || 1.1 // 音调(0 - 2,偏高比较柔和)
|
||||
|
||||
utterance.onend = () => {
|
||||
isSpeaking.value = false
|
||||
isPaused.value = false
|
||||
}
|
||||
|
||||
speechSynthesis.speak(utterance)
|
||||
isSpeaking.value = true
|
||||
isPaused.value = false
|
||||
}
|
||||
|
||||
const pause = () => {
|
||||
if (isSpeaking.value && !isPaused.value) {
|
||||
speechSynthesis.pause()
|
||||
isPaused.value = true
|
||||
}
|
||||
}
|
||||
|
||||
const resume = () => {
|
||||
if (isSpeaking.value && isPaused.value) {
|
||||
speechSynthesis.resume()
|
||||
isPaused.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
speechSynthesis.cancel()
|
||||
isSpeaking.value = false
|
||||
isPaused.value = false
|
||||
}
|
||||
// 页面刷新/关闭时
|
||||
onMounted(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.addEventListener('beforeunload', cancel)
|
||||
}
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
cancel()
|
||||
if (typeof window !== 'undefined') {
|
||||
window.removeEventListener('beforeunload', cancel)
|
||||
}
|
||||
})
|
||||
|
||||
onHide(cancel)
|
||||
onUnload(cancel)
|
||||
|
||||
return {
|
||||
speak,
|
||||
pause,
|
||||
resume,
|
||||
cancel,
|
||||
isSpeaking,
|
||||
isPaused,
|
||||
}
|
||||
}
|
@@ -18,12 +18,12 @@
|
||||
</script>
|
||||
<title></title>
|
||||
<!-- vconsole -->
|
||||
<!--<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
|
||||
<script>
|
||||
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
|
||||
<!-- <script>
|
||||
var vConsole = new window.VConsole();
|
||||
vConsole.destroy();
|
||||
</script -->
|
||||
<script type="text/javascript" src="./lib/jweixin-1.4.0.js"></script>
|
||||
</script>
|
||||
<script type="text/javascript" src="./static/js/jweixin-1.4.0.js"></script> -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
|
@@ -120,14 +120,14 @@
|
||||
]
|
||||
}],
|
||||
"tabBar": {
|
||||
"color": "#7A7E83",
|
||||
"color": "#5E5F60",
|
||||
"selectedColor": "#256BFA",
|
||||
"borderStyle": "black",
|
||||
"backgroundColor": "#ffffff",
|
||||
"midButton": {
|
||||
"width": "50px",
|
||||
"height": "50px",
|
||||
"backgroundImage": "static/tabbar/logo2.png"
|
||||
"backgroundImage": "static/tabbar/logo2copy.png"
|
||||
},
|
||||
"list": [{
|
||||
"pagePath": "pages/index/index",
|
||||
@@ -143,8 +143,8 @@
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/chat/chat",
|
||||
"iconPath": "static/tabbar/logo2.png",
|
||||
"selectedIconPath": "static/tabbar/logo2.png"
|
||||
"iconPath": "static/tabbar/logo2copy.png",
|
||||
"selectedIconPath": "static/tabbar/logo2copy.png"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/msglog/msglog",
|
||||
|
@@ -37,9 +37,14 @@
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="drawer-user">
|
||||
<image class="drawer-user-img" src="/static/icon/boy.png"></image>
|
||||
<text>用户123</text>
|
||||
<image class="drawer-user-setting" src="/static/icon/setting.png" mode=""></image>
|
||||
<image class="drawer-user-img" v-if="userInfo.age === '0'" src="/static/icon/boy.png"></image>
|
||||
<image class="drawer-user-img" v-else src="/static/icon/girl.png"></image>
|
||||
<text>{{ userInfo.name || '暂无用户名' }}</text>
|
||||
<image
|
||||
class="drawer-user-setting button-click"
|
||||
src="/static/icon/setting.png"
|
||||
@click="updateSetting"
|
||||
></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -64,11 +69,13 @@
|
||||
<script setup>
|
||||
import { ref, inject, nextTick, computed } from 'vue';
|
||||
const { $api, navTo, insertSortData } = inject('globalFunction');
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||
import { onLoad, onShow, onHide } from '@dcloudio/uni-app';
|
||||
import useChatGroupDBStore from '@/stores/userChatGroupStore';
|
||||
import useUserStore from '@/stores/useUserStore';
|
||||
import aiPaging from './components/ai-paging.vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
const { isTyping, tabeList, chatSessionID } = storeToRefs(useChatGroupDBStore());
|
||||
const { userInfo } = storeToRefs(useUserStore());
|
||||
const isDrawerOpen = ref(false);
|
||||
const scrollIntoView = ref(false);
|
||||
import config from '@/config';
|
||||
@@ -94,12 +101,17 @@ onShow(() => {
|
||||
});
|
||||
});
|
||||
|
||||
onHide(() => {
|
||||
paging.value?.handleTouchCancel();
|
||||
});
|
||||
|
||||
const toggleDrawer = () => {
|
||||
isDrawerOpen.value = !isDrawerOpen.value;
|
||||
};
|
||||
|
||||
const addNewDialogue = () => {
|
||||
$api.msg('新对话');
|
||||
paging.value?.changeQueries();
|
||||
useChatGroupDBStore().addNewDialogue();
|
||||
};
|
||||
|
||||
@@ -113,6 +125,9 @@ const changeDialogue = (item) => {
|
||||
});
|
||||
}
|
||||
};
|
||||
function updateSetting() {
|
||||
$api.msg('该功能正在开发中,敬请期待后续更新!');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
@@ -190,13 +205,14 @@ const changeDialogue = (item) => {
|
||||
position: relative
|
||||
margin-bottom: constant(safe-area-inset-bottom); /*兼容 IOS<11.2*/
|
||||
margin-bottom: env(safe-area-inset-bottom); /*兼容 IOS>11.2*/
|
||||
color: #000000
|
||||
.drawer-user-img
|
||||
width: 57.2rpx;
|
||||
height: 57.2rpx
|
||||
margin-right: 20rpx
|
||||
.drawer-user-setting
|
||||
width: 57.2rpx;
|
||||
height: 57.2rpx
|
||||
width: 48rpx
|
||||
height: 48rpx
|
||||
position: absolute
|
||||
top: 50%
|
||||
right: 28rpx
|
||||
@@ -267,7 +283,7 @@ const changeDialogue = (item) => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between
|
||||
font-size: 28rpx
|
||||
font-size: 32rpx
|
||||
color: #000000
|
||||
padding: 0 30rpx;
|
||||
font-weight: bold
|
||||
|
273
pages/chat/components/WaveDisplay.vue
Normal file
@@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<view class="wave-container active" :style="{ background }">
|
||||
<!-- 波形显示区域 -->
|
||||
<view class="wave">
|
||||
<view
|
||||
v-for="(bar, index) in waveBars"
|
||||
:key="index"
|
||||
class="wave-bar"
|
||||
:style="{
|
||||
height: `${bar.height}px`,
|
||||
backgroundColor: bar.color,
|
||||
borderRadius: `${bar.borderRadius}px`,
|
||||
}"
|
||||
></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch, computed, onMounted, onUnmounted } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
// 是否激活显示
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 音频数据数组 (0-1之间的值)
|
||||
audioData: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
// 是否显示录音信息
|
||||
showInfo: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 录音时间 (秒)
|
||||
recordingTime: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
// 是否显示取消提示
|
||||
showCancelTip: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// 是否处于取消状态
|
||||
isCanceling: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
background: {
|
||||
type: String,
|
||||
default: 'linear-gradient(to right, #377dff, #9a60ff)',
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:audioData']);
|
||||
|
||||
// 波形条数据
|
||||
const waveBars = ref([]);
|
||||
// 中心条索引
|
||||
const centerIndex = ref(0);
|
||||
// 动画帧ID
|
||||
let animationId = null;
|
||||
|
||||
// 格式化显示时间
|
||||
const formattedTime = computed(() => {
|
||||
const mins = Math.floor(props.recordingTime / 60)
|
||||
.toString()
|
||||
.padStart(2, '0');
|
||||
const secs = (props.recordingTime % 60).toString().padStart(2, '0');
|
||||
return `${mins}:${secs}`;
|
||||
});
|
||||
|
||||
// 录音提示文本
|
||||
const recordingTip = computed(() => {
|
||||
return props.isCanceling ? '松开取消' : '松手发送';
|
||||
});
|
||||
|
||||
// 初始化波形条
|
||||
const initWaveBars = () => {
|
||||
waveBars.value = [];
|
||||
// 创建31个波形条(奇数个,确保有真正的中心点)
|
||||
const barCount = 31;
|
||||
centerIndex.value = Math.floor(barCount / 2);
|
||||
|
||||
for (let i = 0; i < barCount; i++) {
|
||||
// 设置初始状态(中心条最高,向两侧递减)
|
||||
const distanceFromCenter = Math.abs(i - centerIndex.value);
|
||||
const initialHeight = Math.max(2, 20 - distanceFromCenter * 3);
|
||||
|
||||
waveBars.value.push({
|
||||
height: initialHeight,
|
||||
color: '#FFFFFF',
|
||||
borderRadius: 2,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 更新波形显示
|
||||
const updateWaveform = () => {
|
||||
if (!props.isActive) return;
|
||||
// 如果没有传入音频数据,则使用模拟数据
|
||||
const audioData =
|
||||
props.audioData.length > 0
|
||||
? props.audioData
|
||||
: Array(centerIndex.value + 1)
|
||||
.fill(0)
|
||||
.map(() => Math.random() * 0.5 + 0.2);
|
||||
// 从中间向两侧处理
|
||||
for (let i = 0; i <= centerIndex.value; i++) {
|
||||
// 左侧条索引
|
||||
const leftIndex = centerIndex.value - i;
|
||||
// 右侧条索引
|
||||
const rightIndex = centerIndex.value + i;
|
||||
|
||||
// 获取音频数据值 (归一化到0-1)
|
||||
const value = audioData[i] || 0;
|
||||
|
||||
// 更新左侧条
|
||||
if (leftIndex >= 0) {
|
||||
updateWaveBar(leftIndex, value);
|
||||
}
|
||||
|
||||
// 更新右侧条(避免重复更新中心条)
|
||||
if (rightIndex < waveBars.value.length && rightIndex !== leftIndex) {
|
||||
updateWaveBar(rightIndex, value);
|
||||
}
|
||||
}
|
||||
|
||||
// 继续动画
|
||||
animationId = requestAnimationFrame(updateWaveform);
|
||||
};
|
||||
|
||||
// 更新单个波形条
|
||||
const updateWaveBar = (index, value) => {
|
||||
// 动态高度 (4rpx到200rpx之间)
|
||||
const height = 2 + value * 98;
|
||||
|
||||
// // 动态颜色
|
||||
// let color;
|
||||
// if (props.isCanceling) {
|
||||
// color = '#F44336'; // 取消状态显示红色
|
||||
// } else {
|
||||
// const intensity = Math.min(1, value * 1.5);
|
||||
// const r = Math.floor(7 + intensity * 200);
|
||||
// const g = Math.floor(193 - intensity * 50);
|
||||
// const b = Math.floor(96 - intensity * 30);
|
||||
// color = `rgb(${r}, ${g}, ${b})`;
|
||||
// }
|
||||
let color = '#FFFFFF';
|
||||
// 动态圆角
|
||||
const borderRadius = Math.min(4, height * 0.4);
|
||||
|
||||
waveBars.value[index] = {
|
||||
height,
|
||||
color,
|
||||
borderRadius,
|
||||
};
|
||||
};
|
||||
|
||||
// 开始动画
|
||||
const startAnimation = () => {
|
||||
if (!animationId) {
|
||||
animationId = requestAnimationFrame(updateWaveform);
|
||||
}
|
||||
};
|
||||
|
||||
// 停止动画
|
||||
const stopAnimation = () => {
|
||||
if (animationId) {
|
||||
cancelAnimationFrame(animationId);
|
||||
animationId = null;
|
||||
}
|
||||
};
|
||||
|
||||
// 监听激活状态变化
|
||||
watch(
|
||||
() => props.isActive,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
startAnimation();
|
||||
} else {
|
||||
stopAnimation();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// 组件挂载时初始化
|
||||
onMounted(() => {
|
||||
initWaveBars();
|
||||
if (props.isActive) {
|
||||
startAnimation();
|
||||
}
|
||||
});
|
||||
|
||||
// 组件卸载时清理
|
||||
onUnmounted(() => {
|
||||
stopAnimation();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.wave-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
pointer-events: none;
|
||||
padding: 16rpx;
|
||||
border-radius: 36rpx;
|
||||
height: calc(102rpx - 40rpx);
|
||||
gap: 4rpx;
|
||||
box-shadow: 0rpx 8rpx 40rpx 0rpx rgba(0, 54, 170, 0.15);
|
||||
overflow: hidden;
|
||||
&.active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.wave {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.wave-bar {
|
||||
width: 6rpx;
|
||||
min-height: 4rpx;
|
||||
border-radius: 4rpx;
|
||||
margin: 0 3rpx;
|
||||
transition: height 0.3s ease-out, background-color 0.2s;
|
||||
transform-origin: center bottom;
|
||||
}
|
||||
|
||||
.wave-bar:nth-child(3n) {
|
||||
opacity: 0.7;
|
||||
}
|
||||
.recording-info {
|
||||
position: absolute;
|
||||
bottom: -80rpx;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.recording-tip {
|
||||
font-size: 28rpx;
|
||||
color: #07c160;
|
||||
}
|
||||
|
||||
.recording-time {
|
||||
font-size: 28rpx;
|
||||
color: #07c160;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
.cancel-tip {
|
||||
position: absolute;
|
||||
bottom: -120rpx;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
color: #f44336;
|
||||
}
|
||||
</style>
|
@@ -8,8 +8,12 @@
|
||||
我可以根据您的简历和求职需求,帮你精准匹配青岛市互联网招聘信息,对比招聘信息的优缺点,提供面试指导等,请把你的任务交给我吧~
|
||||
</view>
|
||||
<view class="back-rowh3">猜你所想</view>
|
||||
<view class="back-rowmsg">我希望找青岛的IT行业岗位,薪资能否在12000以上?</view>
|
||||
<view class="back-rowmsg">我有三年的工作经验,能否推荐一些适合我的青岛的国企 岗位?</view>
|
||||
<view class="back-rowmsg" v-for="item in queries" @click="sendMessageGuess(item)">
|
||||
{{ item }}
|
||||
</view>
|
||||
<view class="chat-item self" v-if="isRecording">
|
||||
<view class="message">{{ recognizedText }} {{ lastFinalText }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</FadeView>
|
||||
<scroll-view class="chat-list scrollView" :scroll-top="scrollTop" :scroll-y="true" scroll-with-animation>
|
||||
@@ -25,7 +29,7 @@
|
||||
<view class="message" v-if="msg.self">
|
||||
<view class="msg-filecontent" v-if="msg.files.length">
|
||||
<view
|
||||
class="msg-files"
|
||||
class="msg-files btn-light"
|
||||
v-for="(file, vInex) in msg.files"
|
||||
:key="vInex"
|
||||
@click="jumpUrl(file)"
|
||||
@@ -40,7 +44,39 @@
|
||||
<!-- {{ msg.displayText }} -->
|
||||
<view class="message-markdown">
|
||||
<md-render :content="msg.displayText"></md-render>
|
||||
<view class="message-controll"></view>
|
||||
<view class="message-controll" v-show="showControll(index)">
|
||||
<view class="controll-left">
|
||||
<image
|
||||
class="controll-icon btn-light"
|
||||
src="/static/icon/copy.png"
|
||||
@click="copyMarkdown(msg.displayText)"
|
||||
></image>
|
||||
<image
|
||||
class="controll-icon mar_le10 btn-light"
|
||||
src="/static/icon/feedback.png"
|
||||
@click="userGoodFeedback(msg)"
|
||||
></image>
|
||||
<image
|
||||
v-if="isSpeaking && !isPaused && speechIndex === index"
|
||||
class="controll-icon mar_le10 btn-light"
|
||||
src="/static/icon/stop.png"
|
||||
@click="stopMarkdown(msg.displayText, index)"
|
||||
></image>
|
||||
<image
|
||||
class="controll-icon mar_le10 btn-light"
|
||||
src="/static/icon/broadcast.png"
|
||||
@click="readMarkdown(msg.displayText, index)"
|
||||
v-else
|
||||
></image>
|
||||
</view>
|
||||
<view class="controll-right">
|
||||
<image
|
||||
class="controll-icon mar_ri10 btn-light"
|
||||
src="/static/icon/refresh.png"
|
||||
@click="refreshMarkdown(index)"
|
||||
></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- guess -->
|
||||
<view
|
||||
@@ -60,6 +96,9 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="chat-item self" v-if="isRecording">
|
||||
<view class="message">{{ recognizedText }} {{ lastFinalText }}</view>
|
||||
</view>
|
||||
<view v-if="isTyping" :class="{ self: true }">
|
||||
<text class="message msg-loading">
|
||||
<span class="ai-loading"></span>
|
||||
@@ -70,7 +109,12 @@
|
||||
</scroll-view>
|
||||
<view class="vio_container" :class="status" v-if="status !== 'idle'">
|
||||
<view class="record-tip">{{ statusText }}</view>
|
||||
<AudioWave :background="audiowaveStyle" />
|
||||
<WaveDisplay
|
||||
:background="audiowaveStyle"
|
||||
:isActive="isRecording"
|
||||
:audioData="audioDataForDisplay"
|
||||
:showInfo="isRecording"
|
||||
/>
|
||||
</view>
|
||||
<view class="input-area" v-else>
|
||||
<view class="areatext">
|
||||
@@ -82,7 +126,7 @@
|
||||
:disabled="isTyping"
|
||||
:adjust-position="false"
|
||||
placeholder="请输入您的职位名称、薪资要求、岗位地址"
|
||||
v-if="!isVoice"
|
||||
v-show="!isVoice"
|
||||
/>
|
||||
<view
|
||||
class="input_vio"
|
||||
@@ -90,8 +134,8 @@
|
||||
@touchmove="handleTouchMove"
|
||||
@touchend="handleTouchEnd"
|
||||
@touchcancel="handleTouchCancel"
|
||||
v-show="isVoice"
|
||||
type="default"
|
||||
v-else
|
||||
>
|
||||
按住说话
|
||||
</view>
|
||||
@@ -114,8 +158,8 @@
|
||||
<view class="btn-box" v-else-if="!isTyping" @click="changeVoice">
|
||||
<image class="send-btn" src="/static/icon/send4.png"></image>
|
||||
</view>
|
||||
<view class="btn-box" v-else>
|
||||
<image class="send-btn" src="/static/icon/send2xx.png"></image>
|
||||
<view class="btn-box purple" v-else>
|
||||
<view class="btn-box-round"></view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- btn -->
|
||||
@@ -153,15 +197,19 @@
|
||||
:src="file.url"
|
||||
></image>
|
||||
<view class="file-doc" @click="jumpUrl(file)" v-else>
|
||||
<view style="width: 100%">
|
||||
<FileIcon class="doc-icon" :type="file.type"></FileIcon>
|
||||
<view class="doc-con">
|
||||
<view class="filename-text">{{ file.name }}</view>
|
||||
<view class="filename-size">{{ file.size }}</view>
|
||||
<view class="filerow">
|
||||
<FileText :type="file.type"></FileText>
|
||||
<view class="row-x"></view>
|
||||
<view class="filename-size">{{ file.size }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<FileIcon :type="file.type"></FileIcon>
|
||||
<!-- <image class="file-icon" @click="jumpUrl(file)" :src=""></image> -->
|
||||
</view>
|
||||
<view class="file-del" catchtouchmove="true" @click="delfile(file)">
|
||||
<uni-icons type="closeempty" color="#4B4B4B" size="10"></uni-icons>
|
||||
<uni-icons type="closeempty" color="#FFFFFF" size="10"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -176,20 +224,36 @@ import { ref, inject, nextTick, defineProps, defineEmits, onMounted, toRaw, reac
|
||||
import { storeToRefs } from 'pinia';
|
||||
import config from '@/config.js';
|
||||
import useChatGroupDBStore from '@/stores/userChatGroupStore';
|
||||
const { $api, navTo, throttle } = inject('globalFunction');
|
||||
const emit = defineEmits(['onConfirm']);
|
||||
import MdRender from '@/components/md-render/md-render.vue';
|
||||
const { messages, isTyping, textInput, chatSessionID } = storeToRefs(useChatGroupDBStore());
|
||||
import CollapseTransition from '@/components/CollapseTransition/CollapseTransition.vue';
|
||||
import FadeView from '@/components/FadeView/FadeView.vue';
|
||||
import AudioWave from './AudioWave.vue';
|
||||
import WaveDisplay from './WaveDisplay.vue';
|
||||
import FileIcon from './fileIcon.vue';
|
||||
import FileText from './fileText.vue';
|
||||
import { useSpeechReader } from '@/hook/useSpeechReader';
|
||||
import { useAudioRecorder } from '@/hook/useRealtimeRecorder.js';
|
||||
// 全局
|
||||
const { $api, navTo, throttle } = inject('globalFunction');
|
||||
const emit = defineEmits(['onConfirm']);
|
||||
const { messages, isTyping, textInput, chatSessionID } = storeToRefs(useChatGroupDBStore());
|
||||
|
||||
const { isRecording, recognizedText, startRecording, stopRecording, cancelRecording } = useAudioRecorder(
|
||||
config.vioceBaseURl
|
||||
);
|
||||
// hook
|
||||
const {
|
||||
isRecording,
|
||||
startRecording,
|
||||
stopRecording,
|
||||
cancelRecording,
|
||||
audioDataForDisplay,
|
||||
volumeLevel,
|
||||
recognizedText,
|
||||
lastFinalText,
|
||||
} = useAudioRecorder(config.vioceBaseURl);
|
||||
|
||||
const { speak, pause, resume, isSpeaking, isPaused } = useSpeechReader();
|
||||
|
||||
// state
|
||||
const queries = ref([]);
|
||||
const guessList = ref([]);
|
||||
const scrollTop = ref(0);
|
||||
const showGuess = ref(false);
|
||||
@@ -200,18 +264,62 @@ const isVoice = ref(false);
|
||||
const status = ref('idle'); // idle | recording | cancel
|
||||
const startY = ref(0);
|
||||
const cancelThreshold = 100;
|
||||
let recordingTimer = null;
|
||||
const speechIndex = ref(0);
|
||||
const isAudioPermission = ref(false);
|
||||
|
||||
const state = reactive({
|
||||
uploadFileTips: '请根据以上附件,帮我推荐岗位。',
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
scrollToBottom();
|
||||
const statusText = computed(() => {
|
||||
switch (status.value) {
|
||||
case 'recording':
|
||||
return '松手发送,上划取消';
|
||||
case 'cancel':
|
||||
return '松手取消';
|
||||
default:
|
||||
return '按住说话';
|
||||
}
|
||||
});
|
||||
|
||||
const sendMessage = () => {
|
||||
const values = textInput.value;
|
||||
const audiowaveStyle = computed(() => {
|
||||
return status.value === 'cancel'
|
||||
? '#f54545'
|
||||
: status.value === 'recording'
|
||||
? 'linear-gradient(to right, #377dff, #9a60ff)'
|
||||
: '#f1f1f1';
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
changeQueries();
|
||||
scrollToBottom();
|
||||
isAudioPermission.value = await requestMicPermission();
|
||||
});
|
||||
|
||||
const requestMicPermission = async () => {
|
||||
try {
|
||||
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
||||
console.log('✅ 麦克风权限已授权');
|
||||
|
||||
// 立刻停止所有音轨,释放麦克风
|
||||
stream.getTracks().forEach((track) => track.stop());
|
||||
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.warn('❌ 用户拒绝麦克风权限或不支持:', err);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
function showControll(index) {
|
||||
if (index === messages.value.length - 1 && isTyping.value) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const sendMessage = (text) => {
|
||||
const values = textInput.value || text;
|
||||
showfile.value = false;
|
||||
showGuess.value = false;
|
||||
if (values.trim()) {
|
||||
@@ -222,7 +330,9 @@ const sendMessage = () => {
|
||||
const newMsg = { text: values, self: true, displayText: values, files: normalArr };
|
||||
useChatGroupDBStore().addMessage(newMsg);
|
||||
useChatGroupDBStore()
|
||||
.getStearm(values, normalArr, scrollToBottom)
|
||||
.getStearm(values, normalArr, scrollToBottom, {
|
||||
onComplete: () => console.log('Display complete'),
|
||||
})
|
||||
.then(() => {
|
||||
getGuess();
|
||||
scrollToBottom();
|
||||
@@ -276,19 +386,17 @@ const delfile = (file) => {
|
||||
const scrollToBottom = throttle(function () {
|
||||
nextTick(() => {
|
||||
try {
|
||||
setTimeout(() => {
|
||||
const query = uni.createSelectorQuery();
|
||||
query.select('.scrollView').boundingClientRect();
|
||||
query.select('.list-content').boundingClientRect();
|
||||
query.exec((res) => {
|
||||
const scrollViewHeight = res[0].height;
|
||||
const scrollContentHeight = res[1].height;
|
||||
if (scrollContentHeight > scrollViewHeight) {
|
||||
const scrolldistance = scrollContentHeight - scrollViewHeight;
|
||||
scrollTop.value = scrolldistance;
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
const query = uni.createSelectorQuery();
|
||||
query.select('.scrollView').boundingClientRect();
|
||||
query.select('.list-content').boundingClientRect();
|
||||
query.exec((res) => {
|
||||
const scrollViewHeight = res[0].height;
|
||||
const scrollContentHeight = res[1].height;
|
||||
if (scrollContentHeight > scrollViewHeight) {
|
||||
const scrolldistance = scrollContentHeight - scrollViewHeight;
|
||||
scrollTop.value = scrolldistance;
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
console.warn(err);
|
||||
}
|
||||
@@ -386,14 +494,29 @@ function getUploadFile(type = 'camera') {
|
||||
});
|
||||
}
|
||||
|
||||
const handleTouchStart = (e) => {
|
||||
const tipsPermisson = () => {
|
||||
uni.showToast({
|
||||
title: '需要授权麦克风权限才能使用语音功能',
|
||||
icon: 'none',
|
||||
});
|
||||
};
|
||||
|
||||
const handleTouchStart = async (e) => {
|
||||
if (!isAudioPermission.value) {
|
||||
return tipsPermisson();
|
||||
}
|
||||
console.log('handleTouchStart');
|
||||
startY.value = e.touches[0].clientY;
|
||||
status.value = 'recording';
|
||||
showfile.value = false;
|
||||
startRecording();
|
||||
$api.sleep(1000).then(() => {
|
||||
scrollToBottom();
|
||||
});
|
||||
};
|
||||
|
||||
const handleTouchMove = (e) => {
|
||||
console.log('handleTouchMove');
|
||||
const moveY = e.touches[0].clientY;
|
||||
if (startY.value - moveY > cancelThreshold) {
|
||||
status.value = 'cancel';
|
||||
@@ -403,40 +526,32 @@ const handleTouchMove = (e) => {
|
||||
};
|
||||
|
||||
const handleTouchEnd = () => {
|
||||
console.log('handleTouchEnd');
|
||||
if (status.value === 'cancel') {
|
||||
console.log('取消发送');
|
||||
cancelRecording();
|
||||
} else {
|
||||
console.log('stopRecording');
|
||||
stopRecording();
|
||||
console.log('发送语音');
|
||||
$api.sleep(1000).then(() => {
|
||||
if (isAudioPermission.value) {
|
||||
if (recognizedText.value) {
|
||||
sendMessage(recognizedText.value);
|
||||
} else {
|
||||
$api.msg('说话时长太短');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
status.value = 'idle';
|
||||
};
|
||||
|
||||
const handleTouchCancel = () => {
|
||||
console.log('handleTouchCancel');
|
||||
stopRecording();
|
||||
status.value = 'idle';
|
||||
};
|
||||
|
||||
const statusText = computed(() => {
|
||||
switch (status.value) {
|
||||
case 'recording':
|
||||
return '松手发送,上划取消';
|
||||
case 'cancel':
|
||||
return '松手取消';
|
||||
default:
|
||||
return '按住说话';
|
||||
}
|
||||
});
|
||||
|
||||
const audiowaveStyle = computed(() => {
|
||||
return status.value === 'cancel'
|
||||
? '#f54545'
|
||||
: status.value === 'recording'
|
||||
? 'linear-gradient(to right, #377dff, #9a60ff)'
|
||||
: '#f1f1f1';
|
||||
});
|
||||
|
||||
function closeGuess() {
|
||||
showGuess.value = false;
|
||||
}
|
||||
@@ -452,7 +567,74 @@ function changeShowFile() {
|
||||
function colseFile() {
|
||||
showfile.value = false;
|
||||
}
|
||||
defineExpose({ scrollToBottom, closeGuess, colseFile });
|
||||
|
||||
function copyMarkdown(value) {
|
||||
$api.copyText(value);
|
||||
}
|
||||
|
||||
function userGoodFeedback(msg) {
|
||||
$api.msg('该功能正在开发中,敬请期待后续更新!');
|
||||
// const params = {
|
||||
// dataId: msg.dataId,
|
||||
// sessionId: msg.parentGroupId,
|
||||
// userGoodFeedback: 'no',
|
||||
// };
|
||||
}
|
||||
|
||||
function readMarkdown(value, index) {
|
||||
speechIndex.value = index;
|
||||
if (speechIndex.value !== index) {
|
||||
speak(value);
|
||||
return;
|
||||
}
|
||||
if (isPaused.value) {
|
||||
resume();
|
||||
} else {
|
||||
speak(value);
|
||||
}
|
||||
}
|
||||
function stopMarkdown(value, index) {
|
||||
pause(value);
|
||||
speechIndex.value = index;
|
||||
}
|
||||
function refreshMarkdown(index) {
|
||||
if (isTyping.value) {
|
||||
$api.msg('正在生成');
|
||||
} else {
|
||||
const text = messages.value[index - 1].text;
|
||||
sendMessageGuess(text);
|
||||
}
|
||||
}
|
||||
|
||||
const jobSearchQueries = [
|
||||
'青岛有哪些薪资 12K 以上的岗位适合我?',
|
||||
'青岛 3 年工作经验能找到哪些 12K 以上的工作?',
|
||||
'青岛哪些公司在招聘,薪资范围在 12K 以上?',
|
||||
'青岛有哪些企业提供 15K 以上的岗位?',
|
||||
'青岛哪些公司在招 3-5 年经验的岗位?',
|
||||
'我有三年的工作经验,能否推荐一些适合我的青岛的国企 岗位?',
|
||||
'青岛国企目前在招聘哪些岗位?',
|
||||
'青岛有哪些适合 3 年经验的国企岗位?',
|
||||
'青岛国企招聘的岗位待遇如何?',
|
||||
'青岛国企岗位的薪资水平是多少?',
|
||||
'青岛哪些国企支持双休 & 五险一金完善?',
|
||||
'青岛有哪些公司支持远程办公?',
|
||||
'青岛有哪些外企的岗位,薪资 12K 以上的多吗?',
|
||||
'青岛哪些企业在招聘 Web3.0 相关岗位?',
|
||||
'青岛哪些岗位支持海外远程?薪资如何?',
|
||||
'青岛招聘 AI/大数据相关岗位的公司有哪些?',
|
||||
];
|
||||
|
||||
function changeQueries(value) {
|
||||
queries.value = getRandomJobQueries(jobSearchQueries);
|
||||
}
|
||||
|
||||
function getRandomJobQueries(queries, count = 2) {
|
||||
const shuffled = queries.sort(() => 0.5 - Math.random()); // 随机打乱数组
|
||||
return shuffled.slice(0, count); // 取前 count 条
|
||||
}
|
||||
|
||||
defineExpose({ scrollToBottom, closeGuess, colseFile, changeQueries, handleTouchCancel });
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
@@ -536,11 +718,11 @@ image-margin-top = 40rpx
|
||||
flex-direction: column
|
||||
justify-content: flex-start
|
||||
align-items: center
|
||||
width: calc(100% - 88rpx)
|
||||
.backlogo
|
||||
width: 313rpx;
|
||||
height: 190rpx;
|
||||
.back-rowTitle
|
||||
width: 100%;
|
||||
height: 56rpx;
|
||||
font-weight: bold;
|
||||
font-size: 40rpx;
|
||||
@@ -550,27 +732,31 @@ image-margin-top = 40rpx
|
||||
.back-rowText
|
||||
margin-top: 28rpx
|
||||
width: 100%;
|
||||
height: 144rpx;
|
||||
height: 148rpx;
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
border-bottom: 2rpx dashed rgba(0, 0, 0, 0.2);
|
||||
line-height: 40rpx
|
||||
// border-bottom: 2rpx dashed rgba(0, 0, 0, 0.2);
|
||||
border-bottom: 2rpx solid transparent;
|
||||
background-image: linear-gradient(to right, rgba(0, 0, 0, 0.2) 50%, transparent 50%);
|
||||
background-size: 10rpx 2rpx; /* 调整虚线宽度和间距 */
|
||||
background-repeat: repeat-x;
|
||||
background-position: 0 148rpx
|
||||
.back-rowh3
|
||||
width: 100%;
|
||||
height: 30rpx;
|
||||
font-weight: 500;
|
||||
font-size: 22rpx;
|
||||
font-size: 28rpx;
|
||||
color: #000000;
|
||||
margin-top: 24rpx
|
||||
margin-top: 28rpx
|
||||
.back-rowmsg
|
||||
width: 630rpx
|
||||
margin-top: 20rpx
|
||||
width: calc(100% - 32rpx)
|
||||
margin-top: 24rpx
|
||||
font-weight: 500;
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
line-height: 28rpx;
|
||||
font-size: 24rpx
|
||||
background: #F6F6F6;
|
||||
background: rgba(246, 246, 246, 1);
|
||||
border-radius: 8rpx 8rpx 8rpx 8rpx;
|
||||
padding: 32rpx 18rpx;
|
||||
|
||||
@@ -586,6 +772,7 @@ image-margin-top = 40rpx
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 20rpx;
|
||||
width: 100%;
|
||||
}
|
||||
.chat-item.self {
|
||||
justify-content: flex-end;
|
||||
@@ -602,6 +789,19 @@ image-margin-top = 40rpx
|
||||
border-radius: 0 20rpx 20rpx 20rpx;
|
||||
padding: 20rpx 20rpx 0 20rpx;
|
||||
background: #F6F6F6;
|
||||
.message-controll
|
||||
display: flex
|
||||
justify-content: space-between
|
||||
align-items: center
|
||||
border-top: 2rpx solid #EAEAEA
|
||||
padding: 24rpx 0
|
||||
margin-top: -10rpx
|
||||
.controll-left
|
||||
.controll-right
|
||||
.controll-icon
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
|
||||
.messageNull
|
||||
display: none
|
||||
.msg-loading{
|
||||
@@ -703,6 +903,11 @@ image-margin-top = 40rpx
|
||||
transition: transform 0.5s ease;
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
.btn-box-round
|
||||
width: 22rpx
|
||||
height: 22rpx
|
||||
border-radius: 4rpx
|
||||
background: #FFFFFF
|
||||
.purple
|
||||
background: linear-gradient( 225deg, #9E74FD 0%, #256BFA 100%);
|
||||
.add-file-btn{
|
||||
@@ -725,7 +930,7 @@ image-margin-top = 40rpx
|
||||
text
|
||||
font-size: 24rpx
|
||||
font-weight: 500
|
||||
color: #000000
|
||||
color: rgba(0,0,0,.5)
|
||||
padding-top: 8rpx
|
||||
.card-img
|
||||
height: 56rpx
|
||||
@@ -736,38 +941,45 @@ image-margin-top = 40rpx
|
||||
.area-uploadfiles
|
||||
position: absolute
|
||||
top: -180rpx
|
||||
width: calc(100% - 40rpx)
|
||||
width: calc(100% - 30rpx)
|
||||
background: #FFFFFF
|
||||
left: 0
|
||||
padding: 10rpx 20rpx
|
||||
padding: 10rpx 0 10rpx 30rpx
|
||||
box-shadow: 0rpx -4rpx 10rpx 0rpx rgba(11,44,112,0.06);
|
||||
.uploadfiles-scroll
|
||||
height: 100%
|
||||
.uploadfiles-list
|
||||
height: 100%
|
||||
display: flex
|
||||
margin-right: 28rpx
|
||||
flex-wrap: nowrap
|
||||
.file-doc
|
||||
display: flex
|
||||
flex-direction: column
|
||||
align-items: flex-start
|
||||
justify-content: space-between
|
||||
align-items: center
|
||||
justify-content: flex-start
|
||||
padding: 16rpx 20rpx 18rpx 20rpx
|
||||
height: calc(100% - 40rpx)
|
||||
.doc-icon
|
||||
width: 60rpx
|
||||
height: 76rpx
|
||||
margin-right: 20rpx
|
||||
.doc-con
|
||||
flex: 1
|
||||
width: 0
|
||||
.file-uploadsend
|
||||
margin: 10rpx 18rpx 0 10rpx;
|
||||
margin: 10rpx 18rpx 0 0;
|
||||
height: 100%
|
||||
border-radius: 30rpx
|
||||
font-size: 24rpx
|
||||
position: relative
|
||||
width: 360rpx;
|
||||
min-width: 460rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 12rpx 12rpx 12rpx 12rpx;
|
||||
border: 2rpx solid #E2E2E2;
|
||||
overflow: hidden
|
||||
.file-del
|
||||
position: absolute
|
||||
right: 0
|
||||
top: 0
|
||||
right: 25rpx
|
||||
top: 18rpx
|
||||
z-index: 9
|
||||
border-radius: 50%
|
||||
display: flex
|
||||
@@ -775,10 +987,10 @@ image-margin-top = 40rpx
|
||||
justify-content: center
|
||||
transform: translate(50%, -10rpx)
|
||||
height: 40rpx
|
||||
width: 23rpx;
|
||||
height: 23rpx;
|
||||
background: #FFFFFF;
|
||||
border: 2rpx solid #E2E2E2;
|
||||
width: 37rpx;
|
||||
height: 37rpx;
|
||||
background: #4B4B4B;
|
||||
border: 2rpx solid #FFFFFF;
|
||||
.file-del:active
|
||||
background: #e8e8e8
|
||||
.filename-text
|
||||
@@ -787,7 +999,6 @@ image-margin-top = 40rpx
|
||||
white-space: nowrap
|
||||
color: #333333
|
||||
font-size: 24rpx
|
||||
flex: 1
|
||||
font-weight: 500
|
||||
max-width: 100%
|
||||
.filename-size
|
||||
@@ -795,18 +1006,21 @@ image-margin-top = 40rpx
|
||||
text-overflow: ellipsis
|
||||
white-space: nowrap
|
||||
color: #7B7B7B;
|
||||
flex: 1
|
||||
max-width: 100%
|
||||
.file-icon
|
||||
height: 40rpx
|
||||
width: 40rpx
|
||||
.file-iconImg
|
||||
height: 100%
|
||||
width: 100%
|
||||
border-radius: 15rpx
|
||||
.filerow
|
||||
display: flex
|
||||
align-items: center
|
||||
margin-top: 7rpx
|
||||
.row-x
|
||||
margin: 0 18rpx
|
||||
height: 20rpx
|
||||
width: 2rpx
|
||||
background: rgba(226, 226, 226, .9)
|
||||
.file-border
|
||||
width: 160rpx;
|
||||
border: 0
|
||||
width: 160rpx !important;
|
||||
|
||||
@keyframes ai-circle {
|
||||
0% {
|
||||
|
@@ -46,5 +46,3 @@ const props = defineProps({
|
||||
|
||||
const type = props.type;
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
|
38
pages/chat/components/fileText.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<view class="file-type-box">
|
||||
{{ fileAbbreviation }}
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
type: String,
|
||||
});
|
||||
|
||||
const fileAbbreviation = computed(() => {
|
||||
const typeMap = {
|
||||
'application/pdf': 'PDF',
|
||||
'application/msword': 'DOC',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'DOCX',
|
||||
'application/vnd.ms-powerpoint': 'PPT',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'PPTX',
|
||||
'application/vnd.ms-excel': 'XLS',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'XLSX',
|
||||
'text/markdown': 'MD',
|
||||
'text/plain': 'TXT',
|
||||
'text/html': 'HTML',
|
||||
};
|
||||
return typeMap[props.type] || 'OTHER';
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.file-type-box {
|
||||
font-weight: 400;
|
||||
font-size: 24rpx;
|
||||
color: #7b7b7b;
|
||||
line-height: 28rpx;
|
||||
}
|
||||
</style>
|
@@ -328,9 +328,9 @@ function getJobList(type = 'add') {
|
||||
pageState.total = resData.total;
|
||||
pageState.maxPage = Math.ceil(pageState.total / pageState.pageSize);
|
||||
if (rows.length < pageState.pageSize) {
|
||||
loadmoreRef.value.change('noMore');
|
||||
loadmoreRef.value?.change('noMore');
|
||||
} else {
|
||||
loadmoreRef.value.change('more');
|
||||
loadmoreRef.value?.change('more');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -56,16 +56,12 @@
|
||||
|
||||
<script setup>
|
||||
import { reactive, inject, watch, ref, onMounted } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app';
|
||||
const { $api, navTo } = inject('globalFunction');
|
||||
import useUserStore from '@/stores/useUserStore';
|
||||
const userInfo = ref({});
|
||||
const Completion = ref({});
|
||||
const popup = ref(null);
|
||||
onShow(() => {
|
||||
userInfo.value = useUserStore().userInfo;
|
||||
Completion.value = useUserStore().Completion;
|
||||
});
|
||||
const { userInfo, Completion } = storeToRefs(useUserStore());
|
||||
|
||||
function logOut() {
|
||||
popup.value.open();
|
||||
|
BIN
static/.DS_Store
vendored
BIN
static/icon/.DS_Store
vendored
BIN
static/icon/broadcast.png
Normal file
After Width: | Height: | Size: 584 B |
BIN
static/icon/broadcast1.png
Normal file
After Width: | Height: | Size: 722 B |
BIN
static/icon/copy.png
Normal file
After Width: | Height: | Size: 411 B |
BIN
static/icon/copy1.png
Normal file
After Width: | Height: | Size: 513 B |
BIN
static/icon/feedback.png
Normal file
After Width: | Height: | Size: 522 B |
BIN
static/icon/feedback1.png
Normal file
After Width: | Height: | Size: 667 B |
BIN
static/icon/refresh.png
Normal file
After Width: | Height: | Size: 504 B |
BIN
static/icon/refresh1.png
Normal file
After Width: | Height: | Size: 648 B |
Before Width: | Height: | Size: 267 B After Width: | Height: | Size: 271 B |
BIN
static/icon/stop.png
Normal file
After Width: | Height: | Size: 624 B |
BIN
static/icon/stop1.png
Normal file
After Width: | Height: | Size: 758 B |
BIN
static/tabbar/.DS_Store
vendored
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 594 B |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -54,7 +54,7 @@ const useChatGroupDBStore = defineStore("messageGroup", () => {
|
||||
initMessage(tabelRow.sessionId)
|
||||
} else {
|
||||
console.warn('本地数据库存在数据')
|
||||
getHistory('refresh')
|
||||
// getHistory('refresh')
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
@@ -148,6 +148,7 @@ const useChatGroupDBStore = defineStore("messageGroup", () => {
|
||||
if (typeof part === 'string') {
|
||||
newMsg.displayText += part;
|
||||
} else if (typeof part === 'object' && part.type === 'highlight') {
|
||||
consol.log('自定义样式')
|
||||
newMsg.displayText += `<span class="highlight">${part.content}</span>`;
|
||||
} else {
|
||||
newMsg.displayText += String(part); // 兜底
|
||||
@@ -180,7 +181,6 @@ const useChatGroupDBStore = defineStore("messageGroup", () => {
|
||||
}
|
||||
|
||||
function onError(error) {
|
||||
console.error('请求异常:', error);
|
||||
msg('服务响应异常');
|
||||
reject(error);
|
||||
}
|
||||
@@ -273,6 +273,9 @@ const useChatGroupDBStore = defineStore("messageGroup", () => {
|
||||
if (obj.type === 'file') {
|
||||
files.push(obj.file)
|
||||
}
|
||||
if (obj.type === 'tool') {
|
||||
console.log(obj)
|
||||
}
|
||||
}
|
||||
arr.push({
|
||||
parentGroupId: sessionId,
|
||||
|
BIN
unpackage/.DS_Store
vendored
BIN
unpackage/dist/.DS_Store
vendored
BIN
unpackage/dist/build/.DS_Store
vendored
Before Width: | Height: | Size: 16 KiB |
@@ -1 +0,0 @@
|
||||
.collection-content[data-v-6c0afbd6]{padding:.625rem 0}.one-cards[data-v-6c0afbd6]{display:flex;flex-direction:column;padding:0 .625rem}.one-cards .card-box[data-v-6c0afbd6]{width:calc(100% - 2.25rem);border-radius:0;background:#fff;border-radius:.53125rem;padding:.46875rem 1.125rem;margin-top:.75rem}.one-cards .card-box .box-row[data-v-6c0afbd6]{display:flex;justify-content:space-between;margin-top:.25rem;align-items:center}.one-cards .card-box .box-row .mineText[data-v-6c0afbd6]{font-weight:400;font-size:.65625rem;color:#606060}.one-cards .card-box .box-row .textblue[data-v-6c0afbd6]{color:#4778ec}.one-cards .card-box .box-row .row-left[data-v-6c0afbd6]{display:flex;justify-content:space-between}.one-cards .card-box .box-row .row-left .row-tag[data-v-6c0afbd6]{background:#13c57c;border-radius:.53125rem;font-size:.65625rem;color:#fff;line-height:.78125rem;text-align:center;padding:.125rem .25rem;margin-right:.71875rem}.one-cards .card-box[data-v-6c0afbd6]:first-child{margin-top:.1875rem}
|
Before Width: | Height: | Size: 5.2 KiB |
@@ -1 +0,0 @@
|
||||
.container[data-v-1fe8fba7]{display:flex;flex-direction:column;background-color:#f8f8f8}.hr[data-v-1fe8fba7]{height:.3125rem}.company-header[data-v-1fe8fba7]{padding:.625rem 1.25rem;background-color:#fff}.company-header .company-name[data-v-1fe8fba7]{font-size:1.75rem;font-weight:700;color:#333;margin-bottom:.3125rem}.company-header .company-info[data-v-1fe8fba7]{font-size:.75rem;color:#666;display:flex;align-items:center;justify-content:space-between}.company-header .company-info .location[data-v-1fe8fba7]{display:flex;align-items:center}.company-description[data-v-1fe8fba7]{padding:.625rem 1.25rem;background-color:#fff;margin-bottom:.3125rem}.company-description .section-title[data-v-1fe8fba7]{font-size:1.3125rem;font-weight:700;margin-bottom:.3125rem}.company-description .description[data-v-1fe8fba7]{font-size:.75rem;color:#333;line-height:1.125rem}.job-list[data-v-1fe8fba7]{padding:.625rem 1.25rem;background-color:#fff}.job-list .section-title[data-v-1fe8fba7]{font-size:1.3125rem;font-weight:700;margin-bottom:.3125rem}.job-list .job-row[data-v-1fe8fba7]{display:flex;justify-content:space-between;align-items:flex-start;padding:.625rem;border:.0625rem solid #d9d9d9;margin-top:.625rem;border-radius:.53125rem}.job-list .job-row .left[data-v-1fe8fba7]{display:flex;flex-direction:column;flex-grow:1}.job-list .job-row .left .job-title[data-v-1fe8fba7]{font-size:.875rem;font-weight:700;color:#333;margin-bottom:.3125rem}.job-list .job-row .left .job-tags[data-v-1fe8fba7]{display:flex;gap:.3125rem;margin-bottom:.3125rem}.job-list .job-row .left .job-tags .tag[data-v-1fe8fba7]{background-color:#22c55e;color:#fff;padding:.15625rem .3125rem;border-radius:.375rem;font-size:.625rem}.job-list .job-row .left .location[data-v-1fe8fba7]{font-size:.75rem;color:#666}.job-list .job-row .right[data-v-1fe8fba7]{display:flex;flex-direction:column;align-items:flex-end}.job-list .job-row .right .salary[data-v-1fe8fba7]{font-size:.875rem;color:#3b82f6;font-weight:700}.job-list .job-row .right .hot[data-v-1fe8fba7]{color:#ff6b6b;font-size:.75rem;margin-top:.15625rem}
|
Before Width: | Height: | Size: 37 KiB |
BIN
unpackage/dist/build/apptest/assets/boy-CeqY74jF.png
vendored
Before Width: | Height: | Size: 5.0 KiB |
@@ -1 +0,0 @@
|
||||
.card-title[data-v-f2493dde]{color:#5d5d5d;font-weight:700;font-size:.75rem}.nothemonth[data-v-f2493dde]{color:#bfbfbf}.downDate[data-v-f2493dde]{display:flex;align-items:center;justify-content:center;width:100%;margin-top:.625rem}.downDate .downIcon[data-v-f2493dde]{background:#e8e8e8;border-radius:50%;width:1.25rem;height:1.25rem}.AllDay[data-v-f2493dde]{position:relative;padding-top:2.1875rem}.AllDay .monthSelect[data-v-f2493dde]{position:absolute;top:0;left:50%;transform:translate(-50%);text-align:center;line-height:1.5625rem;display:flex;align-items:center;justify-content:center;font-size:.875rem}.AllDay .monthSelect .monthIcon[data-v-f2493dde]{padding:0 .3125rem}.date-7days[data-v-f2493dde]{display:grid;grid-template-columns:repeat(7,1fr);text-align:center;margin-top:.3125rem;font-size:.75rem;grid-gap:.8125rem}.date-7days .day[data-v-f2493dde]{position:relative;z-index:2}.date-7days .active[data-v-f2493dde]{color:#fff}.date-7days .active[data-v-f2493dde]:before{position:absolute;content:"";top:50%;left:50%;transform:translate(-50%,-50%);width:1.25rem;height:1.25rem;background:#4679ef;border-radius:.21875rem;z-index:-1}.date-7days .optional[data-v-f2493dde]:after{border:.0625rem solid #4679ef;position:absolute;content:"";top:50%;left:50%;border-radius:.3125rem;transform:translate(-50%,-50%);width:1.25rem;height:1.25rem;z-index:-1}.collection-content[data-v-f2493dde]{padding:0 0 .625rem}.collection-search[data-v-f2493dde]{padding:.3125rem .625rem}.collection-search .search-content[data-v-f2493dde]{position:relative}.collection-search .search-content .collInput[data-v-f2493dde]{padding:.1875rem .3125rem .1875rem 1.5625rem;background:#e8e8e8;border-radius:.3125rem}.collection-search .search-content .iconsearch[data-v-f2493dde]{position:absolute;left:.3125rem;top:50%;transform:translateY(-50%)}.one-cards[data-v-f2493dde]{display:flex;flex-direction:column;padding:0 .625rem}.one-cards .card-box[data-v-f2493dde]{width:calc(100% - 2.25rem);border-radius:0;background:#fff;border-radius:.53125rem;padding:.46875rem 1.125rem;margin-top:.75rem}.one-cards .card-box .box-row[data-v-f2493dde]{display:flex;justify-content:space-between;margin-top:.25rem;align-items:center}.one-cards .card-box .box-row .mineText[data-v-f2493dde]{font-weight:400;font-size:.65625rem;color:#606060}.one-cards .card-box .box-row .textblue[data-v-f2493dde]{color:#4778ec}.one-cards .card-box .box-row .row-left[data-v-f2493dde]{display:flex;justify-content:space-between}.one-cards .card-box .box-row .row-left .row-tag[data-v-f2493dde]{background:#13c57c;border-radius:.53125rem;font-size:.65625rem;color:#fff;line-height:.78125rem;text-align:center;padding:.125rem .25rem;margin-right:.71875rem}.one-cards .card-box[data-v-f2493dde]:first-child{margin-top:.1875rem}.card-transprent[data-v-f2493dde]{background:transparent!important}.card-transprent[data-v-f2493dde]:first-child{margin:0!important;padding:0!important}
|
@@ -1 +0,0 @@
|
||||
.app-container[data-v-185c4d6f]{width:100%;height:calc(100vh - var(--window-top) - var(--status-bar-height) - var(--window-bottom));background:linear-gradient(180deg,#4778ec,#002979);display:flex;flex-direction:column;position:fixed}.app-container .careerfair-AI[data-v-185c4d6f]{height:1.3125rem;font-family:Inter,Inter;font-weight:400;font-size:1.09375rem;color:#fff;line-height:1.28125rem;padding:2.65625rem 0 0 .9375rem}.app-container .careerfair-tab[data-v-185c4d6f]{margin:.625rem 0 0 .9375rem;width:-webkit-fit-content;width:fit-content;display:flex;flex-wrap:nowrap}.app-container .careerfair-tab .careerfair-tab-options[data-v-185c4d6f]{background:#4778ec;padding:0 .625rem;height:1.96875rem;line-height:1.96875rem;font-weight:400;font-size:.875rem;color:#fff;text-align:center}.app-container .careerfair-tab .actived[data-v-185c4d6f]{position:relative;background:#ffad47;box-shadow:0 .21875rem .21875rem rgba(0,0,0,.25)}.app-container .careerfair-tab .careerfair-tab-options[data-v-185c4d6f]:first-child{border-radius:.53125rem 0 0}.app-container .careerfair-tab .careerfair-tab-options[data-v-185c4d6f]:last-child{border-radius:0 .53125rem 0 0}.app-container .careerfair-scroll[data-v-185c4d6f]{background:#4778ec}.app-container .careerfair-date[data-v-185c4d6f]{height:3.71875rem;display:flex;flex-wrap:nowrap;align-items:center;color:#fff;width:-webkit-fit-content;width:fit-content}.app-container .careerfair-date .date-list[data-v-185c4d6f]{display:flex;flex-direction:column;align-items:center;justify-content:center;width:calc(23.4375rem / 7)}.app-container .careerfair-date .date-list .date-list-item[data-v-185c4d6f]:nth-child(2){font-size:.59375rem;margin-top:.3125rem}.app-container .careerfair-date .date-list .active[data-v-185c4d6f]{width:1.625rem;height:1.625rem;background:#ffad47;display:flex;align-items:center;justify-content:center;border-radius:50%}.app-container .careerfair-list-scroll[data-v-185c4d6f]{overflow:hidden;background:linear-gradient(180deg,rgba(255,255,255,.2),#fff)}.app-container .careerfair-list[data-v-185c4d6f]{display:flex;flex-direction:column;align-items:center;padding:.78125rem .875rem}.app-container .careerfair-list .careerfair-list-card[data-v-185c4d6f]{margin-top:1.125rem;width:calc(100% - 1.25rem);background:#fff;border-radius:.53125rem;padding:.625rem}.app-container .careerfair-list .careerfair-list-card .card-title[data-v-185c4d6f]{height:2.125rem;font-size:1.09375rem;color:#606060;line-height:2.125rem}.app-container .careerfair-list .careerfair-list-card .card-intro[data-v-185c4d6f],.app-container .careerfair-list .careerfair-list-card .card-address[data-v-185c4d6f],.app-container .careerfair-list .careerfair-list-card .card-company[data-v-185c4d6f],.app-container .careerfair-list .careerfair-list-card .card-date[data-v-185c4d6f]{font-weight:400;font-size:.65625rem;color:#606060;line-height:.78125rem;margin-top:.40625rem}.app-container .careerfair-list .careerfair-list-card .card-footer[data-v-185c4d6f]{display:flex;flex-wrap:nowrap;justify-content:space-between;align-items:center}.app-container .careerfair-list .careerfair-list-card .card-footer .cardfooter-ri[data-v-185c4d6f]{width:6.4375rem;height:1.75rem;line-height:1.75rem;font-size:.875rem;text-align:center;color:#fff;background:#ffad47;border-radius:.53125rem}.app-container .careerfair-list .careerfair-list-card .card-intro[data-v-185c4d6f]{display:flex;justify-content:space-between;align-items:center;flex-wrap:nowrap}.app-container .careerfair-list .careerfair-list-card .card-intro .intro-distance[data-v-185c4d6f]{height:.9375rem;background:#13c57c;padding:.09375rem .25rem;line-height:.9375rem;color:#fff;font-size:.65625rem;border-radius:.53125rem}.app-container .careerfair-list .careerfair-list-card[data-v-185c4d6f]:first-child{margin-top:0}
|
@@ -1 +0,0 @@
|
||||
.container[data-v-21f6c3ed]{background-color:#edf4ff;height:100%;display:flex;flex-direction:column;padding:.625rem}.search-bar[data-v-21f6c3ed]{font-size:1rem;font-weight:700;color:#333;margin-bottom:.625rem}.grid-container[data-v-21f6c3ed]{display:flex;flex-wrap:wrap;justify-content:space-between;gap:.625rem}.grid-item[data-v-21f6c3ed]{width:48%;height:6.25rem;border-radius:.625rem;display:flex;flex-direction:column;justify-content:center;align-items:center;color:#fff;font-size:.875rem;font-weight:700;position:relative}.grid-item .status[data-v-21f6c3ed]{position:absolute;bottom:.625rem;font-size:.75rem;background-color:rgba(255,255,255,.9);color:#333;padding:.15625rem .46875rem;border-radius:.46875rem}.blue[data-v-21f6c3ed]{background-color:#3b82f6}.green[data-v-21f6c3ed]{background-color:#22c55e}.orange[data-v-21f6c3ed]{background-color:#f59e0b}.red[data-v-21f6c3ed]{background-color:#ef4444}
|
@@ -1 +0,0 @@
|
||||
.collection-content[data-v-99c64065]{padding:.625rem 0}.one-cards[data-v-99c64065]{display:flex;flex-direction:column;padding:0 .625rem}.one-cards .card-box[data-v-99c64065]{width:calc(100% - 2.25rem);border-radius:0;background:#fff;border-radius:.53125rem;padding:.46875rem 1.125rem;margin-top:.75rem}.one-cards .card-box .box-row[data-v-99c64065]{display:flex;justify-content:space-between;margin-top:.25rem;align-items:center}.one-cards .card-box .box-row .mineText[data-v-99c64065]{font-weight:400;font-size:.65625rem;color:#606060}.one-cards .card-box .box-row .textblue[data-v-99c64065]{color:#4778ec}.one-cards .card-box .box-row .row-left[data-v-99c64065]{display:flex;justify-content:space-between}.one-cards .card-box .box-row .row-left .row-tag[data-v-99c64065]{background:#13c57c;border-radius:.53125rem;font-size:.65625rem;color:#fff;line-height:.78125rem;text-align:center;padding:.125rem .25rem;margin-right:.71875rem}.one-cards .card-box[data-v-99c64065]:first-child{margin-top:.1875rem}
|
@@ -1 +0,0 @@
|
||||
.tianditu-popop[data-v-ad9fd3a8]{position:fixed;left:0;z-index:999;background-color:rgba(0,0,0,.6);display:flex;flex-direction:column}.popup-header[data-v-ad9fd3a8]{flex:1}.popup-content[data-v-ad9fd3a8]{background-color:#fff;min-height:300px;width:100%}.animated[data-v-ad9fd3a8]{animation-duration:1s;animation-fill-mode:both}.animated.infinite[data-v-ad9fd3a8]{animation-iteration-count:infinite}.animated.hinge[data-v-ad9fd3a8]{animation-duration:2s}@keyframes fadeInUp-ad9fd3a8{0%{opacity:0;transform:translate3d(0,100%,0)}to{opacity:1;transform:none}}.fadeInUp[data-v-ad9fd3a8]{animation-name:fadeInUp-ad9fd3a8}
|
@@ -1 +0,0 @@
|
||||
import{_ as e,am as t,o as i,a as n,w as o,f as s,j as a,k as d,n as h,l as p}from"./index-BoIbtAZO.js";const l=e({name:"custom-popup",data:()=>({winWidth:0,winHeight:0,winTop:0,contentHeight:30}),props:{visible:{type:Boolean,require:!0,default:!1},hide:{type:Number,default:0},header:{type:Boolean,default:!0},contentH:{type:Number,default:30}},created(){var e=this;this.contentH&&(this.contentHeight=this.contentH),t({success:function(t){0===e.hide?(e.winWidth=t.screenWidth,e.winHeight=t.screenHeight,e.winTop=0):(e.winWidth=t.windowWidth,e.winHeight=t.windowHeight,e.winTop=t.windowTop)}})},methods:{close(e){this.$emit("onClose")}}},[["render",function(e,t,l,c,r,u){const w=p;return l.visible?(i(),n(w,{key:0,class:"tianditu-popop",style:h({height:r.winHeight+"px",width:r.winWidth+"px",top:r.winTop+"px"})},{default:o((()=>[l.header?(i(),n(w,{key:0,class:"popup-header",onClick:u.close},{default:o((()=>[s(e.$slots,"header",{},void 0,!0)])),_:3},8,["onClick"])):a("",!0),d(w,{style:h({minHeight:r.contentHeight+"vh"}),class:"popup-content fadeInUp animated"},{default:o((()=>[s(e.$slots,"default",{},void 0,!0)])),_:3},8,["style"])])),_:3},8,["style"])):a("",!0)}],["__scopeId","data-v-ad9fd3a8"]]);export{l as _};
|
@@ -1 +0,0 @@
|
||||
import{D as e,o as a,b as s,z as t,H as p}from"./index-BoIbtAZO.js";const o={__name:"dict-Label",props:["value","dictType"],setup(o){const{complete:c,dictLabel:l}=e();return(e,c)=>(a(),s("span",null,t(p(l)(o.dictType,o.value)),1))}};export{o as _};
|
@@ -1 +0,0 @@
|
||||
.container[data-v-dc2d33aa]{display:flex;flex-direction:column;background-color:#f8f8f8}.header[data-v-dc2d33aa]{padding:.625rem 1.25rem;background-color:#fff}.header .header-title[data-v-dc2d33aa]{font-size:1.75rem;font-weight:700;color:#333;margin-bottom:.3125rem}.header .header-info[data-v-dc2d33aa]{margin-top:.625rem;font-size:.75rem;color:#666;display:flex;align-items:center;justify-content:space-between}.header .header-info .location[data-v-dc2d33aa]{display:flex;align-items:center}.header .header-info .date[data-v-dc2d33aa]{flex-shrink:0}.company-list[data-v-dc2d33aa]{padding:.625rem;background-color:#fff;margin-top:.3125rem}.company-list .section-title[data-v-dc2d33aa]{padding:.625rem;font-size:1.25rem;font-weight:700;margin-bottom:.3125rem}.company-row[data-v-dc2d33aa]{display:flex;justify-content:space-between;align-items:center;padding:.625rem;border:.0625rem solid #d9d9d9;margin-top:.625rem;border-radius:.53125rem}.company-row .left[data-v-dc2d33aa]{display:flex;align-items:center;width:100%;height:100%}.company-row .left .logo[data-v-dc2d33aa]{background-color:#22c55e;color:#fff;font-size:.75rem;font-weight:700;width:7.34375rem;height:5.125rem;display:flex;align-items:center;justify-content:center;border-radius:.375rem;margin-right:.625rem}.company-row .left .company-info[data-v-dc2d33aa]{min-height:5.125rem;flex:1;display:flex;flex-direction:column;justify-content:space-between}.company-row .left .company-info .company-name[data-v-dc2d33aa]{font-size:.875rem;color:#333;font-weight:700}.company-row .left .company-info .industry[data-v-dc2d33aa]{font-size:.75rem;color:#666}.company-row .left .company-info .details[data-v-dc2d33aa]{font-size:.75rem;color:#666;display:flex;align-items:center;justify-content:space-between}
|
@@ -1 +0,0 @@
|
||||
.secondary-title[data-v-efd19bad]{font-weight:700;padding:1.25rem 0 .3125rem .9375rem}.expected-station[data-v-efd19bad]{width:100%;overflow:hidden;display:flex;flex-direction:column}.sex-search[data-v-efd19bad]{width:calc(100% - 1.75rem);padding:.3125rem .875rem;display:grid;position:relative}.sex-search .iconsearch[data-v-efd19bad]{position:absolute;left:1.25rem;top:.625rem}.sex-search .searchinput[data-v-efd19bad]{border-radius:.3125rem;background:#fff;padding:.3125rem 0 .3125rem 1.8125rem}.sex-content[data-v-efd19bad]{background:#fff;border-radius:.625rem;width:100%;margin-top:.625rem;display:flex;border-bottom:2px solid #d9d9d9;overflow:hidden;height:100%}.sex-content .sex-content-left[data-v-efd19bad]{width:7.8125rem}.sex-content .sex-content-left .left-list-btn[data-v-efd19bad]{padding:0 1.25rem 0 .75rem;display:grid;place-items:center;height:3.125rem;text-align:center;color:#606060;font-size:.875rem;position:relative}.sex-content .sex-content-left .positionNum[data-v-efd19bad]{position:absolute;right:0;top:50%;transform:translateY(-50%);color:#fff;background:#4778ec;border-radius:50%;width:1.125rem;height:1.125rem}.sex-content .sex-content-left .left-list-btned[data-v-efd19bad]{color:#4778ec;position:relative}.sex-content .sex-content-left .left-list-btned[data-v-efd19bad]:after{position:absolute;left:.625rem;content:"";width:.21875rem;height:1.1875rem;background:#4778ec;border-radius:0}.sex-content .sex-content-right[data-v-efd19bad]{border-left:2px solid #d9d9d9;flex:1}.sex-content .sex-content-right .grid-sex[data-v-efd19bad]{display:grid;grid-template-columns:50% 50%;place-items:center;padding:0 0 1.25rem}.sex-content .sex-content-right .grid-sex .sex-right-btn[data-v-efd19bad]{width:6.59375rem;height:2.625rem;font-size:1rem;line-height:1.28125rem;text-align:center;display:grid;place-items:center;background:#d9d9d9;border-radius:.625rem;margin-top:.9375rem;color:#606060}.sex-content .sex-content-right .grid-sex .sex-right-btned[data-v-efd19bad]{color:#fff;background:#4778ec}
|
@@ -1 +0,0 @@
|
||||
import{_ as e,a0 as t,v as s,x as a,o as c,a as l,w as i,k as o,j as n,b as r,F as h,r as d,d as u,y as f,z as p,I as y,J as k,K as g,l as m,S as b}from"./index-BoIbtAZO.js";import{_}from"./uni-icons.SM4XIXQc.js";const x=e({name:"expected-station",data:()=>({leftValue:{},rightValue:[],stationCateLog:0,copyTree:[]}),props:{station:{type:Array,default:[]},search:{type:Boolean,default:!0},max:{type:Number,default:5}},created(){this.copyTree=this.station,this.copyTree.length&&(this.leftValue=this.copyTree[0],this.rightValue=this.copyTree[0].children)},watch:{station(e){this.copyTree=this.station,this.copyTree.length&&(this.leftValue=this.copyTree[0],this.rightValue=this.copyTree[0].children)}},methods:{changeStationLog(e){this.leftValue=e,this.rightValue=e.children},addItem(e){let s=[],a=0;for(const t of this.copyTree)for(const e of t.children)for(const t of e.children)t.checked&&a++;for(const c of this.copyTree){c.checkednumber=0;for(const l of c.children)for(const i of l.children){if(i.id===e.id){if(!i.checked&&a>=5){t({title:"最多选择5个职位",icon:"none"});continue}i.checked=!i.checked}i.checked&&(s.push(`${i.id}`),c.checkednumber++)}}s=s.join(","),this.$emit("onChange",s)}}},[["render",function(e,t,x,T,V,C){const j=s(a("uni-icons"),_),w=g,I=m,L=b;return c(),l(I,{class:"expected-station"},{default:i((()=>[x.search?(c(),l(I,{key:0,class:"sex-search"},{default:i((()=>[o(j,{class:"iconsearch",type:"search",size:"20"}),o(w,{class:"uni-input searchinput","confirm-type":"search"})])),_:1})):n("",!0),o(I,{class:"sex-content"},{default:i((()=>[o(L,{"show-scrollbar":!1,"scroll-y":!0,class:"sex-content-left"},{default:i((()=>[(c(!0),r(h,null,d(V.copyTree,(e=>(c(),l(I,{key:e.id,class:u(["left-list-btn",{"left-list-btned":e.id===V.leftValue.id}]),onClick:t=>C.changeStationLog(e)},{default:i((()=>[f(p(e.label)+" ",1),y(o(I,{class:"positionNum"},{default:i((()=>[f(p(e.checkednumber),1)])),_:2},1536),[[k,e.checkednumber]])])),_:2},1032,["class","onClick"])))),128))])),_:1}),o(L,{"show-scrollbar":!1,"scroll-y":!0,class:"sex-content-right"},{default:i((()=>[(c(!0),r(h,null,d(V.rightValue,(e=>(c(),l(I,{key:e.id},{default:i((()=>[o(I,{class:"secondary-title"},{default:i((()=>[f(p(e.label),1)])),_:2},1024),o(I,{class:"grid-sex"},{default:i((()=>[(c(!0),r(h,null,d(e.children,(e=>(c(),l(I,{key:e.id,class:u([{"sex-right-btned":e.checked},"sex-right-btn"]),onClick:t=>C.addItem(e)},{default:i((()=>[f(p(e.label),1)])),_:2},1032,["class","onClick"])))),128))])),_:2},1024)])),_:2},1024)))),128))])),_:1})])),_:1})])),_:1})}],["__scopeId","data-v-efd19bad"]]);export{x as _};
|
Before Width: | Height: | Size: 5.3 KiB |
@@ -1 +0,0 @@
|
||||
.tab-container[data-v-b9170ed9]{width:100%;height:100%;display:flex;align-items:center;justify-content:center;flex-direction:row}.uni-margin-wrap[data-v-b9170ed9],.swiper[data-v-b9170ed9]{width:100%;height:100%}.swiper-item[data-v-b9170ed9]{display:block;width:100%;height:100%}.container[data-v-b6f000c9]{background:linear-gradient(#4778ec,#002979);width:100%;height:calc(100vh - var(--window-top) - var(--status-bar-height) - var(--window-bottom));position:fixed}.login-content[data-v-b6f000c9]{position:absolute;left:50%;top:40%;transform:translate(-50%,-50%);display:flex;align-items:flex-end;flex-wrap:nowrap}.login-content .logo[data-v-b6f000c9]{width:8.3125rem;height:5.6875rem}.login-content .logo-title[data-v-b6f000c9]{font-size:2.75rem;color:#fff;width:5.625rem}.btns[data-v-b6f000c9]{position:absolute;top:70%;left:50%;transform:translate(-50%)}.btns .wxlogin[data-v-b6f000c9]{width:17.5625rem;height:4.375rem;border-radius:2.1875rem;background-color:#13c57c;color:#fff;text-align:center;line-height:4.375rem;font-size:2.1875rem}.btns .wxaddress[data-v-b6f000c9]{color:#bbb;margin-top:2.1875rem;text-align:center}.tabtwo[data-v-b6f000c9]{padding:1.25rem;display:flex;flex-direction:column;align-items:center;justify-content:space-between;height:calc(100% - 1.25rem)}.tabtwo-top[data-v-b6f000c9]{margin:6.9375rem 0 0;width:100%}.tabtwo-sex[data-v-b6f000c9]{display:flex;flex-direction:column;justify-content:center;align-items:center;color:#fff;font-size:1.25rem;margin:6.25rem 1.875rem 0}.tabtwo-sex .sex-img[data-v-b6f000c9]{width:5.75rem;height:5.75rem}.dot[data-v-b6f000c9]{width:2.125rem;height:2.125rem;border-radius:50%;background:#d1d1d6;position:relative}.dot[data-v-b6f000c9]:before{content:"";width:1.375rem;height:1.375rem;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);border-radius:50%;background:#1e4baa}.doted[data-v-b6f000c9]{background:#13c57c}.doted[data-v-b6f000c9]:after{content:"";width:1.0625rem;height:1.0625rem;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);border-radius:50%;background:#13c57c}.agebtn[data-v-b6f000c9]{width:19.6875rem;height:3.375rem;border-radius:.625rem;background:#d9d9d9;text-align:center;line-height:3.375rem;font-size:1.25rem;margin-top:1.5625rem;color:#606060}.agebtned[data-v-b6f000c9]{background:#13c57c;color:#fff}.nextstep[data-v-b6f000c9]{width:19.6875rem;height:3.0625rem;border-radius:.625rem;background:#13c57c;text-align:center;line-height:3.0625rem;font-size:1.125rem;color:#fff;margin-bottom:4.6875rem}.confirmStep[data-v-b6f000c9]{margin-bottom:1.5625rem}.eduction-content[data-v-b6f000c9]{width:-webkit-fit-content;width:fit-content;display:grid;grid-template-columns:9.375rem 9.375rem;grid-gap:.625rem;margin-top:1.5625rem}.eduction-content .eductionbtn[data-v-b6f000c9]{width:9.375rem;height:3.375rem;border-radius:.625rem;background:#d9d9d9;text-align:center;line-height:3.375rem;font-size:1.125rem;color:#606060}.eduction-content .eductionbtned[data-v-b6f000c9]{background:#13c57c;color:#fff}.salary[data-v-b6f000c9]{width:-webkit-fit-content;width:fit-content;display:grid;grid-template-columns:20rem;grid-gap:.625rem;margin-top:1.5625rem}.salary .picker-view[data-v-b6f000c9]{width:100%;height:18.75rem;margin-top:.625rem}.salary .picker-view .uni-picker-view-mask[data-v-b6f000c9]{background:rgba(0,0,0,0)}.salary .item .item-child[data-v-b6f000c9]{line-height:2.8125rem;font-size:1.1875rem;color:#606060;text-align:center;background:#d9d9d9;border-radius:.625rem;margin:.625rem .3125rem}.salary .item .item-childed[data-v-b6f000c9]{line-height:3.28125rem;margin:.3125rem .15625rem;background:#13c57c;color:#fff}.salary .item-center[data-v-b6f000c9]{width:1.25rem;line-height:18.75rem;width:1.59375rem;height:1.46875rem;font-family:Inter,Inter;font-weight:400;font-size:.875rem;color:#fff;text-align:center;font-style:normal;text-transform:none}.salary .uni-picker-view-indicator[data-v-b6f000c9]:after{border:0}.salary .uni-picker-view-indicator[data-v-b6f000c9]:before{border:0}.salary .center-text[data-v-b6f000c9]{color:#fff;text-align:center;line-height:12.5rem}.salary .salary-content[data-v-b6f000c9]{width:9.375rem;height:11.875rem}.salary .salary-content .salary-content-item[data-v-b6f000c9]{height:3.25rem;line-height:3.25rem;margin:.625rem .3125rem;border-radius:.625rem;background:#d9d9d9;text-align:center;font-size:1.1875rem}.salary .salary-content .salary-content-item-selected[data-v-b6f000c9]{margin:.3125rem .15625rem;background:#13c57c;color:#fff}.sex-two[data-v-b6f000c9]{padding-left:0;padding-right:0;background:#4678ec}.sex-content[data-v-b6f000c9]{border-radius:.625rem;width:100%;margin-top:.625rem;margin-bottom:1.25rem;display:flex;overflow:hidden;height:100%}
|
Before Width: | Height: | Size: 4.8 KiB |
@@ -1 +0,0 @@
|
||||
import{a5 as a,o as t,a as e,w as n,y as r,z as s,l as o,p as l}from"./index-BoIbtAZO.js";const u={__name:"Salary-Expectation",props:["minSalary","maxSalary","isMonth"],setup(l){const{minSalary:u,maxSalary:i,isMonth:c}=l,m=a((()=>u&&i?c?`${u}-${i}/月`:`${u/1e3}k-${i/1e3}k`:"面议"));return(a,l)=>{const u=o;return t(),e(u,null,{default:n((()=>[r(s(m.value),1)])),_:1})}}},i={__name:"matchingDegree",props:["job"],setup(u){const{job:i}=u,{similarityJobs:c,throttle:m}=l("globalFunction"),p=a((()=>{if(!i)return"";const a=c.calculationMatchingDegree(i);return a?"匹配度 "+a.overallMatch:""}));return(a,l)=>{const u=o;return t(),e(u,null,{default:n((()=>[r(s(p.value),1)])),_:1})}}};export{u as _,i as a};
|
@@ -1 +0,0 @@
|
||||
.app-container[data-v-ca607a35]{width:100%;min-height:calc(100vh - var(--window-top) - var(--status-bar-height) - var(--window-bottom));background:linear-gradient(180deg,#4778ec,#002979);display:flex;flex-direction:column}.app-container .mine-AI[data-v-ca607a35]{height:1.3125rem;font-family:Inter,Inter;font-weight:400;font-size:1.09375rem;color:#fff;line-height:1.28125rem;padding:2.65625rem 0 0 .9375rem}.app-container .mine-userinfo[data-v-ca607a35]{display:flex;justify-content:flex-start;align-items:center;padding:2rem}.app-container .mine-userinfo .userindo-head[data-v-ca607a35]{width:3.15625rem;height:3.15625rem;background:#d9d9d9;border-radius:50%;overflow:hidden;margin-right:1.25rem}.app-container .mine-userinfo .userindo-head .userindo-head-img[data-v-ca607a35]{width:100%;height:100%}.app-container .mine-userinfo .userinfo-ls[data-v-ca607a35]{display:flex;flex-direction:column;align-items:flex-start}.app-container .mine-userinfo .userinfo-ls .userinfo-ls-name[data-v-ca607a35]{font-size:1.3125rem;color:#fff}.app-container .mine-userinfo .userinfo-ls .userinfo-ls-resume[data-v-ca607a35]{font-size:.65625rem;color:#d9d9d9}.app-container .mine-tab[data-v-ca607a35]{margin:0 .9375rem;height:3.90625rem;background:#fff;border-radius:.53125rem;display:flex;padding:.46875rem}.app-container .mine-tab .tab-item[data-v-ca607a35]{display:flex;flex-direction:column;width:25%;align-items:center;justify-content:center;position:relative}.app-container .mine-tab .tab-item .item-img[data-v-ca607a35]{height:1.71875rem;width:1.5625rem}.app-container .mine-tab .tab-item .item-text[data-v-ca607a35]{font-size:.65625rem;color:#000;line-height:.78125rem;text-align:center;margin-top:.3125rem}.app-container .mine-tab .tab-item[data-v-ca607a35]:after{position:absolute;right:0;content:"";width:0;height:3rem;border-radius:0;border-right:.0625rem solid #4778ec}.app-container .mine-tab .tab-item[data-v-ca607a35]:last-child:after{border-right:0}.app-container .mine-tab .tab-item:nth-child(2)>.item-img[data-v-ca607a35]{width:1.59375rem;height:1.40625rem;margin-top:.1875rem;margin-bottom:.125rem}.app-container .mine-tab .tab-item:nth-child(3)>.item-img[data-v-ca607a35]{width:1.9375rem;height:1.28125rem;margin-top:.1875rem;margin-bottom:.3125rem}.app-container .mine-tab .tab-item:nth-child(4)>.item-img[data-v-ca607a35]{width:1.40625rem;height:1.46875rem;margin-bottom:.25rem}.app-container .mine-options[data-v-ca607a35]{margin:1.34375rem .9375rem;min-height:4.84375rem;background:#fff;border-radius:.53125rem;padding:.75rem 1.40625rem;display:flex;flex-direction:column;min-height:-webkit-min-content;min-height:min-content}.app-container .mine-options .mine-options-item[data-v-ca607a35]{height:2.5rem;font-size:.875rem;color:#000;line-height:2.5rem;border-bottom:.0625rem solid #4778ec;padding:0 .9375rem}.app-container .mine-options .mine-logout[data-v-ca607a35]{margin:7.8125rem auto 0;width:12.46875rem;height:3rem;background:#ffad47;border-radius:.53125rem;text-align:center;line-height:3rem;color:#fff;font-size:1.09375rem}
|
@@ -1 +0,0 @@
|
||||
.app-container[data-v-6119d1bb]{width:100%;height:calc(100vh - var(--window-top) - var(--status-bar-height) - var(--window-bottom));background:linear-gradient(180deg,#4778ec,#002979);display:flex;flex-direction:column}.app-container .msg-AI[data-v-6119d1bb]{height:1.3125rem;font-family:Inter,Inter;font-weight:400;font-size:1.09375rem;color:#fff;line-height:1.28125rem;padding:2.65625rem 0 0 .9375rem}.app-container .msg-tab[data-v-6119d1bb]{padding:2.65625rem 0 0 .9375rem;display:flex;justify-content:flex-start;align-items:center;color:#d9d9d9}.app-container .msg-tab .msg-tab-item[data-v-6119d1bb]{margin-right:1.25rem}.app-container .msg-tab .actived[data-v-6119d1bb]{font-size:.875rem;color:#fff;text-shadow:0 .4375rem .4375rem rgba(0,0,0,.25)}.app-container .msg-list[data-v-6119d1bb]{flex:1;overflow:hidden}.app-container .msg-list .swiper[data-v-6119d1bb]{height:100%}.app-container .msg-list .swiper .list[data-v-6119d1bb]{display:flex;flex-direction:column}.app-container .msg-list .swiper .list .list-card[data-v-6119d1bb]{height:2.09375rem;width:calc(100% - 3.6875rem);background:#fff;border-radius:.53125rem;display:flex;justify-content:flex-start;align-items:center;padding:.8125rem 1.125rem;margin:1.125rem .71875rem}.app-container .msg-list .swiper .list .list-card .card-img[data-v-6119d1bb]{width:1.96875rem;height:1.96875rem;background:#d9d9d9;border-radius:50%;display:grid;place-items:center;margin-right:.9375rem}.app-container .msg-list .swiper .list .list-card .card-img .card-img-flame[data-v-6119d1bb]{width:100%;height:100%}.app-container .msg-list .swiper .list .list-card .card-info[data-v-6119d1bb]{flex:1;display:flex;align-items:flex-start;flex-direction:column}.app-container .msg-list .swiper .list .list-card .card-info .info-title[data-v-6119d1bb]{font-weight:400;font-size:.875rem;color:#000}.app-container .msg-list .swiper .list .list-card .card-info .info-text[data-v-6119d1bb],.app-container .msg-list .swiper .list .list-card .card-time[data-v-6119d1bb]{font-size:.53125rem;color:#606060}
|
@@ -1 +0,0 @@
|
||||
.container[data-v-dbb991d2]{width:100%;height:calc(100vh - var(--window-top) - var(--status-bar-height) - var(--window-bottom));background:linear-gradient(180deg,#4778ec,#002979);display:flex;flex-direction:column;align-items:center}.header[data-v-dbb991d2]{display:flex;align-items:center;padding:.9375rem 1.875rem;width:calc(100% - 3.75rem);border-radius:0 0 .625rem .625rem}.header .avatar[data-v-dbb991d2]{width:3.125rem;height:3.125rem;background-color:#ccc;border-radius:50%;margin-right:.625rem}.header .info[data-v-dbb991d2]{display:flex;flex-direction:column}.header .info .name-row[data-v-dbb991d2]{display:flex;align-items:center;position:relative}.header .info .name-row .name[data-v-dbb991d2]{font-size:1.125rem;font-weight:700;color:#fff}.header .info .name-row .edit-icon[data-v-dbb991d2]{width:1.25rem;height:1.25rem;border-radius:50%;position:absolute;right:-1.875rem;top:.1875rem}.header .info .name-row .edit-icon .img[data-v-dbb991d2]{width:100%;height:100%}.header .info .details[data-v-dbb991d2]{font-size:.75rem;color:#dbeafe}.resume-info[data-v-dbb991d2]{padding:0 .8125rem;width:calc(100% - 1.625rem);margin-top:.625rem}.info-card[data-v-dbb991d2]{display:flex;flex-direction:column;justify-content:space-between;align-items:center;color:#fff;padding:.3125rem .75rem;border-radius:.375rem;margin-bottom:.3125rem;background:#4778ec;box-shadow:0 .21875rem .21875rem rgba(0,0,0,.25);border-radius:.53125rem;position:relative}.info-card .card-content[data-v-dbb991d2]{width:100%;display:flex;line-height:1.8125rem;margin-top:.5rem;position:relative}.info-card .label[data-v-dbb991d2]{width:5rem;height:1rem;font-size:.875rem;color:#fff;text-align:justify;margin-right:.625rem}.info-card .long[data-v-dbb991d2]{width:5.625rem;margin-right:0}.info-card .label[data-v-dbb991d2]:after{content:"";display:inline-block;width:100%}.info-card .value[data-v-dbb991d2]{font-size:.875rem;color:#fff}.info-card .card-content[data-v-dbb991d2]:first-child{margin-top:0}.info-card .edit-icon[data-v-dbb991d2]{position:absolute;right:.3125rem;top:.3125rem;width:1.25rem;height:1.25rem}.info-card .edit-icon .img[data-v-dbb991d2]{width:100%;height:100%}.upload-btn[data-v-dbb991d2]{margin-top:.625rem}.upload-btn .btn[data-v-dbb991d2]{display:flex;align-items:center;box-shadow:0 .21875rem .21875rem rgba(0,0,0,.25);height:2.5rem;background-color:#22c55e;color:#fff;font-size:.875rem;font-weight:700;border-radius:.625rem}.popContent[data-v-dbb991d2]{padding:.75rem;background:#4778ec;height:calc(100% - 1.53125rem)}.popContent .sex-content[data-v-dbb991d2]{border-radius:.625rem;width:100%;margin-top:.625rem;margin-bottom:1.25rem;display:flex;overflow:hidden;height:calc(100% - 3.125rem);border:1px solid #4778ec}.popContent .s-header[data-v-dbb991d2]{display:flex;justify-content:space-between;text-align:center;font-size:16px}.popContent .s-header .heade-lf[data-v-dbb991d2]{line-height:30px;width:50px;height:30px;border-radius:4px;border:1px solid #666;color:#666;background:#fff}.popContent .s-header .heade-ri[data-v-dbb991d2]{line-height:30px;width:50px;height:30px;border-radius:4px;border:1px solid #1b66ff;background-color:#1b66ff;color:#fff}
|
@@ -1 +0,0 @@
|
||||
import{_ as a,p as e,u as t,s,G as l,ap as o,v as c,x as i,a as n,w as r,l as d,o as u,k as p,b as m,r as g,F as f,y as _,z as x,j as b,H as w}from"./index-BoIbtAZO.js";import{_ as y,a as v}from"./matchingDegree.DIUzxusN.js";import{_ as j}from"./dict-Label.Dsm7GAlr.js";const T=a({__name:"Intendedposition",setup(a){const{$api:T,navTo:h,vacanciesTo:k}=e("globalFunction");t(),s({});const S=s({page:0,list:[],total:0,maxPage:1,pageSize:10});function z(a="add"){"refresh"===a&&(S.page=0,S.maxPage=1),"add"===a&&S.page<S.maxPage&&(S.page+=1);let e={current:S.page,pageSize:S.pageSize};T.createRequest("/app/user/apply/job",e).then((e=>{const{rows:t,total:s}=e;if("add"===a){const a=S.pageSize*(S.page-1),e=S.list.length,s=t;S.list.splice(a,e,...s)}else S.list=t;S.total=e.total,S.maxPage=Math.ceil(S.total/S.pageSize)}))}return l((()=>{console.log("onLoad"),z()})),o((()=>{z()})),(a,e)=>{const t=d,s=c(i("Salary-Expectation"),y),l=c(i("matchingDegree"),v);return u(),n(t,{class:"collection-content"},{default:r((()=>[p(t,{class:"one-cards"},{default:r((()=>[(u(!0),m(f,null,g(S.list,((a,e)=>(u(),n(t,{class:"card-box",key:e,onClick:e=>{return t=a.jobId,void h(`/packageA/pages/post/post?jobId=${btoa(t)}`);var t}},{default:r((()=>[p(t,{class:"box-row mar_top0"},{default:r((()=>[p(t,{class:"row-left"},{default:r((()=>[_(x(a.jobTitle),1)])),_:2},1024),p(t,{class:"row-right"},{default:r((()=>[p(s,{"max-salary":a.maxSalary,"min-salary":a.minSalary},null,8,["max-salary","min-salary"])])),_:2},1024)])),_:2},1024),p(t,{class:"box-row"},{default:r((()=>[p(t,{class:"row-left"},{default:r((()=>[a.educatio?(u(),n(t,{key:0,class:"row-tag"},{default:r((()=>[p(j,{dictType:"education",value:a.education},null,8,["value"])])),_:2},1024)):b("",!0),a.experience?(u(),n(t,{key:1,class:"row-tag"},{default:r((()=>[p(j,{dictType:"experience",value:a.experience},null,8,["value"])])),_:2},1024)):b("",!0)])),_:2},1024)])),_:2},1024),p(t,{class:"box-row mar_top0"},{default:r((()=>[p(t,{class:"row-item mineText"},{default:r((()=>[_(x(a.postingDate||"发布日期"),1)])),_:2},1024),p(t,{class:"row-item mineText"},{default:r((()=>[_(x(w(k)(a.vacancies)),1)])),_:2},1024),p(t,{class:"row-item mineText textblue"},{default:r((()=>[p(l,{job:a},null,8,["job"])])),_:2},1024),p(t,{class:"row-item"})])),_:2},1024),p(t,{class:"box-row"},{default:r((()=>[p(t,{class:"row-left mineText"},{default:r((()=>[_(x(a.companyName),1)])),_:2},1024),p(t,{class:"row-right mineText"},{default:r((()=>[_(" 青岛 "),p(j,{dictType:"area",value:a.jobLocationAreaCode},null,8,["value"])])),_:2},1024)])),_:2},1024)])),_:2},1032,["onClick"])))),128))])),_:1})])),_:1})}}},[["__scopeId","data-v-6c0afbd6"]]);export{T as default};
|
@@ -1 +0,0 @@
|
||||
import{_ as a,p as e,s as l,q as s,G as t,v as c,x as o,a as i,w as n,l as u,o as d,k as p,y as r,z as f,b as _,r as m,F as y,U as g,H as v,j as b}from"./index-BoIbtAZO.js";import{_ as j}from"./uni-icons.SM4XIXQc.js";import{_ as x}from"./dict-Label.Dsm7GAlr.js";const h=a({__name:"UnitDetails",setup(a){const{$api:h,navTo:k}=e("globalFunction"),z=l({page:0,list:[],total:0,maxPage:1,pageSize:10}),S=s({});return t((a=>{var e;console.log(a),e=a.companyId,h.createRequest(`/app/company/${e}`).then((a=>{S.value=a.data,function(a="add"){"refresh"===a&&(z.page=0,z.maxPage=1),"add"===a&&z.page<z.maxPage&&(z.page+=1);let e={current:z.page,pageSize:z.pageSize};h.createRequest(`/app/company/job/${S.value.companyId}`,e).then((a=>{z.list=a.rows,z.total=a.total,z.maxPage=Math.ceil(z.total/z.pageSize)}))}()}))})),(a,e)=>{const l=g,s=c(o("uni-icons"),j),t=u;return d(),i(t,{class:"container"},{default:n((()=>[p(t,{class:"company-header"},{default:n((()=>[p(l,{class:"company-name"},{default:n((()=>[r(f(S.value.name),1)])),_:1}),p(t,{class:"company-info"},{default:n((()=>[p(t,{class:"location"},{default:n((()=>[p(s,{type:"location-filled",color:"#4778EC",size:"24"}),r(" 青岛 "+f(S.value.location),1)])),_:1}),p(t,{class:"industry",style:{display:"inline-block"}},{default:n((()=>[r(f(S.value.industry)+" ",1),p(x,{dictType:"scale",value:S.value.scale},null,8,["value"])])),_:1})])),_:1})])),_:1}),p(t,{class:"hr"}),p(t,{class:"company-description"},{default:n((()=>[p(t,{class:"section-title"},{default:n((()=>[r("单位介绍")])),_:1}),p(l,{class:"description"},{default:n((()=>[r(f(S.value.description),1)])),_:1})])),_:1}),p(t,{class:"job-list"},{default:n((()=>[p(l,{class:"section-title"},{default:n((()=>[r("在招职位")])),_:1}),(d(!0),_(y,null,m(z.list,(a=>(d(),i(t,{class:"job-row",key:a.id,onClick:e=>v(k)(`/packageA/pages/post/post?jobId=${a.jobId}`)},{default:n((()=>[p(t,{class:"left"},{default:n((()=>[p(l,{class:"job-title"},{default:n((()=>[r(f(a.jobTitle),1)])),_:2},1024),p(t,{class:"job-tags"},{default:n((()=>[p(t,{class:"tag"},{default:n((()=>[p(x,{dictType:"education",value:a.education},null,8,["value"])])),_:2},1024),p(t,{class:"tag"},{default:n((()=>[p(x,{dictType:"experience",value:a.experience},null,8,["value"])])),_:2},1024),p(t,{class:"tag"},{default:n((()=>[r(f(a.vacancies)+"人",1)])),_:2},1024)])),_:2},1024),p(l,{class:"location"},{default:n((()=>[r(" 青岛 "),p(x,{dictType:"area",value:a.jobLocationAreaCode},null,8,["value"])])),_:2},1024)])),_:2},1024),p(t,{class:"right"},{default:n((()=>[p(l,{class:"salary"},{default:n((()=>[r(f(a.minSalary)+"-"+f(a.maxSalary)+"/月",1)])),_:2},1024),a.isHot?(d(),i(l,{key:0,class:"hot"},{default:n((()=>[r("🔥")])),_:1})):b("",!0)])),_:2},1024)])),_:2},1032,["onClick"])))),128))])),_:1})])),_:1})}}},[["__scopeId","data-v-1fe8fba7"]]);export{h as default};
|
@@ -1 +0,0 @@
|
||||
import{_ as a,p as s,q as e,G as t,a as c,w as n,l as o,o as l,k as r,y as d,b as u,r as i,F as p,n as f,z as m,U as y}from"./index-BoIbtAZO.js";const _=a({__name:"choiceness",setup(a){const{$api:_,navTo:k}=s("globalFunction"),C=e([]);function g(){_.createRequest("/app/company/card").then((a=>{const{rows:s,total:e}=a;C.value=s}))}return t((()=>{g()})),(a,s)=>{const e=o,t=y;return l(),c(e,{class:"container"},{default:n((()=>[r(e,{class:"search-bar"},{default:n((()=>[d("精选企业")])),_:1}),r(e,{class:"grid-container"},{default:n((()=>[(l(!0),u(p,null,i(C.value,(a=>(l(),c(e,{class:"grid-item",style:f({backgroundColor:a.backgroudColor}),key:a.companyCardId},{default:n((()=>[r(t,{class:"title"},{default:n((()=>[d(m(a.name),1)])),_:2},1024),a.isCollection?(l(),c(e,{key:0,class:"status",onClick:s=>function(a){_.createRequest(`/app/company/card/collection/${a.companyCardId}`,{},"DELETE").then((a=>{g(),_.msg("取消关注")}))}(a)},{default:n((()=>[d("已关注 ✓")])),_:2},1032,["onClick"])):(l(),c(e,{key:1,class:"status",onClick:s=>function(a){_.createRequest(`/app/company/card/collection/${a.companyCardId}`,{},"PUT").then((a=>{g(),_.msg("关注成功")}))}(a)},{default:n((()=>[d("特别关注")])),_:2},1032,["onClick"]))])),_:2},1032,["style"])))),128))])),_:1})])),_:1})}}},[["__scopeId","data-v-21f6c3ed"]]);export{_ as default};
|
@@ -1 +0,0 @@
|
||||
import{_ as a,p as e,u as t,s,G as l,ap as o,v as c,x as i,a as r,w as n,l as u,o as d,k as p,b as m,r as g,F as f,y as _,z as x,j as b,H as w}from"./index-BoIbtAZO.js";import{_ as y,a as v}from"./matchingDegree.DIUzxusN.js";import{_ as j}from"./dict-Label.Dsm7GAlr.js";const T=a({__name:"collection",setup(a){const{$api:T,navTo:h,vacanciesTo:k}=e("globalFunction");t(),s({});const S=s({page:0,list:[],total:0,maxPage:1,pageSize:10});function z(a="add"){"refresh"===a&&(S.page=0,S.maxPage=1),"add"===a&&S.page<S.maxPage&&(S.page+=1);let e={current:S.page,pageSize:S.pageSize};T.createRequest("/app/user/collection/job",e).then((e=>{const{rows:t,total:s}=e;if("add"===a){const a=S.pageSize*(S.page-1),e=S.list.length,s=t;S.list.splice(a,e,...s)}else S.list=t;S.total=e.total,S.maxPage=Math.ceil(S.total/S.pageSize)}))}return l((()=>{z()})),o((()=>{z()})),(a,e)=>{const t=u,s=c(i("Salary-Expectation"),y),l=c(i("matchingDegree"),v);return d(),r(t,{class:"collection-content"},{default:n((()=>[p(t,{class:"one-cards"},{default:n((()=>[(d(!0),m(f,null,g(S.list,((a,e)=>(d(),r(t,{class:"card-box",key:e,onClick:e=>{return t=a.jobId,void h(`/packageA/pages/post/post?jobId=${btoa(t)}`);var t}},{default:n((()=>[p(t,{class:"box-row mar_top0"},{default:n((()=>[p(t,{class:"row-left"},{default:n((()=>[_(x(a.jobTitle),1)])),_:2},1024),p(t,{class:"row-right"},{default:n((()=>[p(s,{"max-salary":a.maxSalary,"min-salary":a.minSalary},null,8,["max-salary","min-salary"])])),_:2},1024)])),_:2},1024),p(t,{class:"box-row"},{default:n((()=>[p(t,{class:"row-left"},{default:n((()=>[a.educatio?(d(),r(t,{key:0,class:"row-tag"},{default:n((()=>[p(j,{dictType:"education",value:a.education},null,8,["value"])])),_:2},1024)):b("",!0),a.experience?(d(),r(t,{key:1,class:"row-tag"},{default:n((()=>[p(j,{dictType:"experience",value:a.experience},null,8,["value"])])),_:2},1024)):b("",!0)])),_:2},1024)])),_:2},1024),p(t,{class:"box-row mar_top0"},{default:n((()=>[p(t,{class:"row-item mineText"},{default:n((()=>[_(x(a.postingDate||"发布日期"),1)])),_:2},1024),p(t,{class:"row-item mineText"},{default:n((()=>[_(x(w(k)(a.vacancies)),1)])),_:2},1024),p(t,{class:"row-item mineText textblue"},{default:n((()=>[p(l,{job:a},null,8,["job"])])),_:2},1024),p(t,{class:"row-item"})])),_:2},1024),p(t,{class:"box-row"},{default:n((()=>[p(t,{class:"row-left mineText"},{default:n((()=>[_(x(a.companyName),1)])),_:2},1024),p(t,{class:"row-right mineText"},{default:n((()=>[_(" 青岛 "),p(j,{dictType:"area",value:a.jobLocationAreaCode},null,8,["value"])])),_:2},1024)])),_:2},1024)])),_:2},1032,["onClick"])))),128))])),_:1})])),_:1})}}},[["__scopeId","data-v-99c64065"]]);export{T as default};
|
@@ -1 +0,0 @@
|
||||
import{_ as a,v as s,x as e,a as l,w as t,l as d,o as n,k as i,y as c,b as o,r as u,F as f,U as r,d as _,z as m}from"./index-BoIbtAZO.js";import{_ as y}from"./uni-icons.SM4XIXQc.js";const p=a({data:()=>({companies:[{id:1,name:"湖南沃森电器科技有限公司",industry:"制造业 100-299人"},{id:2,name:"青岛成达汽车销售集团",industry:"制造业 100-299人"},{id:3,name:"青岛日森电器有限公司",industry:"制造业 100-299人"},{id:4,name:"青岛融合网络通信有限公司",industry:"制造业 100-299人"}]})},[["render",function(a,p,h,x,z,g){const j=r,k=s(e("uni-icons"),y),v=d;return n(),l(v,{class:"container"},{default:t((()=>[i(v,{class:"header"},{default:t((()=>[i(j,{class:"header-title"},{default:t((()=>[c("2024年春季青岛市商贸服务业招聘会")])),_:1}),i(v,{class:"header-info"},{default:t((()=>[i(v,{class:"location"},{default:t((()=>[i(k,{type:"location-filled",color:"#4778EC",size:"24"}),c(" 青岛 市南区延安三路105号 ")])),_:1}),i(j,{class:"date"},{default:t((()=>[c("2024年7月31日 周三")])),_:1})])),_:1})])),_:1}),i(v,{class:"company-list"},{default:t((()=>[i(j,{class:"section-title"},{default:t((()=>[c("参会单位")])),_:1}),(n(!0),o(f,null,u(z.companies,(a=>(n(),l(v,{class:"company-row",key:a.id},{default:t((()=>[i(v,{class:"left"},{default:t((()=>[i(v,{class:_(["logo","logo-"+a.id])},{default:t((()=>[c(m(a.id),1)])),_:2},1032,["class"]),i(v,{class:"company-info"},{default:t((()=>[i(j,{class:"company-name line_2"},{default:t((()=>[c(m(a.name),1)])),_:2},1024),i(j,{class:"industry"},{default:t((()=>[c(m(a.industry),1)])),_:2},1024),i(v,{class:"details"},{default:t((()=>[i(j,null,{default:t((()=>[c("查看详情")])),_:1}),i(k,{type:"star",size:"26"})])),_:1})])),_:2},1024)])),_:2},1024)])),_:2},1024)))),128))])),_:1})])),_:1})}],["__scopeId","data-v-dc2d33aa"]]);export{p as default};
|
@@ -1 +0,0 @@
|
||||
import{_ as a,p as s,s as e,G as t,a as l,w as r,l as c,o as d,k as i,y as f,b as o,r as u,F as n,S as _,z as p,H as b}from"./index-BoIbtAZO.js";const y=a({__name:"careerfair",setup(a){const{$api:y,navTo:m}=s("globalFunction"),g=e({dateList:[]});return t((()=>{g.dateList=function(){const a=new Date,s=[],e=["日","一","二","三","四","五","六"];for(let t=0;t<30;t++){const l=new Date(a);l.setDate(a.getDate()+t);const r=l.toISOString().slice(0,10).slice(8),c=e[l.getDay()];s.push({date:r,day:c})}return s[0].date="今天",s[1].date="明天",s}()})),(a,s)=>{const e=c,t=_;return d(),l(e,{class:"app-container"},{default:r((()=>[i(e,{class:"careerfair-AI"},{default:r((()=>[f("AI+就业服务程序")])),_:1}),i(e,{class:"careerfair-tab"},{default:r((()=>[i(e,{class:"careerfair-tab-options actived"},{default:r((()=>[f("现场招聘")])),_:1}),i(e,{class:"careerfair-tab-options"},{default:r((()=>[f("VR虚拟招聘会")])),_:1})])),_:1}),i(t,{"scroll-x":!0,"show-scrollbar":!1,class:"careerfair-scroll"},{default:r((()=>[i(e,{class:"careerfair-date"},{default:r((()=>[(d(!0),o(n,null,u(g.dateList,((a,s)=>(d(),l(e,{class:"date-list",key:s},{default:r((()=>[i(e,{class:"date-list-item"},{default:r((()=>[f(p(a.day),1)])),_:2},1024),i(e,{class:"date-list-item active"},{default:r((()=>[f(p(a.date),1)])),_:2},1024)])),_:2},1024)))),128))])),_:1})])),_:1}),i(t,{"scroll-y":!0,class:"careerfair-list-scroll"},{default:r((()=>[i(e,{class:"careerfair-list"},{default:r((()=>[(d(),o(n,null,u(10,((a,t)=>i(e,{class:"careerfair-list-card",key:t},{default:r((()=>[i(e,{class:"card-title"},{default:r((()=>[f("2024年春季青岛市商贸服务业招聘会")])),_:1}),i(e,{class:"card-intro"},{default:r((()=>[i(e,{class:"line_2"},{default:r((()=>[f("内容简介……")])),_:1}),i(e,{class:"intro-distance"},{default:r((()=>[f("500m以内")])),_:1})])),_:1}),i(e,{class:"card-address"},{default:r((()=>[f("市南区延安三路105号")])),_:1}),i(e,{class:"card-footer"},{default:r((()=>[i(e,{class:"cardfooter-lf"},{default:r((()=>[i(e,{class:"card-company"},{default:r((()=>[f("市南区就业人才中心")])),_:1}),i(e,{class:"card-date"},{default:r((()=>[f("7月31日(周三)14:00-18:00")])),_:1})])),_:1}),i(e,{class:"cardfooter-ri",onClick:s[0]||(s[0]=a=>b(m)("/packageA/pages/exhibitors/exhibitors"))},{default:r((()=>[f(" 查看详情 ")])),_:1})])),_:1})])),_:2},1024))),64))])),_:1})])),_:1})])),_:1})}}},[["__scopeId","data-v-185c4d6f"]]);export{y as default};
|
@@ -1 +0,0 @@
|
||||
import{_ as a,s,G as l,a as t,w as c,l as e,o as d,k as i,y as A,d as f,m as r,M as u,N as n}from"./index-BoIbtAZO.js";const o="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADIBAMAAABfdrOtAAAAIVBMVEUAAAD/3fH/3/P/3/P/3vLqi7run8b0tNb6yuX2vtzyr9G1anHtAAAABHRSTlMAgL9ARyeO/QAABGlJREFUeNrtnF9u00AQxtM4B3CDD+AaH8A0OUBtT2l4j2MfIIngPRUcwP1zgAoJnhEPnBJKSkaRdj37Z8Z1K74L/DTft+M43p0dWSiYTZMkBSiS5PTNSELBaQJHSk4zbkQCCp2FjIhZAhrlXJjgHDp0xlNGCp0qQrYyJIsJiDIwGTkGUgQZKGfKCVgolGQgRdQrpMgzIM+sIRFYK3dgiFPOwUlv3RaWYPipKyQXNAtVCpqFCm3MEjZsDl4qjc2SNizyheSChaBCyUKwFLoQ+VJSDkjRzRgDi2K5QlAFmYh0KhEXJCcKkS4l4oPk0oVgKfTjV+ZhDKwSdAsV+8Z+3zpGHxgj7jZVVe+AUqaATEwZ76u/Iimxh1uLaq8VECo8Yr+unlSTreLcJFfVQVT6pfND/hIhS8ovL7cwFTu/JvZu0X5d0GuLhqzt+jEA80hQDdmPbpHcWEFia7cwd0zeahGDDKQg3LKF0It44gapACwWcSQFyV0igU1l0o0oIhIeSOYQCVSWkBgjkYOUDpCFLaRwiOTKFgKZPeTyGAK0Yvvcb6whpX3u186Q1HVxrSz+2dnnjhBamWfutTlk7BxJbf52P3FtRYTQyUeublWNOSS1fASjluYfDlzWFr530cpcft9RO24IFoJqjf88TmwTQQE75LZCGTY8vrFEtmYh5P5IOvNKY8hiU5Fa7bRrOPVmoHY6iC+DXm+jUeDLoJ9mmaZNFo9JKrrQybBQDfm+fdSvFheWqRoVRPlr8mG71ye6EJMGjZWQn9snPWAhpmpVkImyECzFFrJWtLwKcrs9CH+qPEIpR/NOSGsbSbVSQSJlJIdQXgwkN4BsfCHFKP0P0ah+NZBGBQFvCP1W+TIh6z4gu1cDaVWQlBkCPfTJqg9I/WogTR+QJRC/jHKQOS9k91yQkhvSAvEGyQEBJWQsD4mZIbUaciIPCZkhjRoSsEKWmi84rJC1Znsj9YPQvVjIQnA3aM4JaTWQCSdE9ylqzAhZ9QGpdXuNASOk6QOy1O4CpnyQtfbj85yGeLWJNAS3f8d8EP3WRkBCvNokZIbUHVvMKRek6dg4m9MQj9dHDgi9uPYay0HwlETABek8ipHyQGp1JBiKPGTMA1mqc1eH8vUYcuOX+0FaSGsDIc51RsTHZ49IUJOuz+gL/1ZU7ZYfID9w78/5JQKVqv1qwdyvnS4SolMeLHaCPoI+Es3j6/7bH7WHPUbSsJWSAaHVwb67z5360hodtI1AQDlx2JJFFwJnq+ljtik/o5A7744qRc+io1vifuXEfAv72sJ+ZFYmObOBbsn7FfY+UCE/GiI/5CI/riM/eCQ/QtXTMJj8WNvzD+gxjRoOYWiSZfxzGIOsDCO5QxkuZhmTFjasGNLoOmEYfWuBsGHF0C5GcL7iYXiXVYheu4EKrClFJnfdCjKGeqkLUoZyCQ565UCJJBlIEWSgpgZ9jgznYlKijNmIQ1PRMuhkEiyDATNVIrKXd3HbXu9O/11BdzazIfwG2cbUbHV14zsAAAAASUVORK5CYII=",Q=a({__name:"msglog",setup(a){const Q=s({current:0,all:[{}]});function g(a){const s=a.detail.current;Q.current=s}function m(a){Q.current=a}return l((()=>{})),(a,s)=>{const l=e,I=r,C=u,S=n;return d(),t(l,{class:"app-container"},{default:c((()=>[i(l,{class:"msg-AI"},{default:c((()=>[A("AI+就业服务程序")])),_:1}),i(l,{class:"msg-tab"},{default:c((()=>[i(l,{class:f(["msg-tab-item",{actived:0===Q.current}]),onClick:s[0]||(s[0]=a=>m(0))},{default:c((()=>[A("全部")])),_:1},8,["class"]),i(l,{class:f(["msg-tab-item",{actived:1===Q.current}]),onClick:s[1]||(s[1]=a=>m(1))},{default:c((()=>[A("未读")])),_:1},8,["class"])])),_:1}),i(l,{class:"msg-list"},{default:c((()=>[i(S,{class:"swiper",current:Q.current,onChange:g},{default:c((()=>[i(C,{class:"list"},{default:c((()=>[i(l,{class:"list-card"},{default:c((()=>[i(l,{class:"card-img"},{default:c((()=>[i(I,{class:"card-img-flame",src:o})])),_:1}),i(l,{class:"card-info"},{default:c((()=>[i(l,{class:"info-title"},{default:c((()=>[A("今日推荐")])),_:1}),i(l,{class:"info-text"},{default:c((()=>[A("这里有9个职位很适合你,快来看看吧")])),_:1})])),_:1}),i(l,{class:"card-time"},{default:c((()=>[A("刚才")])),_:1})])),_:1})])),_:1}),i(C,{class:"list"},{default:c((()=>[i(l,{class:"list-card"},{default:c((()=>[i(l,{class:"card-img"},{default:c((()=>[i(I,{class:"card-img-flame",src:o})])),_:1}),i(l,{class:"card-info"},{default:c((()=>[i(l,{class:"info-title"},{default:c((()=>[A("今日推荐")])),_:1}),i(l,{class:"info-text"},{default:c((()=>[A("这里有9个职位很适合你,快来看看吧")])),_:1})])),_:1}),i(l,{class:"card-time"},{default:c((()=>[A("刚才")])),_:1})])),_:1})])),_:1})])),_:1},8,["current"])])),_:1})])),_:1})}}},[["__scopeId","data-v-6119d1bb"]]);export{Q as default};
|
@@ -1 +0,0 @@
|
||||
[data-v-57ea6143] .amap-logo,[data-v-57ea6143] .amap-copyright{opacity:0!important}.container[data-v-57ea6143]{display:flex;flex-direction:column;background-color:#f8f8f8}.job-header[data-v-57ea6143]{padding:.625rem 1.25rem;background-color:#fff;margin-bottom:.3125rem}.job-header .job-title[data-v-57ea6143]{font-size:1.71875rem;font-weight:700;color:#333;margin-bottom:.3125rem}.job-header .job-info[data-v-57ea6143]{display:flex;justify-content:space-between;margin-bottom:.3125rem}.job-header .job-info .salary[data-v-57ea6143]{color:#3b82f6;font-size:1.3125rem;font-weight:700}.job-header .job-info .views[data-v-57ea6143]{font-size:.75rem;color:#999}.job-header .location-info[data-v-57ea6143]{font-size:.75rem;color:#666}.job-header .location-info .location[data-v-57ea6143],.job-header .location-info .source[data-v-57ea6143],.job-header .location-info .date[data-v-57ea6143]{margin-right:.3125rem;margin-top:.625rem}.job-header .location-info .source[data-v-57ea6143]{margin-left:.9375rem}.job-details[data-v-57ea6143]{background-color:#fff;padding:.625rem 1.25rem;margin-bottom:.3125rem}.job-details .details-title[data-v-57ea6143]{font-size:1.28125rem;font-weight:700;margin-bottom:.46875rem}.job-details .tags[data-v-57ea6143]{display:flex;gap:.3125rem;margin:.46875rem 0}.job-details .tags .tag[data-v-57ea6143]{background-color:#3b82f6;color:#fff;padding:.15625rem .46875rem;border-radius:.46875rem;font-size:.6875rem}.job-details .description[data-v-57ea6143]{font-size:.75rem;line-height:1.125rem;color:#333}.company-info[data-v-57ea6143]{background-color:#fff;padding:.625rem 1.25rem;margin-bottom:9.375rem}.company-info .company-name[data-v-57ea6143]{font-size:.875rem;font-weight:700;margin-bottom:.3125rem}.company-info .company-details[data-v-57ea6143]{font-size:.75rem;color:#666}.company-info .company-map[data-v-57ea6143]{height:10.625rem;width:100%;background:#e8e8e8;margin-top:.3125rem;border-radius:.5rem;overflow:hidden}.footer[data-v-57ea6143]{position:fixed;bottom:calc(var(--status-bar-height) + var(--window-bottom));left:0;width:calc(100% - 1.25rem);padding:.625rem;background-color:#fff;text-align:center;display:flex;align-items:center}.footer .apply-btn[data-v-57ea6143]{flex:1;background-color:#22c55e;color:#fff;border-radius:.9375rem;font-size:1rem;margin-right:.9375rem}.footer .btned[data-v-57ea6143]{background-color:#666}
|
@@ -1 +0,0 @@
|
||||
.uni-load-more[data-v-7690a0fc]{display:flex;flex-direction:row;height:40px;align-items:center;justify-content:center}.uni-load-more__text[data-v-7690a0fc]{font-size:14px;margin-left:8px}.uni-load-more__img[data-v-7690a0fc]{width:24px;height:24px}.uni-load-more__img--nvue[data-v-7690a0fc]{color:#666}.uni-load-more__img--android[data-v-7690a0fc],.uni-load-more__img--ios[data-v-7690a0fc]{width:24px;height:24px;transform:rotate(0)}.uni-load-more__img--android[data-v-7690a0fc]{animation:loading-ios 1s 0s linear infinite}@keyframes loading-android-7690a0fc{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.uni-load-more__img--ios-H5[data-v-7690a0fc]{position:relative;animation:loading-ios-H5-7690a0fc 1s 0s step-end infinite}.uni-load-more__img--ios-H5 uni-image[data-v-7690a0fc]{position:absolute;width:100%;height:100%;left:0;top:0}@keyframes loading-ios-H5-7690a0fc{0%{transform:rotate(0)}8%{transform:rotate(30deg)}16%{transform:rotate(60deg)}24%{transform:rotate(90deg)}32%{transform:rotate(120deg)}40%{transform:rotate(150deg)}48%{transform:rotate(180deg)}56%{transform:rotate(210deg)}64%{transform:rotate(240deg)}73%{transform:rotate(270deg)}82%{transform:rotate(300deg)}91%{transform:rotate(330deg)}to{transform:rotate(360deg)}}.uni-load-more__img--android-H5[data-v-7690a0fc]{animation:loading-android-H5-rotate-7690a0fc 2s linear infinite;transform-origin:center center}.uni-load-more__img--android-H5 circle[data-v-7690a0fc]{display:inline-block;animation:loading-android-H5-dash-7690a0fc 1.5s ease-in-out infinite;stroke:currentColor;stroke-linecap:round}@keyframes loading-android-H5-rotate-7690a0fc{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes loading-android-H5-dash-7690a0fc{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40}to{stroke-dasharray:90,150;stroke-dashoffset:-120}}.modal-mask[data-v-56e8df2d]{position:fixed;top:0;left:0;width:100vw;height:100vh;background-color:rgba(0,0,0,.5);display:flex;justify-content:center;align-items:center;z-index:9999}.modal-container[data-v-56e8df2d]{width:100vw;height:100vh;background-color:#fff;overflow:hidden;display:flex;flex-direction:column}.modal-header[data-v-56e8df2d]{height:2.75rem;display:flex;align-items:center;justify-content:space-between;padding:0 1rem;border-bottom:.03125rem solid #eee;position:relative}.modal-header .back-btn[data-v-56e8df2d]{font-size:1.125rem;width:1.5rem}.modal-header .modal-title[data-v-56e8df2d]{font-size:1rem;font-weight:500}.content-wrapper[data-v-56e8df2d]{flex:1;display:flex;overflow:hidden}.filter-nav[data-v-56e8df2d]{width:6.25rem;background-color:#f5f5f5}.filter-nav .nav-item[data-v-56e8df2d]{height:3.125rem;padding:0 .625rem;line-height:3.125rem;font-size:.875rem;color:#666}.filter-nav .nav-item.active[data-v-56e8df2d]{background-color:#fff;color:#007aff;font-weight:700}.filter-content[data-v-56e8df2d]{flex:1;padding:.625rem}.filter-content .content-item[data-v-56e8df2d]{margin-top:1.25rem}.filter-content .content-item .item-title[data-v-56e8df2d]{width:8.78125rem;height:1.625rem;font-family:Inter,Inter;font-weight:400;font-size:1.09375rem;color:#000;line-height:1.28125rem;text-align:left;font-style:normal;text-transform:none}.filter-content .content-item[data-v-56e8df2d]:first-child{margin-top:0}.filter-content .check-content[data-v-56e8df2d]{display:grid;grid-template-columns:50% 50%;place-items:center}.filter-content .check-content .checkbox-item[data-v-56e8df2d]{display:flex;align-items:center;width:7.125rem;height:2.03125rem;margin:.625rem .625rem 0 0;text-align:center;background-color:#d9d9d9}.filter-content .check-content .checkbox-item .option-label[data-v-56e8df2d]{font-size:.875rem;width:100%}.filter-content .check-content .checkedstyle[data-v-56e8df2d]{background-color:#007aff;color:#fff}.modal-footer[data-v-56e8df2d]{height:3.125rem;display:flex;border-top:.03125rem solid #eee}.modal-footer .footer-btn[data-v-56e8df2d]{flex:1;margin:0;border-radius:0;line-height:3.125rem}.modal-footer .footer-btn[data-v-56e8df2d]:first-child{border-right:.03125rem solid #eee}
|
@@ -1 +0,0 @@
|
||||
.uni-popup-dialog[data-v-19f0223c]{width:300px;border-radius:11px;background-color:#fff}.uni-dialog-title[data-v-19f0223c]{display:flex;flex-direction:row;justify-content:center;padding-top:25px}.uni-dialog-title-text[data-v-19f0223c]{font-size:16px;font-weight:500}.uni-dialog-content[data-v-19f0223c]{display:flex;flex-direction:row;justify-content:center;align-items:center;padding:20px}.uni-dialog-content-text[data-v-19f0223c]{font-size:14px;color:#6c6c6c}.uni-dialog-button-group[data-v-19f0223c]{display:flex;flex-direction:row;border-top-color:#f5f5f5;border-top-style:solid;border-top-width:1px}.uni-dialog-button[data-v-19f0223c]{display:flex;flex:1;flex-direction:row;justify-content:center;align-items:center;height:45px}.uni-border-left[data-v-19f0223c]{border-left-color:#f0f0f0;border-left-style:solid;border-left-width:1px}.uni-dialog-button-text[data-v-19f0223c]{font-size:16px;color:#333}.uni-button-color[data-v-19f0223c]{color:#007aff}.uni-dialog-input[data-v-19f0223c]{flex:1;font-size:14px;border:1px #eee solid;height:40px;padding:0 10px;border-radius:5px;color:#555}.uni-popup__success[data-v-19f0223c]{color:#4cd964}.uni-popup__warn[data-v-19f0223c]{color:#f0ad4e}.uni-popup__error[data-v-19f0223c]{color:#dd524d}.uni-popup__info[data-v-19f0223c]{color:#909399}.uni-popup[data-v-fc99ec19]{position:fixed;z-index:99}.uni-popup.top[data-v-fc99ec19],.uni-popup.left[data-v-fc99ec19],.uni-popup.right[data-v-fc99ec19]{top:var(--window-top)}.uni-popup .uni-popup__wrapper[data-v-fc99ec19]{display:block;position:relative}.uni-popup .uni-popup__wrapper.left[data-v-fc99ec19],.uni-popup .uni-popup__wrapper.right[data-v-fc99ec19]{padding-top:var(--window-top);flex:1}.fixforpc-z-index[data-v-fc99ec19]{z-index:999}.fixforpc-top[data-v-fc99ec19]{top:0}
|
32
unpackage/dist/build/apptest/index.html
vendored
@@ -1,32 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" href="/app/assets/uni.a0977af4.css">
|
||||
|
||||
<meta charset="UTF-8" />
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
<title>青岛智慧就业服务</title>
|
||||
<!--preload-links-->
|
||||
<!--app-context-->
|
||||
<!-- <script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
|
||||
<script>
|
||||
var vConsole = new window.VConsole();
|
||||
vConsole.destroy();
|
||||
</script -->
|
||||
<script type="module" crossorigin src="/app/assets/index-BoIbtAZO.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/app/assets/index-DQAaRz8Z.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- <script src="https://unpkg.com/vconsole/dist/vconsole.min.js"></script>
|
||||
<script>
|
||||
var vConsole = new window.VConsole();
|
||||
</script> -->
|
||||
<div id="app"><!--app-html--></div>
|
||||
|
||||
</body>
|
BIN
unpackage/dist/build/apptest/static/.DS_Store
vendored
BIN
unpackage/dist/build/apptest/static/icon/.DS_Store
vendored
Before Width: | Height: | Size: 700 B |
BIN
unpackage/dist/build/apptest/static/icon/Group1.png
vendored
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 328 B |