fix(mobile): recover direct channels after network failure
This commit is contained in:
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "aihr-mobile-uni",
|
||||
"version": "0.1.8",
|
||||
"version": "0.1.10",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "aihr-mobile-uni",
|
||||
"version": "0.1.8",
|
||||
"version": "0.1.10",
|
||||
"dependencies": {
|
||||
"@dcloudio/uni-app": "3.0.0-alpha-5020220260725001",
|
||||
"@dcloudio/uni-app-plus": "3.0.0-alpha-5020220260725001",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package",
|
||||
"name": "aihr-mobile-uni",
|
||||
"version": "0.1.9",
|
||||
"version": "0.1.10",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"appid" : "__UNI__B36D8BE",
|
||||
"description" : "帮道员工端",
|
||||
"vueVersion" : "3",
|
||||
"versionName" : "0.1.9",
|
||||
"versionCode" : "109",
|
||||
"versionName" : "0.1.10",
|
||||
"versionCode" : "110",
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
|
||||
@@ -25,7 +25,16 @@
|
||||
<text class="section-note">每次只提交给一个处理部门。</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="channel-grid" role="radiogroup" aria-label="直达对象">
|
||||
<view v-if="channelsLoading" class="channel-state" role="status" aria-live="polite">
|
||||
<text>直达对象加载中…</text>
|
||||
</view>
|
||||
<view v-else-if="channelsFailed" class="channel-state error" role="alert">
|
||||
<text>直达对象加载失败,请检查网络后重试。</text>
|
||||
<button class="secondary-button channel-retry" :disabled="channelsLoading" @click="loadChannels">
|
||||
重新加载直达对象
|
||||
</button>
|
||||
</view>
|
||||
<view v-else class="channel-grid" role="radiogroup" aria-label="直达对象">
|
||||
<button
|
||||
v-for="channel in channels"
|
||||
:key="channel.code"
|
||||
@@ -173,6 +182,8 @@ const path = '/pages/user/direct/index';
|
||||
const pageSize = 20;
|
||||
const loggedIn = ref(false);
|
||||
const channels = ref<DirectChannel[]>([]);
|
||||
const channelsLoading = ref(false);
|
||||
const channelsFailed = ref(false);
|
||||
const items = ref<DirectFeedback[]>([]);
|
||||
const total = ref(0);
|
||||
const pageNum = ref(1);
|
||||
@@ -204,7 +215,12 @@ let voiceTimer: ReturnType<typeof setInterval> | null = null;
|
||||
let voiceStartedAt = 0;
|
||||
|
||||
const hasMore = computed(() => items.value.length < total.value);
|
||||
const canSubmit = computed(() => Boolean(form.channelCode) && Boolean(form.content.trim()));
|
||||
const canSubmit = computed(() =>
|
||||
!channelsLoading.value
|
||||
&& !channelsFailed.value
|
||||
&& Boolean(form.channelCode)
|
||||
&& Boolean(form.content.trim())
|
||||
);
|
||||
const voiceBusy = computed(() => voiceStarting.value || voiceRecording.value || voiceStopping.value || voiceTranscribing.value);
|
||||
const voiceChipLabel = computed(() => {
|
||||
if (voiceStopping.value) return '结束中…';
|
||||
@@ -378,8 +394,28 @@ const changeAnonymous = (event: Event | { detail?: { value?: boolean } }) => {
|
||||
};
|
||||
|
||||
const loadChannels = async () => {
|
||||
channels.value = await listDirectChannels();
|
||||
if (!form.channelCode && channels.value.length) chooseChannel(channels.value[0]);
|
||||
if (channelsLoading.value) return;
|
||||
channelsLoading.value = true;
|
||||
channelsFailed.value = false;
|
||||
try {
|
||||
const rows = await listDirectChannels();
|
||||
if (!rows.length) {
|
||||
channels.value = [];
|
||||
form.channelCode = '';
|
||||
channelsFailed.value = true;
|
||||
return;
|
||||
}
|
||||
channels.value = rows;
|
||||
if (!form.channelCode || !rows.some((channel) => channel.code === form.channelCode)) {
|
||||
chooseChannel(rows[0]);
|
||||
}
|
||||
} catch {
|
||||
channels.value = [];
|
||||
form.channelCode = '';
|
||||
channelsFailed.value = true;
|
||||
} finally {
|
||||
channelsLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const loadMine = async (reset: boolean) => {
|
||||
@@ -463,6 +499,7 @@ onUnload(() => {
|
||||
.section-head,.history-head,.feedback-head,.form-foot,.anonymous-control{display:flex;align-items:center;justify-content:space-between;gap:12px}
|
||||
.section-title{display:block;color:var(--ink);font-size:18px;font-weight:900}.section-note,.muted{display:block;margin-top:4px;color:var(--muted);font-size:12px;line-height:1.6}
|
||||
.channel-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.channel-button{display:grid;min-height:60px;align-content:center;justify-items:center;gap:3px;padding:10px;border:1px solid #e6e8ec;border-radius:14px;background:#fff;color:var(--ink);font-size:14px;font-weight:900;text-align:center;transition:border-color .2s ease,box-shadow .2s ease,transform .1s ease}.channel-button.active{border-color:var(--brand);background:#fff5f6;color:var(--brand);box-shadow:0 6px 16px rgba(230,0,18,.10)}.channel-button:active{transform:scale(.98)}.channel-button::after,.refresh-button::after{border:0}.channel-hint{font-size:11px;font-weight:700;opacity:.72}
|
||||
.channel-state{display:grid;justify-items:start;gap:10px;padding:14px;border-radius:12px;background:#f7f8fa;color:var(--muted);font-size:13px;line-height:1.5}.channel-state.error{background:#fff0f1;color:#a9000d}.channel-retry{min-width:150px;margin:0}
|
||||
.channel-icon{display:grid;width:34px;height:34px;place-items:center;border-radius:12px;background:#f4f5f7;transition:background .2s ease}
|
||||
.channel-button.active .channel-icon{background:var(--employee-primary-soft)}
|
||||
.channel-name{line-height:1.3}
|
||||
|
||||
@@ -36,6 +36,19 @@ test('App 平台编译器已声明且与其他 uni 包同版本,避免 build:a
|
||||
assert.equal(appPlus, pkg.devDependencies['@dcloudio/vite-plugin-uni']);
|
||||
});
|
||||
|
||||
test('App 版本在 package、lockfile 与原生 manifest 间保持一致', async () => {
|
||||
const [pkg, lockfile, manifest] = await Promise.all([
|
||||
readJson('../package.json'),
|
||||
readJson('../package-lock.json'),
|
||||
readJson('../src/manifest.json')
|
||||
]);
|
||||
|
||||
assert.equal(lockfile.version, pkg.version);
|
||||
assert.equal(lockfile.packages?.['']?.version, pkg.version);
|
||||
assert.equal(manifest.versionName, pkg.version);
|
||||
assert.match(String(manifest.versionCode || ''), /^\d+$/);
|
||||
});
|
||||
|
||||
test('Android 自定义基座显式面向 Android 15 权限模型', async () => {
|
||||
const manifest = await readJson('../src/manifest.json');
|
||||
const android = manifest['app-plus']?.distribute?.android;
|
||||
|
||||
@@ -19,6 +19,13 @@ test('员工端直通车包含固定五通道、业务匿名和本人回复闭
|
||||
assert.match(page, /匿名提交/);
|
||||
assert.match(page, /正式回复/);
|
||||
assert.match(page, /requestId/);
|
||||
assert.match(page, /v-else-if="channelsFailed"/);
|
||||
assert.match(page, /重新加载直达对象/);
|
||||
assert.match(page, /@click="loadChannels"/);
|
||||
assert.match(page, /const channelsLoading = ref\(false\)/);
|
||||
assert.match(page, /const channelsFailed = ref\(false\)/);
|
||||
assert.match(page, /const loadChannels = async \(\) => \{[\s\S]*if \(channelsLoading\.value\) return;[\s\S]*channelsFailed\.value = false;[\s\S]*await listDirectChannels\(\)[\s\S]*catch \{[\s\S]*form\.channelCode = '';[\s\S]*channelsFailed\.value = true;[\s\S]*finally \{[\s\S]*channelsLoading\.value = false;/);
|
||||
assert.match(page, /const canSubmit = computed\(\(\) =>[\s\S]*!channelsLoading\.value[\s\S]*!channelsFailed\.value/);
|
||||
assert.match(broadcast, /openDirect/);
|
||||
assert.ok(pages.includes('pages/user/direct/index'));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user