first commit
This commit is contained in:
commit
db5762abd4
687 files changed
+171307
No files matched your search
@@ -0,0 +1,778 @@
|
||||
<script>
|
||||
import "~/assets/styles/TicketAttachments.DtbJGLkE.css";
|
||||
import "~/assets/styles/RichTextEditor.NkmgPT5m.css";
|
||||
import "~/assets/styles/_id_.C-0--Lx-.css";
|
||||
definePageMeta({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
import { toDisplayString } from "vue";
|
||||
import { renderList } from "vue";
|
||||
import { onMounted } from "vue";
|
||||
import { normalizeClass } 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 { Fragment } 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 { 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 { r as dict_r } from "~/lib/dict.js";
|
||||
import skeleton from "primevue/skeleton";
|
||||
import { n as sanitize_n } from "~/lib/sanitize.js";
|
||||
import RichTextEditor from "~/components/RichTextEditor.vue";
|
||||
import { n as ticketAttachments_n } from "~/lib/ticketAttachments.js";
|
||||
import TicketAttachments from "~/components/TicketAttachments.vue";
|
||||
import TicketNotice from "~/components/TicketNotice.vue";
|
||||
import { t as composables_t } from "~/lib/composables-2.js";
|
||||
var le = {
|
||||
class: `page`,
|
||||
},
|
||||
ue = {
|
||||
class: `page-head`,
|
||||
},
|
||||
de = {
|
||||
key: 0,
|
||||
class: `panel`,
|
||||
},
|
||||
fe = {
|
||||
class: `panel head-panel`,
|
||||
},
|
||||
pe = {
|
||||
class: `ticket-head`,
|
||||
},
|
||||
me = {
|
||||
class: `ticket-title`,
|
||||
},
|
||||
he = {
|
||||
class: `ticket-num`,
|
||||
},
|
||||
ge = {
|
||||
class: `ticket-meta`,
|
||||
},
|
||||
w = {
|
||||
class: `panel thread-panel`,
|
||||
},
|
||||
T = {
|
||||
class: `thread`,
|
||||
},
|
||||
E = {
|
||||
class: `message-head`,
|
||||
},
|
||||
D = {
|
||||
class: `sender`,
|
||||
},
|
||||
O = {
|
||||
key: 0,
|
||||
class: `badge`,
|
||||
},
|
||||
k = {
|
||||
class: `time`,
|
||||
},
|
||||
A = [`innerHTML`],
|
||||
j = {
|
||||
key: 0,
|
||||
class: `message-quote`,
|
||||
},
|
||||
M = [`innerHTML`],
|
||||
N = {
|
||||
class: `reply-box`,
|
||||
},
|
||||
P = {
|
||||
key: 0,
|
||||
class: `reply-quote`,
|
||||
role: `status`,
|
||||
},
|
||||
F = [`innerHTML`],
|
||||
I = {
|
||||
class: `reply-attachments`,
|
||||
},
|
||||
L = {
|
||||
class: `reply-upload`,
|
||||
for: `reply-files`,
|
||||
},
|
||||
_e = [`disabled`],
|
||||
R = {
|
||||
key: 0,
|
||||
class: `muted`,
|
||||
},
|
||||
ve = {
|
||||
key: 1,
|
||||
class: `reply-file-list`,
|
||||
},
|
||||
ye = {
|
||||
class: `reply-actions`,
|
||||
},
|
||||
be = {
|
||||
class: `buttons`,
|
||||
},
|
||||
z = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `[id]`,
|
||||
setup(m) {
|
||||
let y = useRoute(),
|
||||
z = useApi(),
|
||||
B = String(y.params.id ?? y.query.id ?? ``);
|
||||
composables_t({
|
||||
key: (e) => e.fullPath,
|
||||
});
|
||||
let V = ref(null),
|
||||
H = ref(!0),
|
||||
U = ref(``),
|
||||
W = ref(``),
|
||||
G = ref(!1),
|
||||
K = ref(!1),
|
||||
q = ref([]),
|
||||
J = ref(!1),
|
||||
Y = ref(0);
|
||||
async function X() {
|
||||
try {
|
||||
let e = await z.get(`/ticket/${B}`);
|
||||
if (!e.ticket || !e.ticket.id) {
|
||||
U.value = `工单不存在或已删除`;
|
||||
return;
|
||||
}
|
||||
V.value = e.ticket;
|
||||
} catch (e) {
|
||||
U.value = e instanceof Error ? e.message : `加载失败`;
|
||||
} finally {
|
||||
H.value = !1;
|
||||
}
|
||||
}
|
||||
let Z = computed(() => {
|
||||
let e = V.value;
|
||||
return e
|
||||
? [
|
||||
{
|
||||
id: 0,
|
||||
content: e.content,
|
||||
attachment: e.attachment || [],
|
||||
create_time: e.create_time,
|
||||
type: `Client`,
|
||||
client_name: e.username,
|
||||
admin_name: ``,
|
||||
client_id: e.client_id,
|
||||
quote_reply_id: 0,
|
||||
quote_info: null,
|
||||
},
|
||||
...(e.replies || []).filter((e) => e.id !== 0),
|
||||
]
|
||||
.sort((e, t) => e.create_time - t.create_time)
|
||||
.map((e) => ({
|
||||
...e,
|
||||
files: ticketAttachments_n(e.attachment),
|
||||
}))
|
||||
: [];
|
||||
});
|
||||
function Q(e) {
|
||||
return e.type === `Admin`
|
||||
? e.admin_name || `客服`
|
||||
: e.client_name || `我`;
|
||||
}
|
||||
let $ = computed(() => Z.value.find((e) => e.id === Y.value));
|
||||
async function xe(e) {
|
||||
if (J.value || G.value || V.value?.status === `已关闭`) return;
|
||||
let t = e.target,
|
||||
n = Array.from(t.files ?? []);
|
||||
if (n.length) {
|
||||
((J.value = !0), (U.value = ``));
|
||||
try {
|
||||
for (let e of n) {
|
||||
let t = await z.upload(e);
|
||||
if (!t?.save_name)
|
||||
throw Error(`附件「${e.name}」上传失败,请重新选择文件`);
|
||||
q.value.push({
|
||||
save_name: t.save_name,
|
||||
name: e.name,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
U.value = e instanceof Error ? e.message : `附件上传失败`;
|
||||
} finally {
|
||||
((J.value = !1), (t.value = ``));
|
||||
}
|
||||
}
|
||||
}
|
||||
function Se(e) {
|
||||
G.value || q.value.splice(e, 1);
|
||||
}
|
||||
function Ce(e) {
|
||||
e.id > 0 && V.value?.status !== `已关闭` && (Y.value = e.id);
|
||||
}
|
||||
function we(e) {
|
||||
return Number(e.quote_info?.is_deleted) === 1
|
||||
? `该回复已删除`
|
||||
: e.quote_info?.content ||
|
||||
Z.value.find((t) => t.id === e.quote_reply_id)?.content ||
|
||||
`原回复 #${e.quote_reply_id}(内容暂不可用)`;
|
||||
}
|
||||
function Te(e) {
|
||||
let t = e.quote_info,
|
||||
n = Z.value.find((t) => t.id === e.quote_reply_id);
|
||||
return (
|
||||
t?.sender_name ||
|
||||
t?.admin_name ||
|
||||
t?.client_name ||
|
||||
(n ? Q(n) : `回复 #${e.quote_reply_id}`)
|
||||
);
|
||||
}
|
||||
function Ee(e) {
|
||||
return Number(e.quote_info?.is_deleted) === 1
|
||||
? []
|
||||
: ticketAttachments_n(
|
||||
e.quote_info?.attachment ||
|
||||
Z.value.find((t) => t.id === e.quote_reply_id)?.attachment ||
|
||||
[],
|
||||
);
|
||||
}
|
||||
async function De() {
|
||||
if (!(
|
||||
G.value ||
|
||||
!W.value.trim() ||
|
||||
J.value ||
|
||||
V.value?.status === `已关闭`
|
||||
)) {
|
||||
G.value = !0;
|
||||
try {
|
||||
(await z.post(`/ticket/${B}/reply`, {
|
||||
content: W.value.trim(),
|
||||
attachment: q.value.map((e) => e.save_name),
|
||||
quote_reply_id: Y.value,
|
||||
}),
|
||||
(W.value = ``),
|
||||
(q.value = []),
|
||||
(Y.value = 0),
|
||||
await X());
|
||||
} catch (e) {
|
||||
U.value = e instanceof Error ? e.message : `回复失败`;
|
||||
} finally {
|
||||
G.value = !1;
|
||||
}
|
||||
}
|
||||
}
|
||||
async function Oe() {
|
||||
K.value = !0;
|
||||
try {
|
||||
(await z.put(`/ticket/${B}/urge`), await X());
|
||||
} catch (e) {
|
||||
U.value = e instanceof Error ? e.message : `催单失败`;
|
||||
} finally {
|
||||
K.value = !1;
|
||||
}
|
||||
}
|
||||
async function ke() {
|
||||
K.value = !0;
|
||||
try {
|
||||
(await z.put(`/ticket/${B}/close`), await X());
|
||||
} catch (e) {
|
||||
U.value = e instanceof Error ? e.message : `关闭失败`;
|
||||
} finally {
|
||||
K.value = !1;
|
||||
}
|
||||
}
|
||||
return (
|
||||
onMounted(X),
|
||||
(n, a) => {
|
||||
let c = TicketNotice,
|
||||
m = NuxtLink,
|
||||
_ = skeleton,
|
||||
v = message,
|
||||
y = button,
|
||||
S = TicketAttachments,
|
||||
C = RichTextEditor;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, le, [
|
||||
createVNode(c),
|
||||
createElementVNode(`div`, ue, [
|
||||
createVNode(
|
||||
m,
|
||||
{
|
||||
to: `/tickets`,
|
||||
class: `back`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(a[2] ||= [
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-arrow-left`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
createTextVNode(` 返回工单列表 `, -1),
|
||||
]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
]),
|
||||
unref(H)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, de, [
|
||||
createVNode(_, {
|
||||
height: `220px`,
|
||||
}),
|
||||
]))
|
||||
: unref(U) && !unref(V)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
v,
|
||||
{
|
||||
key: 1,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(U)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: unref(V)
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
{
|
||||
key: 2,
|
||||
},
|
||||
[
|
||||
createElementVNode(`div`, fe, [
|
||||
createElementVNode(`div`, pe, [
|
||||
createElementVNode(`div`, me, [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
he,
|
||||
`#` + toDisplayString(unref(V).ticket_num),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`h2`,
|
||||
null,
|
||||
toDisplayString(unref(V).title),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
unref(V).status === `已关闭`
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createBlock(
|
||||
y,
|
||||
{
|
||||
key: 0,
|
||||
label: `关闭工单`,
|
||||
severity: `danger`,
|
||||
outlined: ``,
|
||||
size: `small`,
|
||||
loading: unref(K),
|
||||
onClick: ke,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`],
|
||||
)),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
{
|
||||
class: `status-tag`,
|
||||
style: normalizeStyle({
|
||||
color: `var(--p-text-color)`,
|
||||
borderColor: unref(V).color,
|
||||
}),
|
||||
},
|
||||
toDisplayString(unref(V).status),
|
||||
5,
|
||||
),
|
||||
]),
|
||||
createElementVNode(`div`, ge, [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
`提交时间:` +
|
||||
toDisplayString(
|
||||
(`formatTime` in n
|
||||
? n.formatTime
|
||||
: unref(dict_r))(unref(V).create_time),
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
]),
|
||||
createElementVNode(`div`, w, [
|
||||
createElementVNode(`div`, T, [
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
unref(Z),
|
||||
(t, a) => (
|
||||
openBlock(),
|
||||
createElementBlock(
|
||||
`div`,
|
||||
{
|
||||
key: `${t.id}-${a}`,
|
||||
class: normalizeClass([
|
||||
`message`,
|
||||
{
|
||||
admin: t.type === `Admin`,
|
||||
},
|
||||
]),
|
||||
},
|
||||
[
|
||||
createElementVNode(`div`, E, [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
{
|
||||
class: normalizeClass([
|
||||
`sender-avatar`,
|
||||
{
|
||||
staff: t.type === `Admin`,
|
||||
},
|
||||
]),
|
||||
},
|
||||
toDisplayString(Q(t).slice(0, 1)),
|
||||
3,
|
||||
),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
D,
|
||||
toDisplayString(Q(t)),
|
||||
1,
|
||||
),
|
||||
t.type === `Admin`
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`span`,
|
||||
O,
|
||||
`客服`,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
k,
|
||||
toDisplayString(
|
||||
(`formatTime` in n
|
||||
? n.formatTime
|
||||
: unref(dict_r))(
|
||||
t.create_time,
|
||||
),
|
||||
),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
class: `message-body`,
|
||||
innerHTML: (`sanitizeHtml` in n
|
||||
? n.sanitizeHtml
|
||||
: unref(sanitize_n))(t.content),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
A,
|
||||
),
|
||||
t.quote_reply_id
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, j, [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
`引用 ` +
|
||||
toDisplayString(Te(t)) +
|
||||
`:`,
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
innerHTML:
|
||||
(`sanitizeHtml` in n
|
||||
? n.sanitizeHtml
|
||||
: unref(sanitize_n))(
|
||||
we(t),
|
||||
),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
M,
|
||||
),
|
||||
createVNode(
|
||||
S,
|
||||
{
|
||||
files: Ee(t),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`files`],
|
||||
),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
createVNode(
|
||||
S,
|
||||
{
|
||||
files: t.files,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`files`],
|
||||
),
|
||||
t.id > 0 &&
|
||||
unref(V).status !== `已关闭`
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
y,
|
||||
{
|
||||
key: 1,
|
||||
label: `引用`,
|
||||
icon: `pi pi-reply`,
|
||||
text: ``,
|
||||
size: `small`,
|
||||
class: `quote-button`,
|
||||
onClick: (e) => Ce(t),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`onClick`],
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
],
|
||||
2,
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
]),
|
||||
createElementVNode(`div`, N, [
|
||||
unref($)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, P, [
|
||||
createElementVNode(`div`, null, [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
`引用 ` +
|
||||
toDisplayString(Q(unref($))) +
|
||||
`:`,
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`div`,
|
||||
{
|
||||
innerHTML: (`sanitizeHtml` in n
|
||||
? n.sanitizeHtml
|
||||
: unref(sanitize_n))(
|
||||
unref($).content,
|
||||
),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
F,
|
||||
),
|
||||
]),
|
||||
createVNode(y, {
|
||||
icon: `pi pi-times`,
|
||||
text: ``,
|
||||
rounded: ``,
|
||||
size: `small`,
|
||||
"aria-label": `取消引用`,
|
||||
onClick: (a[0] ||= (e) =>
|
||||
(Y.value = 0)),
|
||||
}),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
createVNode(
|
||||
C,
|
||||
{
|
||||
modelValue: unref(W),
|
||||
"onUpdate:modelValue": (a[1] ||= (e) =>
|
||||
isRef(W) ? (W.value = e) : null),
|
||||
label: `回复内容`,
|
||||
"min-height": 140,
|
||||
placeholder: `输入回复内容…`,
|
||||
disabled: unref(V).status === `已关闭`,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `disabled`],
|
||||
),
|
||||
createElementVNode(`div`, I, [
|
||||
createElementVNode(`label`, L, [
|
||||
(a[3] ||= createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-paperclip`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
(a[4] ||= createTextVNode(`添加附件`, -1)),
|
||||
createElementVNode(
|
||||
`input`,
|
||||
{
|
||||
id: `reply-files`,
|
||||
type: `file`,
|
||||
multiple: ``,
|
||||
disabled:
|
||||
unref(G) ||
|
||||
unref(J) ||
|
||||
unref(V).status === `已关闭`,
|
||||
onChange: xe,
|
||||
},
|
||||
null,
|
||||
40,
|
||||
_e,
|
||||
),
|
||||
]),
|
||||
unref(J)
|
||||
? (openBlock(),
|
||||
createElementBlock(
|
||||
`span`,
|
||||
R,
|
||||
`正在上传…`,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
unref(q).length
|
||||
? (openBlock(),
|
||||
createElementBlock(`ul`, ve, [
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
unref(q),
|
||||
(t, n) => (
|
||||
openBlock(),
|
||||
createElementBlock(
|
||||
`li`,
|
||||
{
|
||||
key: t.save_name,
|
||||
},
|
||||
[
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
toDisplayString(t.name),
|
||||
1,
|
||||
),
|
||||
createVNode(
|
||||
y,
|
||||
{
|
||||
icon: `pi pi-times`,
|
||||
text: ``,
|
||||
rounded: ``,
|
||||
size: `small`,
|
||||
"aria-label": `移除附件 ${t.name}`,
|
||||
disabled: unref(G),
|
||||
onClick: (e) => Se(n),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
`aria-label`,
|
||||
`disabled`,
|
||||
`onClick`,
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
createElementVNode(`div`, ye, [
|
||||
unref(U)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
v,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
class: `inline-error`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(
|
||||
toDisplayString(unref(U)),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, be, [
|
||||
unref(V).status === `已关闭`
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createBlock(
|
||||
y,
|
||||
{
|
||||
key: 0,
|
||||
label: `催单`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
size: `small`,
|
||||
loading: unref(K),
|
||||
onClick: Oe,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`],
|
||||
)),
|
||||
createVNode(
|
||||
y,
|
||||
{
|
||||
label: `提交回复`,
|
||||
loading: unref(G),
|
||||
disabled:
|
||||
unref(V).status === `已关闭` ||
|
||||
!unref(W).trim() ||
|
||||
unref(J),
|
||||
onClick: De,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`, `disabled`],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
64,
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-3743a20f`]],
|
||||
);
|
||||
export {};
|
||||
export default z;
|
||||
</script>
|
||||
@@ -0,0 +1,675 @@
|
||||
<script>
|
||||
import "~/assets/styles/RichTextEditor.NkmgPT5m.css";
|
||||
import "~/assets/styles/create.gX6gpD00.css";
|
||||
import { toDisplayString } from "vue";
|
||||
import { renderList } 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 { reactive } from "vue";
|
||||
import { createElementBlock } from "vue";
|
||||
import { Fragment } 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 { withModifiers } from "vue";
|
||||
import { useRouter } 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 radiobutton from "primevue/radiobutton";
|
||||
import inputtext from "primevue/inputtext";
|
||||
import { n as product_name_n } from "~/lib/product-name.js";
|
||||
import select from "primevue/select";
|
||||
import RichTextEditor from "~/components/RichTextEditor.vue";
|
||||
import TicketNotice from "~/components/TicketNotice.vue";
|
||||
import chip from "primevue/chip";
|
||||
import multiselect from "primevue/multiselect";
|
||||
var le = {
|
||||
class: `ticket-create`,
|
||||
},
|
||||
ue = {
|
||||
class: `ticket-section`,
|
||||
},
|
||||
de = {
|
||||
class: `section-fields`,
|
||||
},
|
||||
fe = {
|
||||
key: 0,
|
||||
role: `status`,
|
||||
},
|
||||
C = {
|
||||
class: `type-options`,
|
||||
},
|
||||
w = {
|
||||
class: `field`,
|
||||
},
|
||||
T = {
|
||||
key: 2,
|
||||
class: `field`,
|
||||
},
|
||||
E = {
|
||||
class: `field`,
|
||||
},
|
||||
D = {
|
||||
class: `host-opt`,
|
||||
},
|
||||
O = {
|
||||
class: `host-opt-meta`,
|
||||
},
|
||||
k = {
|
||||
class: `ticket-section`,
|
||||
},
|
||||
A = {
|
||||
class: `section-fields`,
|
||||
},
|
||||
j = {
|
||||
class: `field`,
|
||||
},
|
||||
M = {
|
||||
class: `field`,
|
||||
},
|
||||
N = {
|
||||
class: `upload-drop`,
|
||||
for: `files`,
|
||||
},
|
||||
P = [`disabled`],
|
||||
F = {
|
||||
key: 0,
|
||||
class: `files`,
|
||||
},
|
||||
I = {
|
||||
class: `fname`,
|
||||
},
|
||||
L = [`aria-label`, `disabled`, `onClick`],
|
||||
R = {
|
||||
class: `actions`,
|
||||
},
|
||||
z = _plugin_vue_export_helper_t(
|
||||
defineComponent({
|
||||
__name: `create`,
|
||||
setup(m) {
|
||||
let b = useApi(),
|
||||
z = useRouter(),
|
||||
B = ref([]),
|
||||
V = ref([]),
|
||||
H = ref([]),
|
||||
U = reactive({
|
||||
title: ``,
|
||||
ticket_type_id: null,
|
||||
admin_role_id: null,
|
||||
host_ids: [],
|
||||
content: ``,
|
||||
}),
|
||||
W = ref(!1),
|
||||
G = ref(``),
|
||||
K = ref(!1),
|
||||
q = ref(!1);
|
||||
function J(e) {
|
||||
return e.dedicate_ip || e.assign_ip || ``;
|
||||
}
|
||||
function pe(e) {
|
||||
return [`#${e.id}`, e.name, J(e)].filter(Boolean).join(` / `);
|
||||
}
|
||||
let Y = computed(() => new Map(H.value.map((e) => [e.id, e])));
|
||||
function me(e) {
|
||||
let t = Y.value.get(e);
|
||||
return t
|
||||
? `${product_name_n(t.product_name) || t.name} (#${t.id})`
|
||||
: `#${e}`;
|
||||
}
|
||||
let X = ref([]),
|
||||
Z = ref(!1);
|
||||
async function he(e) {
|
||||
if (Z.value || W.value) return;
|
||||
let t = e.target,
|
||||
n = Array.from(t.files ?? []);
|
||||
if (n.length) {
|
||||
((Z.value = !0), (G.value = ``));
|
||||
try {
|
||||
for (let e of n) {
|
||||
let t = await b.upload(e);
|
||||
if (!t?.save_name)
|
||||
throw Error(`附件「${e.name}」上传失败,请重新选择文件`);
|
||||
X.value.push({
|
||||
save_name: t.save_name,
|
||||
name: e.name,
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
G.value = e instanceof Error ? e.message : `上传失败`;
|
||||
} finally {
|
||||
((Z.value = !1), (t.value = ``));
|
||||
}
|
||||
}
|
||||
}
|
||||
function ge(e) {
|
||||
W.value || X.value.splice(e, 1);
|
||||
}
|
||||
async function Q() {
|
||||
if (!K.value) {
|
||||
((K.value = !0), (q.value = !1), (G.value = ``));
|
||||
try {
|
||||
let [e, t] = await Promise.all([
|
||||
b.get(`/ticket/type`),
|
||||
b.get(`/ticket/department`),
|
||||
]);
|
||||
((B.value = e.list ?? []), (V.value = t.list ?? []));
|
||||
try {
|
||||
let e = [],
|
||||
t = 1,
|
||||
n = 0;
|
||||
do {
|
||||
let r = await b.get(`/host`, {
|
||||
page: t,
|
||||
limit: 200,
|
||||
});
|
||||
(e.push(...(r.list ?? [])),
|
||||
(n = Number(r.count ?? e.length)),
|
||||
(t += 1));
|
||||
} while (e.length < n && t <= 100);
|
||||
H.value = e;
|
||||
} catch {
|
||||
H.value = [];
|
||||
}
|
||||
((U.ticket_type_id = B.value[0]?.id ?? null),
|
||||
(U.admin_role_id = V.value[0]?.id ?? null),
|
||||
(q.value = !0));
|
||||
} catch (e) {
|
||||
G.value =
|
||||
e instanceof Error ? e.message : `加载工单选项失败,请重试`;
|
||||
} finally {
|
||||
K.value = !1;
|
||||
}
|
||||
}
|
||||
}
|
||||
async function $() {
|
||||
if (!(W.value || Z.value || K.value || !q.value)) {
|
||||
if (((G.value = ``), !U.title.trim())) {
|
||||
G.value = `请输入工单标题`;
|
||||
return;
|
||||
}
|
||||
if (!U.content.trim()) {
|
||||
G.value = `请输入工单内容`;
|
||||
return;
|
||||
}
|
||||
W.value = !0;
|
||||
try {
|
||||
let e = await b.post(`/ticket`, {
|
||||
title: U.title.trim(),
|
||||
content: U.content.trim(),
|
||||
ticket_type_id: U.ticket_type_id,
|
||||
admin_role_id: U.admin_role_id,
|
||||
host_ids: U.host_ids,
|
||||
attachment: X.value.map((e) => e.save_name),
|
||||
});
|
||||
z.push(`/tickets/${e.id}`);
|
||||
} catch (e) {
|
||||
G.value = e instanceof Error ? e.message : `提交失败`;
|
||||
} finally {
|
||||
W.value = !1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (
|
||||
onMounted(Q),
|
||||
(n, i) => {
|
||||
let s = TicketNotice,
|
||||
c = button,
|
||||
m = radiobutton,
|
||||
_ = inputtext,
|
||||
y = select,
|
||||
b = chip,
|
||||
z = multiselect,
|
||||
J = RichTextEditor,
|
||||
Y = message,
|
||||
_e = NuxtLink;
|
||||
return (
|
||||
openBlock(),
|
||||
createElementBlock(`div`, le, [
|
||||
createVNode(s),
|
||||
(i[18] ||= createElementVNode(`h2`, null, `创建工单`, -1)),
|
||||
createElementVNode(
|
||||
`form`,
|
||||
{
|
||||
onSubmit: withModifiers($, [`prevent`]),
|
||||
},
|
||||
[
|
||||
createElementVNode(`section`, ue, [
|
||||
(i[9] ||= createElementVNode(
|
||||
`aside`,
|
||||
null,
|
||||
[
|
||||
createElementVNode(`h3`, null, `基本信息`),
|
||||
createElementVNode(
|
||||
`p`,
|
||||
null,
|
||||
`请提供一些基本信息,这有助于我们快速定位您的问题并将其转交给正确的团队处理。`,
|
||||
),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`div`, de, [
|
||||
unref(K)
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, fe, `正在加载工单选项…`))
|
||||
: unref(q)
|
||||
? createCommentVNode(``, !0)
|
||||
: (openBlock(),
|
||||
createBlock(c, {
|
||||
key: 1,
|
||||
label: `重新加载工单选项`,
|
||||
severity: `secondary`,
|
||||
outlined: ``,
|
||||
onClick: Q,
|
||||
})),
|
||||
createElementVNode(`fieldset`, C, [
|
||||
(i[5] ||= createElementVNode(
|
||||
`legend`,
|
||||
null,
|
||||
`工单类型`,
|
||||
-1,
|
||||
)),
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
unref(B),
|
||||
(t) => (
|
||||
openBlock(),
|
||||
createElementBlock(
|
||||
`label`,
|
||||
{
|
||||
key: t.id,
|
||||
},
|
||||
[
|
||||
createVNode(
|
||||
m,
|
||||
{
|
||||
modelValue: unref(U).ticket_type_id,
|
||||
"onUpdate:modelValue": (i[0] ||= (e) =>
|
||||
(unref(U).ticket_type_id = e)),
|
||||
"input-id": `ticket-type-${t.id}`,
|
||||
value: t.id,
|
||||
disabled: !unref(q),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[
|
||||
`modelValue`,
|
||||
`input-id`,
|
||||
`value`,
|
||||
`disabled`,
|
||||
],
|
||||
),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
toDisplayString(t.name),
|
||||
1,
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
]),
|
||||
createElementVNode(`div`, w, [
|
||||
(i[6] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `title`,
|
||||
},
|
||||
`工单标题`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
_,
|
||||
{
|
||||
id: `title`,
|
||||
modelValue: unref(U).title,
|
||||
"onUpdate:modelValue": (i[1] ||= (e) =>
|
||||
(unref(U).title = e)),
|
||||
placeholder: `输入工单标题`,
|
||||
maxlength: `100`,
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`],
|
||||
),
|
||||
]),
|
||||
unref(V).length > 1
|
||||
? (openBlock(),
|
||||
createElementBlock(`div`, T, [
|
||||
(i[7] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `department`,
|
||||
},
|
||||
`服务部门`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
y,
|
||||
{
|
||||
"input-id": `department`,
|
||||
modelValue: unref(U).admin_role_id,
|
||||
"onUpdate:modelValue": (i[2] ||= (e) =>
|
||||
(unref(U).admin_role_id = e)),
|
||||
options: unref(V),
|
||||
optionLabel: `name`,
|
||||
optionValue: `id`,
|
||||
disabled: !unref(q),
|
||||
fluid: ``,
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `options`, `disabled`],
|
||||
),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, E, [
|
||||
(i[8] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `ticket-hosts`,
|
||||
},
|
||||
`关联产品`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
z,
|
||||
{
|
||||
"input-id": `ticket-hosts`,
|
||||
modelValue: unref(U).host_ids,
|
||||
"onUpdate:modelValue": (i[3] ||= (e) =>
|
||||
(unref(U).host_ids = e)),
|
||||
options: unref(H),
|
||||
optionLabel: `name`,
|
||||
optionValue: `id`,
|
||||
filter: ``,
|
||||
filterFields: [
|
||||
`product_name`,
|
||||
`name`,
|
||||
`dedicate_ip`,
|
||||
`assign_ip`,
|
||||
`id`,
|
||||
],
|
||||
filterPlaceholder: `输入关键字`,
|
||||
placeholder: `选择关联产品`,
|
||||
display: `chip`,
|
||||
fluid: ``,
|
||||
},
|
||||
{
|
||||
option: withCtx(({ option: t }) => [
|
||||
createElementVNode(`div`, D, [
|
||||
createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
toDisplayString(
|
||||
unref(product_name_n)(t.product_name) ||
|
||||
t.name,
|
||||
),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
O,
|
||||
toDisplayString(pe(t)),
|
||||
1,
|
||||
),
|
||||
]),
|
||||
]),
|
||||
chip: withCtx(
|
||||
({ value: e, removeCallback: t }) => [
|
||||
createVNode(
|
||||
b,
|
||||
{
|
||||
label: me(e),
|
||||
removable: ``,
|
||||
onRemove: (n) => t(n, e),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`label`, `onRemove`],
|
||||
),
|
||||
],
|
||||
),
|
||||
_: 1,
|
||||
},
|
||||
8,
|
||||
[`modelValue`, `options`],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
createElementVNode(`section`, k, [
|
||||
(i[17] ||= createElementVNode(
|
||||
`aside`,
|
||||
null,
|
||||
[
|
||||
createElementVNode(`h3`, null, `详细信息`),
|
||||
createElementVNode(`p`, null, [
|
||||
createTextVNode(
|
||||
`请尽可能详细地描述您的问题,包括您已经尝试过的解决方案。`,
|
||||
),
|
||||
createElementVNode(`br`),
|
||||
createTextVNode(
|
||||
`如果您有相关的文件或图片,请上传它们,这将有助于我们更快地诊断问题并为您提供解决方案。`,
|
||||
),
|
||||
]),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`div`, A, [
|
||||
createElementVNode(`div`, j, [
|
||||
(i[10] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `content`,
|
||||
},
|
||||
`工单内容`,
|
||||
-1,
|
||||
)),
|
||||
createVNode(
|
||||
J,
|
||||
{
|
||||
id: `content`,
|
||||
modelValue: unref(U).content,
|
||||
"onUpdate:modelValue": (i[4] ||= (e) =>
|
||||
(unref(U).content = e)),
|
||||
label: `工单内容`,
|
||||
placeholder: `请描述问题、复现步骤和报错信息`,
|
||||
disabled: unref(W),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`modelValue`, `disabled`],
|
||||
),
|
||||
]),
|
||||
createElementVNode(`div`, M, [
|
||||
(i[15] ||= createElementVNode(
|
||||
`label`,
|
||||
{
|
||||
for: `files`,
|
||||
},
|
||||
`附件`,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(`label`, N, [
|
||||
(i[11] ||= createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-upload`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
(i[12] ||= createElementVNode(
|
||||
`span`,
|
||||
null,
|
||||
[
|
||||
createElementVNode(`b`, null, `点击此处`),
|
||||
createTextVNode(`上传相关文件`),
|
||||
],
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`small`,
|
||||
null,
|
||||
toDisplayString(
|
||||
unref(Z)
|
||||
? `正在上传,请稍候…`
|
||||
: `支持多选;上传完成后再提交工单`,
|
||||
),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`input`,
|
||||
{
|
||||
id: `files`,
|
||||
type: `file`,
|
||||
multiple: ``,
|
||||
disabled: unref(Z) || unref(W),
|
||||
onChange: he,
|
||||
},
|
||||
null,
|
||||
40,
|
||||
P,
|
||||
),
|
||||
]),
|
||||
unref(X).length
|
||||
? (openBlock(),
|
||||
createElementBlock(`ul`, F, [
|
||||
(openBlock(!0),
|
||||
createElementBlock(
|
||||
Fragment,
|
||||
null,
|
||||
renderList(
|
||||
unref(X),
|
||||
(t, n) => (
|
||||
openBlock(),
|
||||
createElementBlock(
|
||||
`li`,
|
||||
{
|
||||
key: t.save_name,
|
||||
},
|
||||
[
|
||||
(i[14] ||= createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-paperclip`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
)),
|
||||
createElementVNode(
|
||||
`span`,
|
||||
I,
|
||||
toDisplayString(t.name),
|
||||
1,
|
||||
),
|
||||
createElementVNode(
|
||||
`button`,
|
||||
{
|
||||
type: `button`,
|
||||
class: `rm`,
|
||||
"aria-label": `移除附件 ${t.name}`,
|
||||
disabled: unref(W),
|
||||
onClick: (e) => ge(n),
|
||||
},
|
||||
[
|
||||
...(i[13] ||= [
|
||||
createElementVNode(
|
||||
`i`,
|
||||
{
|
||||
class: `pi pi-times`,
|
||||
},
|
||||
null,
|
||||
-1,
|
||||
),
|
||||
]),
|
||||
],
|
||||
8,
|
||||
L,
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
128,
|
||||
)),
|
||||
]))
|
||||
: createCommentVNode(``, !0),
|
||||
]),
|
||||
unref(G)
|
||||
? (openBlock(),
|
||||
createBlock(
|
||||
Y,
|
||||
{
|
||||
key: 0,
|
||||
severity: `error`,
|
||||
closable: !1,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
createTextVNode(toDisplayString(unref(G)), 1),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
))
|
||||
: createCommentVNode(``, !0),
|
||||
createElementVNode(`div`, R, [
|
||||
createVNode(
|
||||
_e,
|
||||
{
|
||||
to: `/tickets`,
|
||||
class: `cancel-link`,
|
||||
},
|
||||
{
|
||||
default: withCtx(() => [
|
||||
...(i[16] ||= [createTextVNode(`取消`, -1)]),
|
||||
]),
|
||||
_: 1,
|
||||
},
|
||||
),
|
||||
createVNode(
|
||||
c,
|
||||
{
|
||||
type: `submit`,
|
||||
label: `创建工单`,
|
||||
loading: unref(W),
|
||||
disabled: unref(Z) || unref(K) || !unref(q),
|
||||
},
|
||||
null,
|
||||
8,
|
||||
[`loading`, `disabled`],
|
||||
),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
32,
|
||||
),
|
||||
])
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
}),
|
||||
[[`__scopeId`, `data-v-710c7c49`]],
|
||||
);
|
||||
export {};
|
||||
export default z;
|
||||
</script>
|
||||
@@ -0,0 +1,623 @@
|
||||
<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 ?? ``,
|
||||
}),
|
||||
});
|
||||
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, {
|
||||
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, {
|
||||
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>
|
||||
@@ -0,0 +1,17 @@
|
||||
<script>
|
||||
import "~/assets/styles/TicketAttachments.DtbJGLkE.css";
|
||||
import "~/assets/styles/RichTextEditor.NkmgPT5m.css";
|
||||
import "~/assets/styles/_id_.C-0--Lx-.css";
|
||||
import { createBlock } from "vue";
|
||||
import { defineComponent } from "vue";
|
||||
import { openBlock } from "vue";
|
||||
import _id_ from "~/pages/tickets/[id].vue";
|
||||
var i = defineComponent({
|
||||
__name: `ticket`,
|
||||
setup(t) {
|
||||
return (t, i) => (openBlock(), createBlock(_id_));
|
||||
},
|
||||
});
|
||||
export {};
|
||||
export default i;
|
||||
</script>
|
||||
Reference in new issue
Block a user