Files

634 lines
22 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script>
/**
* 工单列表:状态/类型/关键词分页查询;筛选字典和统计独立请求,部分失败不会把已成功的选项全部丢弃。
*/
import "~/assets/styles/tickets.Dz8JrDhQ.css";
import { toDisplayString } from "vue";
import { onMounted } from "vue";
import { createBlock } from "vue";
import { ref } from "vue";
import { withCtx } from "vue";
import { createCommentVNode } from "vue";
import { computed } from "vue";
import { isRef } from "vue";
import { createElementBlock } from "vue";
import { createElementVNode } from "vue";
import { createTextVNode } from "vue";
import { unref } from "vue";
import { defineComponent } from "vue";
import { createVNode } from "vue";
import { openBlock } from "vue";
import { normalizeStyle } from "vue";
import { withKeys } from "vue";
import { useRoute } from "#app";
import { NuxtLink } from "#components";
import { useApi } from "~/lib/auth.js";
import button from "primevue/button";
import { t as _plugin_vue_export_helper_t } from "~/lib/_plugin-vue_export-helper.js";
import message from "primevue/message";
import inputtext from "primevue/inputtext";
import { r as dict_r } from "~/lib/dict.js";
import datatable from "primevue/datatable";
import paginator from "primevue/paginator";
import select from "primevue/select";
import column from "primevue/column";
import ListEmpty from "~/components/ListEmpty.vue";
import { t as useListPage_t } from "~/lib/useListPage.js";
var ie = {
class: `list-page`,
},
D = {
class: `list-head`,
},
O = {
class: `list-head-actions`,
},
ae = {
class: `list-toolbar`,
},
oe = {
class: `list-toolbar-right`,
},
k = {
class: `list-table`,
},
A = {
key: 3,
class: `list-foot`,
},
j = _plugin_vue_export_helper_t(
defineComponent({
__name: `index`,
setup(f) {
let v = useApi(),
j = useRoute(),
M = ref([]),
N = ref([]),
P = ref({}),
F = ref(``),
I = ref(!1),
L = ref(``),
R = ref(!1),
z = ref(``),
B = ref(``),
V = Number(j.query.status),
H = ref(V > 0 ? V : null),
U = ref(null),
{
list: W,
total: G,
loading: K,
error: q,
page: J,
limit: Y,
onPage: se,
reload: X,
} = useListPage_t(`/ticket`, {
limit: 10,
params: () => ({
keywords: B.value,
status: H.value ? [H.value] : [],
ticket_type_id: U.value ?? ``,
}),
});
// 状态和类型使用 allSettled 分别处理,失败项单独汇总提示。
async function Z() {
if (!I.value) {
((I.value = !0), (F.value = ``));
try {
let [e, t] = await Promise.allSettled([
v.get(`/ticket/status`),
v.get(`/ticket/type`),
]);
(e.status === `fulfilled` && (M.value = e.value.list ?? []),
t.status === `fulfilled` && (N.value = t.value.list ?? []));
let n = [e, t].flatMap((e, t) =>
e.status === `rejected`
? [
`${t === 0 ? `工单状态` : `工单类型`}加载失败:${e.reason instanceof Error ? e.reason.message : `请稍后重试`}`,
]
: [],
);
F.value = n.join(`;`);
} finally {
I.value = !1;
}
}
}
// 工单统计独立加载,异常不清空工单主列表。
async function Q() {
if (!R.value) {
((R.value = !0), (L.value = ``));
try {
P.value = await v.get(`/ticket/statistic`);
} catch (e) {
L.value = e instanceof Error ? e.message : `工单统计加载失败`;
} finally {
R.value = !1;
}
}
}
computed(() =>
M.value
.filter((e) => P.value[e.id] !== void 0)
.map((e) => ({
...e,
count: P.value[e.id] ?? 0,
})),
);
let ce = computed(() => [
{
label: `全部状态`,
value: null,
},
...M.value.map((e) => ({
label: e.name,
value: e.id,
})),
]),
le = computed(() => [
{
label: `全部类型`,
value: null,
},
...N.value.map((e) => ({
label: e.name,
value: e.id,
})),
]),
$ = computed(() => !!B.value || !!H.value || !!U.value);
// 确认搜索后应用关键词并交由公共分页工具重载。
function ue() {
((B.value = z.value.trim()), X());
}
// 清除关键词、状态与工单类型,恢复全部工单。
function de() {
((z.value = ``),
(B.value = ``),
(H.value = null),
(U.value = null),
X());
}
return (
onMounted(() => {
(Z(), Q());
}),
// 筛选字典、统计提示与工单主列表分开展示,失败选项提供重试,不用空列表掩盖请求错误。
(t, r) => {
let o = message,
f = button,
g = NuxtLink,
_ = inputtext,
v = select,
E = ListEmpty,
j = column,
M = datatable,
N = paginator;
return (
openBlock(),
createElementBlock(`div`, ie, [
createVNode(
o,
{
severity: `info`,
closable: !1,
class: `support-notice`,
},
{
default: withCtx(() => [
...(r[3] ||= [
createElementVNode(
`div`,
null,
[
createTextVNode(
`尊敬的客户您好:为了更好地为您服务,请详细描述您遇到的问题,并提供相关截图或报错信息。`,
),
createElementVNode(`br`),
createTextVNode(
`请勿在工单中发送账户密码等敏感信息。我们会尽快为您处理。`,
),
],
-1,
),
]),
]),
_: 1,
},
),
createElementVNode(`div`, D, [
(r[4] ||= createElementVNode(`h2`, null, `工单`, -1)),
createElementVNode(`div`, O, [
createVNode(
g,
{
to: `/tickets/create`,
},
{
default: withCtx(() => [
createVNode(f, {
as: `span`,
label: `创建工单`,
icon: `pi pi-plus`,
}),
]),
_: 1,
},
),
]),
]),
unref(L)
? (openBlock(),
createBlock(
o,
{
key: 0,
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(
` 工单统计暂不可用:` +
toDisplayString(unref(L)) +
` `,
1,
),
createVNode(
f,
{
label: `重试统计`,
size: `small`,
severity: `secondary`,
text: ``,
loading: unref(R),
onClick: Q,
},
null,
8,
[`loading`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(F)
? (openBlock(),
createBlock(
o,
{
key: 1,
severity: `warn`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(F)) + ` `, 1),
createVNode(
f,
{
label: `重试筛选选项`,
size: `small`,
severity: `secondary`,
text: ``,
loading: unref(I),
onClick: Z,
},
null,
8,
[`loading`],
),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
createElementVNode(`div`, ae, [
createElementVNode(`div`, oe, [
createVNode(
_,
{
modelValue: unref(z),
"onUpdate:modelValue": (r[0] ||= (e) =>
isRef(z) ? (z.value = e) : null),
class: `list-search`,
placeholder: `输入关键字`,
onKeyup: withKeys(ue, [`enter`]),
},
null,
8,
[`modelValue`],
),
createVNode(
v,
{
modelValue: unref(U),
"onUpdate:modelValue": (r[1] ||= (e) =>
isRef(U) ? (U.value = e) : null),
class: `list-select`,
options: unref(le),
optionLabel: `label`,
optionValue: `value`,
onChange: unref(X),
},
null,
8,
[`modelValue`, `options`, `onChange`],
),
createVNode(
v,
{
modelValue: unref(H),
"onUpdate:modelValue": (r[2] ||= (e) =>
isRef(H) ? (H.value = e) : null),
class: `list-select`,
options: unref(ce),
optionLabel: `label`,
optionValue: `value`,
onChange: unref(X),
},
null,
8,
[`modelValue`, `options`, `onChange`],
),
createVNode(f, {
label: `清除筛选`,
icon: `pi pi-filter-slash`,
severity: `secondary`,
text: ``,
size: `small`,
onClick: de,
}),
]),
]),
createElementVNode(`div`, k, [
createVNode(
M,
{
value: unref(W),
loading: unref(K),
lazy: ``,
rows: unref(Y),
totalRecords: unref(G),
first: (unref(J) - 1) * unref(Y),
dataKey: `id`,
},
{
empty: withCtx(() => [
createVNode(
E,
{
icon: `pi pi-comments`,
title: unref(K) ? `加载中…` : `还没有工单`,
description: unref($)
? `换个筛选条件试试`
: `遇到问题可以提交工单联系我们`,
},
{
default: withCtx(() => [
unref($)
? createCommentVNode(``, !0)
: (openBlock(),
createBlock(
g,
{
key: 0,
to: `/tickets/create`,
},
{
default: withCtx(() => [
createVNode(f, {
as: `span`,
label: `创建工单`,
icon: `pi pi-plus`,
size: `small`,
}),
]),
_: 1,
},
)),
]),
_: 1,
},
8,
[`title`, `description`],
),
]),
default: withCtx(() => [
createVNode(
j,
{
header: `ID`,
style: {
width: `120px`,
},
},
{
body: withCtx(({ data: t }) => [
createVNode(
g,
{
to: `/tickets/${t.id}`,
class: `col-id`,
},
{
default: withCtx(() => [
createTextVNode(
`#` + toDisplayString(t.ticket_num),
1,
),
]),
_: 2,
},
1032,
[`to`],
),
]),
_: 1,
},
),
createVNode(
j,
{
header: `标题`,
style: {
"min-width": `220px`,
},
},
{
body: withCtx(({ data: t }) => [
createVNode(
g,
{
to: `/tickets/${t.id}`,
class: `title-link`,
},
{
default: withCtx(() => [
createTextVNode(
toDisplayString(t.title),
1,
),
]),
_: 2,
},
1032,
[`to`],
),
]),
_: 1,
},
),
createVNode(
j,
{
header: `工单类型`,
style: {
width: `130px`,
},
},
{
body: withCtx(({ data: t }) => [
createTextVNode(
toDisplayString(t.name || `—`),
1,
),
]),
_: 1,
},
),
createVNode(
j,
{
header: `提交时间`,
style: {
"min-width": `160px`,
},
},
{
body: withCtx(({ data: n }) => [
createTextVNode(
toDisplayString(
(`formatTime` in t
? t.formatTime
: unref(dict_r))(n.post_time),
),
1,
),
]),
_: 1,
},
),
createVNode(
j,
{
header: `最近回复`,
style: {
"min-width": `160px`,
},
},
{
body: withCtx(({ data: n }) => [
createTextVNode(
toDisplayString(
n.last_reply_time
? (`formatTime` in t
? t.formatTime
: unref(dict_r))(n.last_reply_time)
: `—`,
),
1,
),
]),
_: 1,
},
),
createVNode(
j,
{
header: `状态`,
style: {
width: `110px`,
},
},
{
body: withCtx(({ data: t }) => [
createElementVNode(
`span`,
{
class: `status-tag`,
style: normalizeStyle({
color: `var(--p-text-color)`,
borderColor: t.color,
}),
},
toDisplayString(t.status),
5,
),
]),
_: 1,
},
),
]),
_: 1,
},
8,
[`value`, `loading`, `rows`, `totalRecords`, `first`],
),
]),
unref(q)
? (openBlock(),
createBlock(
o,
{
key: 2,
severity: `error`,
closable: !1,
},
{
default: withCtx(() => [
createTextVNode(toDisplayString(unref(q)), 1),
]),
_: 1,
},
))
: createCommentVNode(``, !0),
unref(G) > 0
? (openBlock(),
createElementBlock(`div`, A, [
(r[5] ||= createElementVNode(
`div`,
{
class: `list-bulk`,
},
null,
-1,
)),
createVNode(
N,
{
rows: unref(Y),
totalRecords: unref(G),
first: (unref(J) - 1) * unref(Y),
rowsPerPageOptions: [10, 20, 50],
onPage: unref(se),
},
null,
8,
[`rows`, `totalRecords`, `first`, `onPage`],
),
]))
: createCommentVNode(``, !0),
])
);
}
);
},
}),
[[`__scopeId`, `data-v-1ff3e04d`]],
);
export {};
export default j;
</script>