fix(mobile): show real assignments on today page
This commit is contained in:
@@ -47,7 +47,7 @@ mobile-uni/
|
|||||||
- `App.vue` 只放应用级生命周期和全局样式,不承载业务页面。
|
- `App.vue` 只放应用级生命周期和全局样式,不承载业务页面。
|
||||||
- 页面跳转使用 uni-app 页面栈和 tabBar,不手写锚点切换。
|
- 页面跳转使用 uni-app 页面栈和 tabBar,不手写锚点切换。
|
||||||
- 认证令牌沿用当前 H5 的 `aihr_mobile_access_token` 和 `aihr_mobile_client_id`。
|
- 认证令牌沿用当前 H5 的 `aihr_mobile_access_token` 和 `aihr_mobile_client_id`。
|
||||||
- 开发代理沿用 `/dev-api -> http://127.0.0.1:8080`。
|
- 开发代理沿用 `/dev-api -> https://wygj-api.localhost`,显式 `VITE_PROXY_TARGET` 时可覆盖。
|
||||||
|
|
||||||
## 3. 三端页面计划
|
## 3. 三端页面计划
|
||||||
|
|
||||||
@@ -222,6 +222,8 @@ mobile-uni/
|
|||||||
- 员工端每日三题提交/回读已用真实 API 跑通: 新手机号首次加载生成 3 条 daily 任务,提交一题后状态变 `已完成`,回读到用户答案、反馈和参考答案;未提交前参考答案为空。
|
- 员工端每日三题提交/回读已用真实 API 跑通: 新手机号首次加载生成 3 条 daily 任务,提交一题后状态变 `已完成`,回读到用户答案、反馈和参考答案;未提交前参考答案为空。
|
||||||
- 主管复盘-派专项-员工回读闭环已用真实 API 跑通: 员工完成一场对练生成 `待复盘`,主管读取复盘详情可见对话和标注,标记已复盘并带 `nextScenarioId` 后该记录不再出现在待复盘列表,员工专项列表立即回读复盘后手工专项。
|
- 主管复盘-派专项-员工回读闭环已用真实 API 跑通: 员工完成一场对练生成 `待复盘`,主管读取复盘详情可见对话和标注,标记已复盘并带 `nextScenarioId` 后该记录不再出现在待复盘列表,员工专项列表立即回读复盘后手工专项。
|
||||||
- PC 成长激励和组织权限页已收口真实数据边界: 派专项必须输入真实员工手机号或 extPartyId,不再写入 `mobile-user`;无项目范围接口时只显示空态,不再展示假项目样例。
|
- PC 成长激励和组织权限页已收口真实数据边界: 派专项必须输入真实员工手机号或 extPartyId,不再写入 `mobile-user`;无项目范围接口时只显示空态,不再展示假项目样例。
|
||||||
|
- `mobile-uni` 本地 dev 代理已对齐 portless:默认 `/dev-api -> https://wygj-api.localhost`,不再依赖裸 `8080`;真实浏览器登录链路已复跑通过。
|
||||||
|
- 员工今日页“今日安排”已优先回读真实 `/api/aihr/mobile/practice/assignments`;有待训练专项或每日三题时覆盖公开 home seed,真实浏览器已验证 `13900000998` 首页显示当天 daily 任务并可跳到练习页。
|
||||||
|
|
||||||
## 7. 风险
|
## 7. 风险
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@
|
|||||||
portless
|
portless
|
||||||
```
|
```
|
||||||
|
|
||||||
portless 会按根目录 `portless.json` 执行 `frontend` 和 `mobile-uni` 的 `npm run dev`。后端由 `./scripts/dev.sh` 默认通过 `portless run --name wygj-api ./scripts/dev-backend.sh` 启动;管理端 Vite 代理读取 `frontend/.env.development` 的 `VITE_APP_PROXY_TARGET=https://wygj-api.localhost`,不依赖固定 `8080`。如需单独启动后端,可执行:
|
portless 会按根目录 `portless.json` 执行 `frontend` 和 `mobile-uni` 的 `npm run dev`。后端由 `./scripts/dev.sh` 默认通过 `portless run --name wygj-api ./scripts/dev-backend.sh` 启动;管理端 Vite 代理读取 `frontend/.env.development` 的 `VITE_APP_PROXY_TARGET=https://wygj-api.localhost`,`mobile-uni` Vite 代理默认指向 `https://wygj-api.localhost`,都不依赖固定 `8080`。如需单独启动后端,可执行:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
portless run --name wygj-api ./scripts/dev-backend.sh
|
portless run --name wygj-api ./scripts/dev-backend.sh
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
<button class="primary-button login-button" @click="goLogin">去登录</button>
|
<button class="primary-button login-button" @click="goLogin">去登录</button>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="section-card" v-else-if="home?.primary">
|
<view class="section-card" v-else-if="hasSchedule">
|
||||||
<view class="section-head">
|
<view class="section-head">
|
||||||
<view class="section-title">
|
<view class="section-title">
|
||||||
<text class="section-icon">日</text>
|
<text class="section-icon">日</text>
|
||||||
@@ -53,18 +53,18 @@
|
|||||||
<view class="schedule-row">
|
<view class="schedule-row">
|
||||||
<text class="step-dot blue">1</text>
|
<text class="step-dot blue">1</text>
|
||||||
<view class="schedule-copy">
|
<view class="schedule-copy">
|
||||||
<text class="schedule-title">每日小训:{{ home.primary.title.replace('三角色对练', '') }}</text>
|
<text class="schedule-title">{{ primaryScheduleTitle }}</text>
|
||||||
<text class="schedule-desc">{{ home.primary.desc }}</text>
|
<text class="schedule-desc">{{ primaryScheduleDesc }}</text>
|
||||||
</view>
|
</view>
|
||||||
<button class="schedule-action blue-action" @click="openTool(home.primary.cta)">开始</button>
|
<button class="schedule-action blue-action" @click="openPrimarySchedule">开始</button>
|
||||||
</view>
|
</view>
|
||||||
<view class="schedule-row" v-if="home.review">
|
<view class="schedule-row" v-if="home?.review">
|
||||||
<text class="step-dot orange">2</text>
|
<text class="step-dot orange">2</text>
|
||||||
<view class="schedule-copy">
|
<view class="schedule-copy">
|
||||||
<text class="schedule-title">今日复习:{{ home.review.title }}</text>
|
<text class="schedule-title">今日复习:{{ home?.review?.title }}</text>
|
||||||
<text class="schedule-desc">{{ home.review.desc }}</text>
|
<text class="schedule-desc">{{ home?.review?.desc }}</text>
|
||||||
</view>
|
</view>
|
||||||
<button class="schedule-action orange-action" @click="ask(home.review.title)">去复习</button>
|
<button class="schedule-action orange-action" @click="ask(home?.review?.title || '岗前SOP复习')">去复习</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -106,11 +106,13 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { onShow } from '@dcloudio/uni-app';
|
import { onShow } from '@dcloudio/uni-app';
|
||||||
import type { RoleHome } from '@/types/api';
|
import type { PracticeAssignment, RoleHome } from '@/types/api';
|
||||||
import { getMobileHome } from '@/services/home';
|
import { getMobileHome } from '@/services/home';
|
||||||
|
import { getPracticeAssignments } from '@/services/practice';
|
||||||
import { getAuth, isLoggedIn, rememberLoginRedirect } from '@/services/auth';
|
import { getAuth, isLoggedIn, rememberLoginRedirect } from '@/services/auth';
|
||||||
|
|
||||||
const home = ref<RoleHome | null>(null);
|
const home = ref<RoleHome | null>(null);
|
||||||
|
const assignments = ref<PracticeAssignment[]>([]);
|
||||||
const message = ref('');
|
const message = ref('');
|
||||||
const loggedIn = ref(false);
|
const loggedIn = ref(false);
|
||||||
const quickQuestions = ['催费话术', '投诉应对', '收费标准'];
|
const quickQuestions = ['催费话术', '投诉应对', '收费标准'];
|
||||||
@@ -140,6 +142,26 @@ const mapTiles = computed(() => {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const primaryAssignment = computed(() =>
|
||||||
|
assignments.value.find((item) => item.status === '待训练' && item.source !== 'daily')
|
||||||
|
|| assignments.value.find((item) => item.status === '待训练')
|
||||||
|
|| null
|
||||||
|
);
|
||||||
|
const hasSchedule = computed(() => Boolean(primaryAssignment.value || home.value?.primary || home.value?.review));
|
||||||
|
const primaryScheduleTitle = computed(() => {
|
||||||
|
const item = primaryAssignment.value;
|
||||||
|
if (item) {
|
||||||
|
return item.source === 'daily'
|
||||||
|
? `每日三题:${item.question || item.scenarioName}`
|
||||||
|
: `专项训练:${item.scenarioName || item.question}`;
|
||||||
|
}
|
||||||
|
return `每日小训:${home.value?.primary?.title.replace('三角色对练', '') || '场景练习'}`;
|
||||||
|
});
|
||||||
|
const primaryScheduleDesc = computed(() => {
|
||||||
|
const item = primaryAssignment.value;
|
||||||
|
if (item) return item.source === 'daily' ? '提交后显示反馈与参考答案' : (item.reason || '主管指派专项训练');
|
||||||
|
return home.value?.primary?.desc || '进入练习页查看今日任务';
|
||||||
|
});
|
||||||
const mentorName = computed(() => {
|
const mentorName = computed(() => {
|
||||||
if (!loggedIn.value) return '同事';
|
if (!loggedIn.value) return '同事';
|
||||||
const phone = getAuth().phone.trim();
|
const phone = getAuth().phone.trim();
|
||||||
@@ -153,15 +175,31 @@ const mentorBubbleText = computed(() =>
|
|||||||
const loadHome = async () => {
|
const loadHome = async () => {
|
||||||
loggedIn.value = isLoggedIn();
|
loggedIn.value = isLoggedIn();
|
||||||
message.value = '';
|
message.value = '';
|
||||||
|
assignments.value = [];
|
||||||
if (!loggedIn.value) {
|
if (!loggedIn.value) {
|
||||||
home.value = null;
|
home.value = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
const [homeResult, assignmentResult] = await Promise.allSettled([
|
||||||
home.value = await getMobileHome('user');
|
getMobileHome('user'),
|
||||||
} catch (error) {
|
getPracticeAssignments(true)
|
||||||
|
]);
|
||||||
|
if (homeResult.status === 'fulfilled') {
|
||||||
|
home.value = homeResult.value;
|
||||||
|
} else {
|
||||||
home.value = null;
|
home.value = null;
|
||||||
message.value = error instanceof Error ? error.message : '首页数据加载失败';
|
message.value = homeResult.reason instanceof Error ? homeResult.reason.message : '首页数据加载失败';
|
||||||
|
}
|
||||||
|
if (assignmentResult.status === 'fulfilled') {
|
||||||
|
assignments.value = assignmentResult.value;
|
||||||
|
} else {
|
||||||
|
loggedIn.value = isLoggedIn();
|
||||||
|
if (!loggedIn.value) {
|
||||||
|
home.value = null;
|
||||||
|
message.value = '登录已过期,请重新登录';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
message.value = assignmentResult.reason instanceof Error ? assignmentResult.reason.message : '今日任务加载失败';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -179,6 +217,10 @@ const goLogin = () => {
|
|||||||
uni.navigateTo({ url: '/pages/auth/login/index' });
|
uni.navigateTo({ url: '/pages/auth/login/index' });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openPrimarySchedule = () => {
|
||||||
|
uni.switchTab({ url: '/pages/user/practice/index' });
|
||||||
|
};
|
||||||
|
|
||||||
const openTool = (title: string) => {
|
const openTool = (title: string) => {
|
||||||
if (title.includes('问') || title.includes('SOP') || title.includes('sop')) {
|
if (title.includes('问') || title.includes('SOP') || title.includes('sop')) {
|
||||||
goSop();
|
goSop();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import uniPlugin from '@dcloudio/vite-plugin-uni';
|
|||||||
const uni = typeof uniPlugin === 'function' ? uniPlugin : uniPlugin.default;
|
const uni = typeof uniPlugin === 'function' ? uniPlugin : uniPlugin.default;
|
||||||
const devPort = Number(process.env.PORT) || 5175;
|
const devPort = Number(process.env.PORT) || 5175;
|
||||||
const devHost = process.env.HOST || '0.0.0.0';
|
const devHost = process.env.HOST || '0.0.0.0';
|
||||||
|
const proxyTarget = process.env.VITE_PROXY_TARGET || 'https://wygj-api.localhost';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [uni()],
|
plugins: [uni()],
|
||||||
@@ -13,8 +14,9 @@ export default defineConfig({
|
|||||||
strictPort: true,
|
strictPort: true,
|
||||||
proxy: {
|
proxy: {
|
||||||
'/dev-api': {
|
'/dev-api': {
|
||||||
target: 'http://127.0.0.1:8080',
|
target: proxyTarget,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
|
secure: false,
|
||||||
rewrite: (path) => path.replace(/^\/dev-api/, '')
|
rewrite: (path) => path.replace(/^\/dev-api/, '')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user