You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
shop-admin/src/views/im/waiter/index.vue

226 lines
7.6 KiB

<template>
<div class="list-container">
<table-list
v-loading="loading"
:code="code"
:config="config"
:data="list"
:operation="['search']"
:reset="handleReset"
title="客服"
:total="total"
@create="handleCreate()"
@remove="handleRemove"
@search="handleSearch"
>
<template #search>
<el-form inline>
<el-form-item label="所属店铺" prop="storeId">
<el-select
v-model="state.condition.storeId"
:config="{ label: 'name', value: 'id' }"
:opts="opts.store"
/>
</el-form-item>
<el-form-item label="客服ID" prop="waiterId">
<el-input v-model="state.condition.waiterId" />
</el-form-item>
<el-form-item label="客服昵称" prop="waiterNickname">
<el-input v-model="state.condition.waiterNickname" />
</el-form-item>
</el-form>
</template>
</table-list>
<el-dialog v-model="formState.formVisible" :title="formState.form.id ? '编辑' : '添加' + '客服'" width="480px">
<el-form
ref="refsForm"
v-loading="formState.submitting"
label-width="100px"
:model="formState.form"
:rules="formState.rules"
>
<el-form-item label="所属店铺" prop="storeId">
<el-select
v-model="formState.form.storeId"
:config="{ label: 'name', value: 'id' }"
:disabled="formState.form.id"
:opts="opts.store"
/>
</el-form-item>
<el-form-item label="客服类型" prop="type">
<el-input v-model="formState.form.type" maxlength="20" />
</el-form-item>
<el-form-item label="客服头像" prop="waiterAvatar">
<el-upload-image v-model="formState.form.waiterAvatar" config-id="im/" />
</el-form-item>
<el-form-item label="客服ID" prop="waiterId">
<el-input v-model="formState.form.waiterId" :disabled="!!formState.form.id" maxlength="20" />
</el-form-item>
<el-form-item label="客服昵称" prop="waiterNickname">
<el-input v-model="formState.form.waiterNickname" maxlength="20" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="formState.formVisible = false">取消</el-button>
<el-button :loading="formState.submitting" type="primary" @click="handleSave">保存</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup lang="jsx">
import ElImage from '@/components/extra/ElImage.vue';
const store = useStore();
const route = useRoute();
const { proxy } = getCurrentInstance();
const loading = ref(false);
const code = computed(() => store.state.imWaiter.code);
const list = computed(() => store.state.imWaiter.list);
const total = computed(() => store.state.imWaiter.total);
const opts = computed(() => store.state.imWaiter.opts);
if (!unref(opts).init) {
store.dispatch('imWaiter/load');
}
const state = reactive({
condition: {
storeId: null,
waiterId: null,
waiterNickname: null,
},
});
const handleReset = () => {
state.condition = {
storeId: unref(opts).store?.[0]?.id,
waiterId: null,
waiterNickname: null,
};
};
const handleSearch = async () => {
if (state.condition.storeId) {
loading.value = true;
await store.dispatch('imWaiter/search');
loading.value = false;
} else {
store.commit('imWaiter/setList', []);
store.commit('imWaiter/setTotal', 0);
}
};
watch(
() => unref(opts).store,
(value) => {
if (!state.condition.storeId) {
state.condition.storeId = value[0]?.id;
}
}
);
watch(
() => state.condition,
(value) => {
store.commit('imWaiter/setCondition', _.cloneDeep(value));
},
{ immediate: true, deep: true }
);
watch(
() => state.condition.storeId,
() => {
handleSearch();
}
);
onActivated(() => {
let storeId = route.query.storeId;
if (storeId) {
state.condition.storeId = +storeId;
} else {
handleSearch();
}
});
/* 表单 */
const refsForm = ref(null);
const formState = reactive({
formVisible: false,
submitting: false,
form: {
id: null,
storeId: null,
type: null,
waiterAvatar: null,
waiterId: null,
waiterNickname: null,
},
rules: {
storeId: [{ required: true, message: '所属店铺不能为空' }],
type: [{ required: true, message: '客服类型不能为空' }],
waiterAvatar: [{ required: true, message: '客服头像不能为空' }],
waiterId: [{ required: true, message: '客服ID不能为空' }],
waiterNickname: [{ required: true, message: '客服昵称不能为空' }],
},
});
// 添加/编辑
const handleCreate = (row) => {
Object.assign(
formState.form,
row || {
id: null,
storeId: null,
type: null,
waiterAvatar: null,
waiterId: null,
waiterNickname: null,
}
);
if (!formState.form.storeId) {
formState.form.storeId = state.condition.storeId;
}
formState.formVisible = true;
};
// 保存
const handleSave = async () => {
formState.submitting = true;
try {
await proxy.$validate(refsForm);
let data = _.cloneDeep(formState.form);
await store.dispatch('imWaiter/save', data);
formState.formVisible = false;
} catch (e) {
console.info('取消保存', e);
}
formState.submitting = false;
};
const handleRemove = async (rows) => {
store.dispatch('imWaiter/remove', {
storeId: state.condition.storeId,
waiterIds: rows.map((item) => item.waiterId),
});
};
const config = reactive({
// 表格列配置
columns: [
{
label: '所属店铺',
width: 160,
slots: {
default: ({ row }) => proxy.$dict(unref(opts).store, row.storeId, { label: 'name', value: 'id' }),
},
},
{
label: '客服头像',
width: 160,
slots: {
default: ({ row }) => <ElImage src={row.waiterAvatar} alt={row.waiterNickname} />,
},
},
{
label: '客服ID',
prop: 'waiterId',
},
{
label: '客服昵称',
prop: 'waiterNickname',
},
],
});
</script>
<style lang="less" scoped></style>